/***************************************************************************
 *                                                                         *
 *   BBSRPT.C                                                              *
 *                                                                         *
 *   Copyright (c) 1992-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   Offline Report Utility.                                               *
 *                                                                         *
 *                                                     E. Bush  2/7/92     *
 *                                                     R. Skurnick         *
 ***************************************************************************/

#include "gcomm.h"
#include "bbsrpt.h"
#include "majorbbs.h"
#include "gme.h"
#include "gmeutl.h"
#include "gmeloc.h"
#include "gmeoff.h"
#include "protstuf.h"
#include "excphand.h"
#include "wgsuext.h"
#define NMQSTS        10           // max number of additional sign-up questions
#define ANSSIZ        80           // answer size  

#define FILREV "$Revision: 15 $"

static VOID prtsp(CHAR *stg,...);

INT state;                         /* current state of program             */
INT substate=1;                    /* current substate of program          */
INT datval=0;                      /* return code of getdate routine       */
INT redir=0;                       /* is output specified to goto other out*/
INT pagbrk=0;                      /* page break location   0=nobreak      */
INT line=-1;                       /* line counter for output              */

CHAR curpos;                       /* current postion in menu              */

INT auddone=0,                     /* end of program variable              */
    printer=0,                     /* Printing it out?                     */
    found,                         /* Did the scan find one yet?           */
    stop,                          /* Should we stop now?                  */
    form,                          /* Count on form feed                   */
    state,                         /* State switch variable                */
    credit,                        /* Count credits?                       */
    fward,                         /* Forward or backward search           */
    wchmnu,                        /* Return to which menu 0=main 1=user   */
    casesn,                        /* Is this a case sensative search?     */
    cntlin;                        /* count the number of lines used on scr*/

CHAR date1[DATESIZ],               /* date fields for use                  */
     retdat[DATESIZ];              /* buffer for getdat() return           */

CHAR repchr[2],                    /* response character with '\0'         */
       yorn[4],                    /* yes or no repsonce with '\0'         */
     forwrd[10];                   /* foward or backwards holding location */

CHAR unam[120],                    /* user id field holding structure      */
     uad1[120],                    /* user id field holding structure      */
     uad2[120],                    /* user id field holding structure      */
     uad3[120];                    /* user id field holding structure      */

CHAR inpnam[15],                   /* input file name storage location     */
     outnam[15];                   /* name of where to put output          */

CHAR c;                            /* Random Character Holder              */

CHAR datone[DATESIZ],              /* Date holder for 01/02/1980 form      */
     datnone[DATESIZ],             /* Date holder for 19800102 form        */
     dattwo[DATESIZ],              /* date holder for 01/02/1980 form      */
     datntwo[DATESIZ],             /* date holder for 19800102 form        */
     name[NAMESIZ],                /* Output file name                     */
     search[SCHSTG],               /* Random String Search Character array */
     srcstg[STGSIZ],               /* Search String                        */
     uid[UIDSIZ],                  /* current User-ID we're working with   */
     search1[STGSIZ],              /* String to search for #1              */
     search2[STGSIZ],              /* String to search for #2              */
     search3[STGSIZ];              /* Comment String                       */

CHAR *keytmp;                      /* buffer for loading in the key data   */

VOID *scrsav1,                     /* screen save locations                */
     *scrsav2,                     /* screen save locations                */
     *scrsav3;                     /* screen save locations                */


FILE *outf;                        /* file pointer for output              */

CHAR chkkey[KEYSIZ+1];             /* hold key name for Sysop access to For*/
GBOOL gmeup=FALSE;                 /* has the GME been initialized?        */
struct qscfg *qsptr;               /* user quickscan record pointer        */

DFAFILE *bfp,                      /* btrieve file pointer                 */
        *bfp2,                     /* btrieve file pointer                 */
        *accbb,                    /* user account btrieve file ptr        */
        *keybb;                    /* user keys btrieve file ptr           */


LONG credits;                      /* Credits scanned on auditrail         */

static                             /* report header for sig access levels  */
CHAR *rpthdr={
"\
Legend of Forums and Default Levels\n\
-----------------------------------\n\n\
  No.        Name        Non Priv    Priv    Max Non Priv  Privileged Key\n\
 -----  ---------------  --------  --------  ------------  --------------\n"
};

static                             /* report header for remote access repor*/
CHAR *remhdr={
"\
Legend of Remote Options and Flags\n\
----------------------------------\n\n\
HASMST - Has Master Key to System\n\
SUSPEN - Account has been suspended\n\
UNDAXS - Account can not be deleted\n\n\
 Option        Description of Access\n\
--------  -------------------------------\n"
};

struct usracc uacct;                /* user account structure               */

struct acclass acctcls;            /* class structure                      */

struct usracc *usaptr;             /* ptr to current user's usracc entry   */

static
CHAR *lvls[]={"Zero","","Read","","D/L","","Write","","U/L","",
              "Coop","","Forum-Op","","Sysop","Default"
};

static
struct valop {
     CHAR *opname;
     INT op;
} valops[]={
     {"SENDALL", 11},
     {"SEND",    12},
     {"LOGON",   13},
     {"DETAIL",  22},
     {"AUDIT",   23},
     {"USERS",   24},
     {"SEARCH",  25},
     {"HANGUP",  31},
     {"SUSPEND", 32},
     {"PROTECT", 33},
     {"DELETE",  34},
     {"SHUTDOWN",35},
     {"CLEANUP", 36},
     {"SYSTATS", 41},
     {"MODSTATS",42},
     {"DEMSTATS",43},
     {"CLSSTATS",44},
     {"EMULATE", 51},
     {"MONITOR", 52},
     {"INPUT",   53},
     {"CHANGE",  54},
     {"TYPE",    61},
     {"COPY",    62},
     {"RENAME",  63},
     {"DIR",     64},
     {"MD",      65},
     {"RD",      66},
     {"DEL",     67},
     {"ACCOUNT", 71},
     {"TRANSFER",73}
};

struct option {                    /* Data on each menu option             */
     CHAR stroke;                  /* keystroke to invoke                  */
     INT x,y;                      /* position on screen of menu option    */
     CHAR u,d,l,r;                 /* connects for arrow keys              */
     CHAR *title;                  /* name of option                       */
} options[] = {
     {'0',30,17,'4','0','4','8',"Return to Utility Menu"},
     {'1', 8, 5,'1','2','1','5',"Audit Trail Search Utility"},
     {'2', 8, 8,'1','3','2','6',"Type User Account Labels"},
     {'3', 8,11,'2','4','3','7',"Type User Account Database"},
     {'4', 8,14,'3','0','4','8',"Forum Quickscan Report"},
     {'5',46, 5,'5','6','1','5',"Forum Access Report"},
     {'6',46, 8,'5','7','2','6',"User Key Report"},
     {'7',46,11,'6','8','3','7',"Remote Access Report"},
     {'8',46,14,'7','0','4','8',"User Classes Report"},
};

INT helpx=5,helpy=21;              /* location of help box in main screen  */

CHAR *help[9][2]={                 /* help messages for each option        */
     {"                    Return to Utility Menu.",
      ""},
     {"  Search Audit Trail for specific information and report findings to",
      "                       printer, screen, or file."},
     {"        Dump the user account database into 6-line ASCII labels.",
      ""},
     {"                Dump the entire user account database.",
      ""},
     {"            Report on user quickscan lists, indexed by Forum.",
      ""},
     {"              Report on non-default access levels to Forums,",
      "                           indexed by User-ID."},
     {"               Report detailing \"keys\" held by each User-ID.",
      ""},
     {"    Report all User-IDs having any access to the Remote System Menu",
      "             and the options that each such user can access."},
     {"               Dump a list of all classes within the system.",
      ""},
};

struct option *cursor=options+1;   /* options cursor                       */

DFAFILE *genbb;                    /* generic user data file btrieve file p*/

extern CHAR scntbl[][GVIDSCNSIZ];

INT
main(                              /* start of main line code              */
INT argc,
CHAR *argv[])
{
TRY
     INT i;

     (VOID)argc;
#ifdef GCWINNT
     if (!canRunUtil()) {
          MessageBox(NULL,NOPROCEED,
                    argv[0],MB_ICONSTOP|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
          return(1);
     }
#else
     (VOID)argv;
#endif // GCWINNT
     protinit("WGSRPT ");
     initvid();
     if (setjmp(disaster)) {
          clsvid();
          return(1);
     }
     outf=stdout;
     scrsav1=alcmem(GVIDSCNSIZ);
     scrsav2=alcmem(GVIDSCNSIZ);
     scrsav3=alcmem(GVIDSCNSIZ);
     keytmp=alcmem(RINGSZ);
     monorcol();
     for (i=0 ; i < NUMSCN ; i++ ) {
          cvtscn(scntbl[i]);
     }
     state=MNMENU;
     curpos='1';
     while (state != ENDPRG) {
          mem2scn(scntbl[6],0,GVIDSCNSIZ);
          newpos(curpos,(curpos-'0'));
          switch(state) {
          case MNMENU:
               mnmenu();
               break;
          case ACCLBL:
               acclbl();
               break;
          case ACCUSR:
               accusr();
               break;
          case FORACS:
               foracs();
               break;
          case LOKNKY:
               loknky();
               break;
          case REMACS:
               remacs();
               break;
          case USRCLS:
               usrcls();
               break;
          case FORQSC:
               forqsc();
               break;
          case AUDSCN:
               audscn();
               break;
          }
     }
     endprg();
     return(0);
EXCEPT
#ifdef GCWINNT
     return(1);
#endif // GCWINNT
}

static
VOID
mnmenu(VOID)                       /* main menu keyhit handling routine    */
{
     GBOOL visCursor=FALSE;
     INT c;          /* 01234567890123--6789*//* where you're starting from  */
     static CHAR fwd[]="12345678001234567800";/* where to go after PgDn,etc. */
     static CHAR rev[]="80123456788012345678";/* where to go after PgUp,etc. */

     cursiz(GVIDNOCURS);
     c=getchc();
     if (c == '\r') {
          c=cursor->stroke;
     }
     switch (c) {
     case '1':
     case F1:
          newpos('1',1);
          state=AUDSCN;
          substate=AUDPRTMNU;
          visCursor=TRUE;
          break;
     case F2:
     case '2':
          newpos('2',1);
          state=ACCLBL;
          visCursor=TRUE;
          break;
     case '3':
     case F3:
          newpos('3',1);
          state=ACCUSR;
          visCursor=TRUE;
          break;
     case '4':
     case F4:
          newpos('4',1);
          state=FORQSC;
          visCursor=TRUE;
          break;
     case '5':
     case F5:
          newpos('5',1);
          state=FORACS;
          visCursor=TRUE;
          break;
     case '6':
     case F6:
          newpos('6',1);
          state=LOKNKY;
          visCursor=TRUE;
          break;
     case '7':
     case F7:
          newpos('7',1);
          state=REMACS;
          visCursor=TRUE;
          break;
     case '8':
     case F8:
          newpos('8',1);
          state=USRCLS;
          visCursor=TRUE;
          break;
     case ESC:
     case '0':
     case F10:
          newpos('0',1);
          state=ENDPRG;
          visCursor=TRUE;
          break;
     case CRSRUP:
          newpos(cursor->u,1);
          break;
     case CRSRDN:
          newpos(cursor->d,1);
          break;
     case CRSRLF:
          newpos(cursor->l,1);
          break;
     case CRSRRT:
          newpos(cursor->r,1);
          break;
     case ' ':
     case '\t':
     case PGDN:
     case END:
          newpos(fwd[cursor->stroke-'0'],1);
          break;
     case '\b':
     case BAKTAB:
     case PGUP:
     case HOME:
          newpos(rev[cursor->stroke-'0'],1);
          break;
     }
     if (visCursor) {
          cursiz(GVIDLILCURS);
     }
}

static VOID
endprg(VOID)                       /* end the program                      */
{
     closgme();
     cursact(1);
     locate(0,24);
     clsvid();
}

static
VOID
acclbl(VOID)                       /* account label dump main line         */
{
     INT chkdon=0;
     INT ziponl;
     INT strdat=0;
     USHORT dateStart;

     locate(0,25);
     cursact(0);
     if (cancel()) {
          return;
     }
     cursact(1);
     explodeto(scntbl[1],0,4,39,7,12,5);
     strcpy(yorn,"No");
     do {
          if (!edtval(25,7,sizeof(yorn),yorn,validyn,0)) {
               state=MNMENU;
               return;
          }
     } while (yorn[0] == '\0');
     strcpy(date1,"01/01/1980");
     if (yorn[0] == 'Y') {
          strdat=1;
          explodeto(scntbl[1],0,8,39,11,17,8);
          locate(34,10);
          setatr(0x0f);
          printf("  /  /    ");
          locate(34,10);
          while (!chkdon) {
               switch (getdat()) {
               case -2:
                    state=MNMENU;
                    return;
               case -1:
                    scn2mem(scrsav2,0,GVIDSCNSIZ);
                    locate(0,25);
                    explodeto(scntbl[0],0,17,37,22,19,7);
                    getchc();
                    mem2scn(scrsav2,0,GVIDSCNSIZ);
                    locate(34,10);
                    setatr(0x0f);
                    printf("  /  /    ");
                    locate(34,10);
                    break;
               case 0:
                    locate(34,10);
                    setatr(0x2f);
                    printf("01/01/1980");
                    strcpy(date1,"01/01/1980");
                    chkdon=1;
                    break;
               case 1:
                    locate (34,10);
                    setatr(0x2f);
                    printf("%s",retdat);
                    strcpy(date1,retdat);
                    chkdon=1;
                    break;
               }
          }
     }
     strcpy(repchr,"1");
     if (strdat) {
          explodeto(scntbl[1],0,0,39,3,22,11);
     }
     else {
          explodeto(scntbl[1],0,0,39,3,17,8);
     }
     strcpy(yorn,"No");
     do {
          if (strdat) {
               if (!edtval(35,13,sizeof(yorn),yorn,validyn,0)) {
                    state=MNMENU;
                    return;
               }
          }
          else {
               if (!edtval(30,10,sizeof(yorn),yorn,validyn,0)) {
                    state=MNMENU;
                    return;
               }
          }
     } while (yorn[0] == '\0');
     if (yorn[0] == 'Y') {
          ziponl=1;
     }
     else {
          ziponl=0;
     }
     explode(scntbl[4],0,0,79,24);
     setatr(0x1f);
     prtcen(1,"Type User Account Labels");
     bfp=dfaOpen("wgsusr2.dat",sizeof(struct usracc),NULL);
     dfaSetBlk(bfp);
     if (!dfaQueryLO(0)) {
          catastro("User account file is empty!");
     }
     setatr(0x1f);
     setwin(0L,2,3,76,22,1);
     cursact(0);
     locate(2,3);
     if (redir) {
          printf("Now outputting report to \"%s\"\n",inpnam);
     }
     dateStart=dcdate(date1);
     do {
          dfaAbsRec(&uacct,0);
          if (uacct.credat >= dateStart) {
               refmt(uacct.usrnam,unam);
               refmt(uacct.usrad1,uad1);
               refmt(uacct.usrad2,uad2);
               refmt(uacct.usrad3,uad3);
               if (cisazp(uad3) || !ziponl) {
                    if (pagbrk > 0 && (line+=6) >= pagbrk) {
                         if (finup() == ESC) {
                              break;
                         }
                         line=0;
                    }
                    if (alblank(uad1)) {
                         prtsp("%-40s%s\n%s\n%s\n\n\n\n",unam,
                              uacct.userid,
                              uad2,uad3);
                    }
                    else {
                         prtsp("%-40s%s\n%s\n%s\n%s\n\n\n",unam,
                              uacct.userid,
                              uad1,
                              uad2,uad3);
                    }
               }
          }
     } while (dfaQueryNX());
     dfaClose(bfp);
     fclose(outf);
     endrpt();
}

static GBOOL
myvalid(                           /* validate 1, 2, or 3 for edtval() call*/
INT c,                                  /* integer value of character      */
CHAR *stg)                              /* string being filled in          */
{
     switch(c) {
     case '1':
          strcpy(stg,"1");
          break;
     case '2':
          strcpy(stg,"2");
          break;
     case '3':
          strcpy(stg,"3");
          break;
     default:
          return(TRUE);
     }
     return(FALSE);
}

static INT
cisazp(stg)                        /* check for a valid zip code sequence  */
CHAR *stg;                              /* string to be checked            */
{
     if (pcmtch(stg,"\5\5\5\2\2\2\2\2")) {
          if (pcmtch(stg,"\5\5\5, \2\2\2\2\2")) {
               movmem(stg+strlen(stg)-6,stg+strlen(stg)-7,7);
          }
          if (pcmtch(stg,"\5\5\5 \1\1 \2\2\2\2\2")) {
               *(stg+strlen(stg)-7)=toupper(*(stg+strlen(stg)-7));
          }
          return(1);
     }
     if (pcmtch(stg,"\5\5\5\2\2\2\2\2-\2\2\2\2")) {
          if (pcmtch(stg,"\5\5\5, \2\2\2\2\2-\2\2\2\2")) {
               movmem(stg+strlen(stg)-11,stg+strlen(stg)-12,12);
          }
          if (pcmtch(stg,"\5\5\5 \1\1 \2\2\2\2\2-\2\2\2\2")) {
               *(stg+strlen(stg)-12)=toupper(*(stg+strlen(stg)-12));
          }
          return(1);
     }
     return(0);
}

static
INT
pcmtch(input,picstg)
CHAR *input,*picstg;
{
     CHAR c,pc;
     CHAR *lanypc=NULL,*lanyin;

     while ((c=*input++) != '\0') {
          if ((pc=*picstg++) == '\5') {
               while ((pc=*(picstg+=2)) == '\5') {
                    picstg++;
               }
               while (!cmtch(c,pc)) {
                    if (c == '\0') {
                         return(0);
                    }
                    c=*input++;
               }
               lanypc=picstg-3;
               lanyin=input;
               input--;
          }
          else {
               if (!cmtch(c,pc)) {
                    if (lanypc != NULL) {
                         picstg=lanypc;
                         input=lanyin;
                    }
                    else {
                         return(0);
                    }
               }
          }
     }
     while (*picstg == '\5') {
          picstg+=3;
     }
     return(*picstg == '\0');
}

INT
cmtch(
CHAR c,
CHAR pc)
{
     switch (pc) {
     case '\1':                       /* alpha */
          return(isalpha(c));
     case '\2':                       /* numeric */
          return(isdigit(c));
     case '\3':                       /* plus-or-minus */
          return(c == '+' || c == '-' || c == ' ');
     case '\4':                       /* any-char */
          return(1);
     default:
          return(c == pc);
     }
}

INT
efflen(stg)
CHAR *stg;
{
     INT i,len;

     for (i=len=0 ; *stg != '\0' ; ) {
          i++;
          if (*stg++ != ' ') {
               len=i;
          }
     }
     return(len);
}

VOID
refmt(stg,rts)                     /* remformat with proper uppers for add */
CHAR *stg,*rts;
{
     INT alpha1,c;
     CHAR *inistg;

     inistg=stg;
     *(stg+efflen(stg))='\0';
     alpha1=1;
     for ( ; *stg != '\0' ; stg++) {
          if (isalpha(*stg) || isdigit(*stg) || *stg == '\'') {
               if (alpha1) {
                    *rts++=toupper(*stg);
                    alpha1=0;
               }
               else if (*(stg-2) == ' '
                 && ((c=toupper(*(stg-1))) == 'N' || c == 'S')
                 && ((c=toupper(*stg)) == 'E' || c == 'W')
                 && (*(stg+1) == ' ' || *(stg+1) == '\0')) {
                    *rts++=toupper(*stg);
               }
               else if (stg == inistg+1
                 && ((c=toupper(*(stg-1))) == 'P')
                 && ((c=toupper(*stg)) == 'O')
                 && ((c=toupper(*(stg+1))) == ' ' || c == 'B')) {
                    *rts++=toupper(*stg);
               }
               else {
                    *rts++=tolower(*stg);
               }
          }
          else {
               alpha1=1;
               if ((*stg == '.' || *stg == ',') && *(stg+1) != ' '
                 && *(stg+1) != ',') {
                    *rts++=*stg;
                    *rts++=' ';
               }
               else if (*stg == ' ' && (*(stg+1) == ' ' || *(stg+1) == ',')) {
                    /* do nothing */
               }
               else {
                    *rts++=*stg;
               }
          }
     }
     *rts='\0';
}

INT
alblank(stg)                       /* return 1 if all spaces in string     */
CHAR *stg;
{
     while (*stg != '\0') {
          if (*stg != ' ') {
               return(0);
          }
          stg++;
     }
     return(1);
}

VOID
accusr(VOID)                       /* User account dump main line code     */
{
     ULONG numact,numpai,numale,numfem,useavl;
     INT y,m,d;
     CHAR bdyDisp[LDATSIZ];
     DFAFILE * dfaUserExt;         // user account extension database
     struct uaccext uaccext;       // User account extension buffer
     struct {
          CHAR userid[UIDSIZ];     // User-ID
          CHAR modnam[MNMSIZ];     // Module Name ("WGSSUP - AddlQues")
          CHAR answer[NMQSTS][ANSSIZ]; // answers to questions
     } supbuf;
     INT i;

     locate(0,25);
     cursact(0);
     if (cancel()) {
          return;
     }
     explode(scntbl[4],0,0,79,24);
     setatr(0x1f);
     prtcen(1,"Type User Account Database");
     scn2mem(scrsav1,0,GVIDSCNSIZ);
     numact=numpai=numale=numfem=useavl=0L;

     dfaUserExt=dfaOpen(UACCEXTDAT,sizeof(struct uaccext),NULL);
     bfp=dfaOpen("wgsusr2.dat",sizeof(struct usracc),NULL);
     genbb=dfaOpen("wgsgen2.dat",GENSIZ,NULL);
     dfaSetBlk(bfp);
     if (!dfaQueryLO(0)) {
          catastro("User account file is empty!");
     }
     locate(2,3);
     setatr(0x1f);
     setwin(0L,2,3,76,22,1);
     if (redir) {
          printf("Now outputting report to \"%s\"\n",inpnam);
     }
     cursact(0);
     do {
          dfaAbsRec(&uacct,0);
          sDateDecode(uacct.birthd,&y,&m,&d);
          if (validDate(y,m,d)) {
               prnDate(y,m,d,bdyDisp,LDATSIZ,PRND_MDYY,'/');
          }
          else {
               stlcpy(bdyDisp,uacct.birthd,LDATSIZ);
          }
          getgen(&genbuf,uacct.userid);
          if (!redir) {
               printf("\014");
          }
          prtsp("UserID   : %-30s     Password: %-10s\n",
                uacct.userid,uacct.psword);
          prtsp("Real Name: %-30s     System Type: %d%s\n",uacct.usrnam,
                uacct.systyp,((uacct.ansifl&ANSON) ? "(A)" : "   "));
          prtsp("Address 1: %-30s     Born: %-10s  Sex: %s\n",uacct.usrad1,
                bdyDisp,(uacct.sex == 'M' ? "Male" : "Female"));
          prtsp("Address 2: %-30s     CRT: %2dx%2d\n",uacct.usrad2,
                uacct.scnwid,uacct.scnbrk);
          prtsp("Address 3: %-30s     Date Created: %s\n",uacct.usrad3,
                ncdatel(uacct.credat));
          prtsp("Address 4: %-30s     Date Last Used: %s\n",uacct.usrad4,
                ncdatel(uacct.usedat));
          prtsp("Phone Number: %-30s  Default Editor: %s\n",uacct.usrpho,
                (uacct.usrprf&PRFLIN) ? "LINE" : "FSE");
          prtsp("Language: %s\n",genbuf.lngnam[0] != '\0' ? genbuf.lngnam
                                                          : "<none selected>");
          dfaSetBlk(dfaUserExt);
          //stlcpy(uaccext.userid,uacct.userid,UIDSIZ)
          if (dfaAcqEQ(&uaccext,uacct.userid,0)) {
             prtsp("Alternate E-Mail: %s\n",uaccext.alteml);
             prtsp("Password Hint: %s\n",uaccext.pwdhint);
          }
          dfaRstBlk();
          dfaSetBlk(genbb);
          stzcpy(supbuf.userid,uacct.userid,UIDSIZ);
          stzcpy(supbuf.modnam,"WGSSUP - AddlQues",MNMSIZ);
          if (dfaAcqEQ(&supbuf,&supbuf,0)) {
             for (i=0; i < NMQSTS; i++)
                if (supbuf.answer[i][0] != '\0')
                   prtsp("ADDSUP%d: %s\n",i+1,supbuf.answer[i]);
          }
          dfaRstBlk();

          prtsp("\n");
          prtsp("Current Class (Keyring): %-16s      Days in Class: %d\n\n",
                uacct.curcls,uacct.daystt);
          prtsp("Credits Available: %8ld  Total ever: %8ld  Total Paid: "
                "%8ld\n\n",uacct.creds,uacct.totcreds,uacct.totpaid);

          numact++;
          if (uacct.totpaid != 0L) {
               numpai++;;
          }
          if (uacct.sex == 'M') {
               numale++;
          }
          else {
               numfem++;
          }
          useavl+=uacct.creds;
          if (pagbrk > 0) {
               if (finup() == ESC) {
                    break;
               }
               line=0;
          }
     } while (dfaQueryNX());
     if (pagbrk > 0) {
          printf("\014\n");
     }
     dfaClose(dfaUserExt);
     dfaClose(genbb);
     dfaClose(bfp);
     prtsp("\nTotal Accounts:  %ld\n",numact);
     prtsp("Paying Accounts: %ld\n",numpai);
     prtsp("Male Accounts:   %ld\n",numale);
     prtsp("Female Accounts: %ld\n",numfem);
     prtsp("Total Number of Credits: %ld\n",useavl);
     fclose(outf);
     endrpt();
}

VOID
foracs(VOID)                       /* forum access report main line code   */
{
     locate(0,25);
     cursact(0);
     if (cancel()) {
          return;
     }
     explode(scntbl[4],0,0,79,24);
     setatr(0x1f);
     prtcen(1,"Forum Access Report");
     scn2mem(scrsav1,0,GVIDSCNSIZ);
     initgme();
     strcpy(chkkey,msgscan("galme.msg","FORSYS"));
     accbb=dfaOpen("wgsusr2.dat",sizeof(struct usracc),NULL);
     keybb=dfaOpen("wgskey2.dat",RINGSZ,NULL);
     locate(2,3);
     setatr(0x1f);
     if (redir) {
          printf("Now outputting report to \"%s\"\n",inpnam);
     }
     setwin(0L,2,3,76,22,1);
     prtqsc();
     prtsp("\n");
     prtleg();
     shtdwn();
     endrpt();
}

VOID
prtqsc(VOID)                       /* Cycle through each user's bqscfg rec */
{
     cntlin=0;
     dfaSetBlk(qscbb);
     if (dfaQueryLO(0)) {
          do {
               dfaAbsRec(qsptr,0);
               if (!procqsc()) {
                    break;
               }
               dfaSetBlk(qscbb);
          } while (dfaQueryNX());
     }
}

INT
procqsc(VOID)                      /* Report on a users non-default access */
{
     INT i,prtuid,numprt,retlvl,anynon;
     struct fordef *fdef;

     dfaSetBlk(accbb);
     if (!dfaAcqEQ(&uacct,qsptr->userid,0)) {
          dfaSetBlk(qscbb);
          dfaGetEQ(qsptr,qsptr->userid,0);
          dfaDelete();
          return(1);
     }
     dfaRstBlk();
     anynon=0;
     prtuid=1;
     numprt=4;
     for (i=0 ; i < numforums() ; i++) {
          fdef=seqdef(i);
          if ((retlvl=rdautl(fdef->forum)) != NOTSET) {
               if (prtuid) {
                    prtdln();
                    prtsp("USER-ID: %s",qsptr->userid);
                    cntlin+=2;
                    prtuid=0;
                    anynon=1;
               }
               if (numprt == 4) {
                    prtsp("\n     ");
                    cntlin++;
                    numprt=0;
               }
               if (!redir && cntlin >= 19) {
                    if (finup() == ESC) {
                         return(0);
                    }
                    cntlin=0;
               }
               prtsp("%6u-",fdef->forum);
               prtsp("%-10s",lvls[retlvl]);
               numprt++;
          }
     }
     if (anynon) {
          prtsp("\n");
     }
     return(1);
}

VOID
prtleg(VOID)                       /* Print legend of current sig defaults */
{
     INT i;
     struct fordef *fdef;

     prtsp("%s",rpthdr);
     for (i=0 ; i < numforums() ; i++) {
          fdef=seqdef(i);
          prtsp(" %05u  %-15s  ",fdef->forum,fdef->name);
          prtsp("%-10s",lvls[(SHORT)fdef->dfnpv]);
          prtsp("%-10s",lvls[(SHORT)fdef->dfprv]);
          prtsp("%-14s",lvls[(SHORT)fdef->mxnpv]);
          prtsp("%s\n",fdef->forlok);
     }
}

VOID
prtdln(VOID)                       /* Print dash line                      */
{
     INT i;

     for (i=0 ; i < 74 ; i++) {
          prtsp("-");
     }
     prtsp("\n");
}

INT
rdautl(                            /* Read access level, curr guy          */
USHORT forum)
{
     INT i,level;
     CHAR chkcls[KEYSIZ];
     struct fmidky *fmarr;

     if (sameas(uacct.userid,"Sysop")) {
          return(SYAXES);
     }
     chkcls[0]=RINGID;
     chkcls[1]='\0';
     strcat(chkcls,uacct.curcls);
     dfaSetBlk(keybb);
     if (dfaAcqEQ(keytmp,chkcls,0) && fndakey(chkkey,&keytmp[KLSTOF])) {
          dfaRstBlk();
          return(SYAXES);
     }
     if (dfaAcqEQ(keytmp,uacct.userid,0) && fndakey(chkkey,&keytmp[KLSTOF])) {
          dfaRstBlk();
          return(SYAXES);
     }
     dfaRstBlk();
     fmarr=(struct fmidky *)qsptr->accmsg;
     level=NOTSET;
     for (i=0 ; i < qsptr->nforums ; i++) {
          if (fmarr[i].forum == forum) {
               level=acclvl(qsptr->accmsg+qsptr->nforums*sizeof(struct fmidky),
                            i);
               break;
          }
     }
     return(level);
}

INT
fndakey(lock,keylist)              /* find a key in list                   */
CHAR *lock,*keylist;
{
     CHAR *keyptr,*ptr;

     keyptr=ptr=keylist;
     while (*ptr != '\0') {
          if (*ptr == ' ') {
               *ptr='\0';
               if (sameas(lock,keyptr)) {
                    return(1);
               }
               *ptr=' ';
               keyptr=ptr+1;
          }
          ptr++;
     }
     return(0);
}

VOID
loknky(VOID)                       /* Key report main line code            */
{
     locate(0,25);
     cursact(0);
     if (cancel()) {
          return;
     }
     explode(scntbl[4],0,0,79,24);
     setatr(0x1f);
     prtcen(1,"User Key Report");
     scn2mem(scrsav1,0,GVIDSCNSIZ);
     setwin(0L,2,3,76,22,1);
     bfp=dfaOpen("wgsusr2.dat",sizeof(struct usracc),NULL);
     bfp2=dfaOpen("wgskey2.dat",RINGSZ,NULL);
     if (usaptr == NULL) {
          usaptr=(struct usracc *)alcmem(sizeof(struct usracc));
     }
     dfaSetBlk(bfp);
     if (!dfaQueryLO(0)) {
          catastro("User account file is empty!");
     }
     setatr(0x1f);
     setwin(0L,2,3,76,22,1);
     cursact(0);
     locate(2,3);
     if (redir) {
          printf("Now outputting report to \"%s\"\n",inpnam);
     }
     cntlin=0;
     do {
          dfaAbsRec(&uacct,0);
          prtsp("USER-ID: %-30s  Current Class (Keyring): %s\n",uacct.userid,
                 uacct.prmcls);
          prtsp("This user has the following special keys:\n");
          cntlin+=2;
          dspkey(uacct.userid,0);
          if (!redir && cntlin >= 16) {
               cntlin=0;
               if (finup() == ESC) {
                    break;
               }
          }
     } while (dfaQueryNX());
     dfaClose(bfp);
     dfaClose(bfp2);
     endrpt();
}

static
VOID
dspkey(                            /* display a rough list of keys in list */
CHAR *keyr,                             /* keyring name to display (or UID)*/
INT ring)                               /* is it a keyring? (0 or 1)       */
{
     INT i=0;
     CHAR *bas,*ptr,keyring[UIDSIZ];

     if (ring) {
          keyring[0]=RINGID;
          strcpy(keyring+1,keyr);
     }
     else {
          strcpy(keyring,keyr);
     }
     if (!getkey(keyring)) {
          prtsp("No special keys for this user\n\n");
          cntlin+=2;
          return;
     }
     ptr=&keytmp[KLSTOF];
     if (*ptr == '\0') {
          prtsp("No special keys for this user\n\n");
          cntlin+=2;
          return;
     }
     while (1) {
          bas=ptr;
          while (*ptr != ' ') {
               if (*ptr++ == '\0') {
                    prtsp("%-16.16s\n",bas);
                    prtsp("\n");
                    cntlin++;
                    return;
               }
          }
          *ptr='\0';
          prtsp("%-16.16s ",bas);
          *ptr++=' ';
          if (++i > 3) {      /* (4 on each line) */
               prtsp("\n");
               cntlin++;
               i=0;
          }
     }
}

static
INT
getkey(                            /* get a list of keys from BTRIEVE      */
CHAR *uid)                              /* user-id or keyring name to get  */
{
     INT acq;

     dfaSetBlk(bfp2);
     acq=dfaAcqEQ(keytmp,uid,0);
     dfaRstBlk();
     return(acq);
}

VOID
remacs(VOID)                       /* Remote sysop access report main line */
{
     locate(0,25);
     cursact(0);
     if (cancel()) {
          return;
     }
     explode(scntbl[4],0,0,79,24);
     setatr(0x1f);
     prtcen(1,"Remote Sysop Access Report");
     scn2mem(scrsav1,0,GVIDSCNSIZ);
     setwin(0L,2,3,76,22,1);
     bfp=dfaOpen("wgsusr2.dat",sizeof(struct usracc),NULL);
     if (usaptr == NULL) {
          usaptr=(struct usracc *)alcmem(sizeof(struct usracc));
     }
     locate(2,3);
     setatr(0x1f);
     prtrsy();
     prtlst();
     dfaClose(bfp);
     endrpt();
}

VOID
prtrsy(VOID)                       /* Cycle through each users usracc recor*/
{
     dfaSetBlk(bfp);
     if (dfaQueryLO(0)) {
          do {
               dfaAbsRec(usaptr,0);
               procrsy();
          } while (dfaQueryNX());
     }
}

VOID
procrsy(VOID)                      /* Report on a users if has flags or acc*/
{
     INT i,cnt=0;

     if (anyaxs() || (usaptr->flags&(HASMST|UNDAXS|SUSPEN))) {
          prtsp("USER-ID: %-30.30s     ",usaptr->userid);
          if ((usaptr->flags&HASMST) || sameas(usaptr->userid,"Sysop")) {
               prtsp("HASMST ");
          }
          if (usaptr->flags&SUSPEN) {
               prtsp("SUSPEN ");
          }
          if ((usaptr->flags&UNDAXS) || sameas(usaptr->userid,"Sysop")) {
               prtsp("UNDAXS ");
          }
          prtsp("\n");
          for (i=0 ; i < (sizeof(valops)/sizeof(struct valop)) ; i++) {
               if (axs4op(valops[i].op)) {
                    if (cnt == 6) {
                         cnt=0;
                         prtsp("\n");
                    }
                    if (cnt == 0) {
                         prtsp("     ");
                    }
                    prtsp("%-10s",valops[i].opname);
                    cnt++;
               }
          }
          prtsp("\n\n");
     }
}

VOID
prtlst(VOID)                       /* Print legend of current sig defaults */
{
     if (pagbrk) {
          if (finup() == ESC) {
               return;
          }
     }
     if (redir) {
          fprintf(outf,"%s",remhdr);
     }
     printf("%s",remhdr);
     prtsp("SENDALL   Send Message to All\n");
     prtsp("SEND      Send Message to User-ID\n");
     prtsp("LOGON     Edit server Log-on Message\n");
     prtsp("DETAIL    Detail Info on User-ID\n");
     prtsp("AUDIT     Display the Audit Trail\n");
     prtsp("USERS     Stats of Users Online\n");
     prtsp("SEARCH    Account Database Search\n");
     prtsp("HANGUP    Disconnect a User-ID\n");
     prtsp("SUSPEND   Suspend/Unsuspend a User-ID\n");
     prtsp("PROTECT   Protect/Unprotect a User-ID\n");
     if (!redir) {
          if (finup() == ESC) {
               return;
          }
     }
     prtsp("DELETE    Delete a User-ID\n");
     prtsp("SHUTDOWN  Shutdown the System\n");
     prtsp("CLEANUP   Force Cleanup or Event\n");
     prtsp("SYSTATS   View Overall Statistics\n");
     prtsp("MODSTATS  View Module Usage\n");
     prtsp("DEMSTATS  View Demographic Statistics\n");
     prtsp("CLSSTATS  View Class Statistics\n");
     prtsp("EMULATE   Emulate a channel\n");
     prtsp("MONITOR   Monitor All mode\n");
     prtsp("INPUT     Monitor Input mode\n");
     prtsp("CHANGE    Change Channel Status\n");
     prtsp("TYPE      TYPE (a file)\n");
     prtsp("COPY      COPY (a file)\n");
     prtsp("RENAME    RENAME (a file)\n");
     prtsp("DIR       DIR (directory listing)\n");
     prtsp("MD        MD (make a directory)\n");
     prtsp("RD        RD (remove a directory)\n");
     prtsp("DEL       DELETE (a file)\n");
     prtsp("ACCOUNT   Accounting Access\n");
     prtsp("TRANSFER  Transfer File Access\n\n");
}

INT
anyaxs(VOID)                       /* does user have any access at all?    */
{
     INT i;

     if (sameas(usaptr->userid,"Sysop")) {
          return(1);
     }
     for (i=0 ; i < AXSSIZ ; i++) {
          if (usaptr->access[i]&0xFFFF) {
               return(1);
          }
     }
     return(0);
}

INT
axs4op(op)                         /* does user have access to this op?    */
INT op;
{
     if (sameas(usaptr->userid,"Sysop")) {
          return(1);
     }
     return(usaptr->access[op>>4]&(1<<(op%16)));
}

VOID
usrcls(VOID)                       /* list classes main line code          */
{
     locate(0,25);
     cursact(0);
     if (cancel()) {
          return;
     }
     explode(scntbl[4],0,0,79,24);
     setatr(0x1f);
     prtcen(1,"User Classes Report");
     scn2mem(scrsav1,0,GVIDSCNSIZ);
     locate(2,3);
     setatr(0x1f);
     if (redir) {
          printf("Now outputting report to \"%s\"\n",inpnam);
     }
     setwin(0L,2,3,76,22,1);
     bfp2=dfaOpen("wgskey2.dat",RINGSZ,NULL);
     bfp=dfaOpen("wgsclas2.dat",sizeof(struct acclass),NULL);
     if (!dfaQueryLO(0)) {
          catastro("Classes Data file is empty!");
     }
     do {
          dfaAbsRec(&acctcls,0);
          if (!(acctcls.flags&HASCRD && acctcls.flags&NOCRED)) {
               if (!redir) {
                    printf("\014");
               }
               prtsp("Class Name:  %-16s\n\n",acctcls.clname);
               prtsp("Number of minutes user can spend online per call: %s\n",
               ((acctcls.limcal == -1) ? "Unlimited" :
                      spr("%d %s",acctcls.limcal,"Minutes")));
               prtsp("Number of minutes user can spend online per  day: %s\n",
               ((acctcls.limday == -1) ? "Unlimited" :
                spr("%d %s",acctcls.limday,"Minutes")));
               if (acctcls.limday != -1) {
                    prtsp("If the time limit for the day is reached, "
                 "the system will %s\n",
                 ((acctcls.flags&KCKOFF) ? "disconnect them." :
                  spr("switch them \n     to the %s class.",
                      acctcls.nxtcls[DOUTTIM])));
                    prtsp("  (Class transition message used: %s)\n",
                 (acctcls.msgs[0][0] == '\0') ? "the default." :
                 "<< Custom >>");
               }
               prtsp("Users in this class are %sexempt from credit charges.\n",
               ((acctcls.flags&CRDXMT) ? "" : "NOT "));
               prtsp("Users in this class are %sallowed to go into debt%s.\n",
               (acctcls.dbtlmt == 0 ? "NOT " : ""),
               ((acctcls.dbtlmt == 0) ? "" :
                (acctcls.dbtlmt == -1 ? " (for unlimited credits)"
                 : spr(" (for %s credits)",l2as(acctcls.dbtlmt)))));
               prtsp("%s",(acctcls.dbtlmt == 0 ? "" : fgvchk()));
               swtch();
               prtsp("\n");
               prtsp("Keys held by class (%s keyring):\n",acctcls.clname);
               dspkey(acctcls.clname,1);
               prtsp("\n");
               if (!redir) {
                    if (finup() == ESC) {
                         break;
                    }
               }
          }
     } while (dfaQueryNX());
     dfaClose(bfp);
     dfaClose(bfp2);
     endrpt();
}

VOID
swtch(VOID)                        /* list why a class would switch        */
{
     if (acctcls.flags&(NOCRED|DBTLMT|HASCRD|DAYEXP|IDLEXP)) {
          prtsp("Users in this class will switch to another class if:\n\n");
          if (acctcls.flags&NOCRED) {
               prtsp("     They run out of credits (switch to %s).\n",
                     acctcls.nxtcls[DCREDIT]);
            prtsp("       (Class transition message used: %s)\n",
               (acctcls.msgs[1][0] == '\0') ? "the default." :
               "<< Custom >>");
          }
          if (acctcls.flags&DBTLMT) {
               prtsp("     They reach their debt limit (switch to %s).\n",
                     acctcls.nxtcls[DCREDIT]);
            prtsp("       (Class transition message used: %s)\n",
               (acctcls.msgs[1][0] == '\0') ? "the default." :
               "<< Custom >>");
          }
          if (acctcls.flags&HASCRD) {
               prtsp("     They are posted credits (switch to %s).\n",
                     acctcls.nxtcls[DCREDIT]);
            prtsp("       (Class transition message used: %s)\n",
               (acctcls.msgs[1][0] == '\0') ? "the default." :
               "<< Custom >>");
          }
          if (acctcls.flags&DAYEXP) {
               prtsp("     They have been in the class for %d days "
               "(switch to %s).\n",acctcls.dftday,acctcls.nxtcls[DEXPIRE]);
          }
          if (acctcls.flags&IDLEXP) {
               prtsp("     They haven't logged on for %d days "
               "(switch to %s).\n",acctcls.idlday,acctcls.nxtcls[DLOAFER]);
          }
     }
}

CHAR *
fgvchk(VOID)                       /* when to forgive check and report     */
{
     static CHAR buf[120];
     INT used=0;

     strcpy(buf,"All debts on this account will be cleared ");
     if (acctcls.flags&MONDAY) {
          strcat(buf,"on Every Monday");
          used=1;
     }
     if (acctcls.flags&FSTMTH) {
          strcat(buf,"on the 1st of each month");
          used=1;
     }
     if (acctcls.flags&NUMDAY) {
          strcat(buf,spr("every %d days",acctcls.fgvday));
          used=1;
     }
     if (acctcls.flags&HITLMT) {
          strcat(buf,"when they hit their debt limit");
          used=1;
     }
     if (used) {
          strcat(buf,acctcls.flags&REPDBT ? " and\nwill be reported.\n"
                                          : ".\n");
     }
     else {
          strcpy(buf,"Debts will never be cleared.\n");
     }
     return(buf);
}

VOID
forqsc(VOID)                       /* Forum quickscan report main line     */
{
     locate(0,25);
     cursact(0);
     if (cancel()) {
          return;
     }
     explode(scntbl[4],0,0,79,24);
     setatr(0x1f);
     prtcen(1,"Forum Quickscan Report");
     scn2mem(scrsav1,0,GVIDSCNSIZ);
     setatr(0x1f);
     locate(2,3);
     setwin(0L,2,3,76,22,1);
     initgme();
     strcpy(chkkey,msgscan("galme.msg","FORSYS"));
     accbb=dfaOpen("wgsusr2.dat",sizeof(struct usracc),NULL);
     keybb=dfaOpen("wgskey2.dat",RINGSZ,NULL);
     cycqsc();
     shtdwn();
     endrpt();
}

VOID
cycqsc(VOID)                       /* Cycle through each SIG in sigtab     */
{
     INT i;
     unsigned forum;

     cntlin=0;
     for (i=0 ; i < numforums() ; i++) {
          forum=seqdef(i)->forum;
          prtshdr(forum);
          if (!prcusrs(forum)) {
               return;
          }
     }
}

INT
prcusrs(                           /* report on Forum and its q-scanners   */
USHORT forum)                      /*  (and others with non-default access)*/
{
     INT i,retlvl;
     CHAR dspusr[80];
     struct fmidky *fmarr;
     LONG himsg;

     dfaSetBlk(qscbb);
     if (dfaQueryLO(0)) {
          do {
               dfaAbsRec(qsptr,0);
               if (sameas(qsptr->userid,"Sysop")) {
                    continue;
               }
               dfaSetBlk(accbb);
               if (!dfaAcqEQ(&uacct,qsptr->userid,0)) {
                    dfaRstBlk();
                    dfaGetEQ(qsptr,qsptr->userid,0);
                    dfaDelete();
               }
               else {
                    dfaRstBlk();
                    fmarr=(struct fmidky *)qsptr->accmsg;
                    himsg=0L;
                    for (i=0 ; i < qsptr->nforums ; i++) {
                         if (fmarr[i].forum == forum) {
                              himsg=fmarr[i].msgid;
                              break;
                         }
                    }
                    if ((retlvl=rdautl(forum)) != NOTSET || himsg > 1L) {
                         setmem(dspusr,sizeof(dspusr),0);
                         sprintf(dspusr,"%-30s %c%s",qsptr->userid,
                                (himsg > 1L ? '*' : ' '),lvls[retlvl]);
                         strcat(dspusr,"\n");
                         prtsp(dspusr);
                         cntlin++;
                         if (!redir && cntlin >= 19) {
                              cntlin=0;
                              if (finup() == ESC) {
                                   return(0);
                              }
                         }
                    }
               }
               dfaSetBlk(qscbb);
          } while (dfaQueryNX());
          prtdln();
          cntlin++;
     }
     return(1);
}

VOID
prtshdr(                           /* print header info for this Forum     */
USHORT forum)
{
     struct fordef *fdef;

     fdef=getdef(forum);
     prtsp("            Forum Name: %-16s\n",fdef->name);
     prtsp("              Forum ID: %-6u\n",fdef->forum);
     prtsp(" Non-Privileged Access: %-8s\n",lvls[(SHORT)fdef->dfnpv]);
     prtsp("     Privileged Access: %-8s\n",lvls[(SHORT)fdef->dfprv]);
     prtsp("    Max Non-Privileged: %-8s\n",lvls[(SHORT)fdef->mxnpv]);
     prtsp("        Privileged Key: %-16s\n",fdef->forlok);
     prtdln();
     cntlin+=6;
}

VOID
audscn(VOID)                       /* audit trail scanner main line        */
{
     locate(0,25);
     cursact(0);
     while (!auddone) {
          switch (substate) {
               case AUDMENU:
                    audmenu();
                    break;
               case AUDUMENU:
                    audumenu();
                    break;
               case AUDPRTMNU:
                    audprtmnu();
                    break;
               case AUDPRTUMNU:
                    audprtumnu();
                    break;
               case AUDPWHERE2:
                    pwhere();
                    break;
               case AUDFOWARD:
                    foward();
                    break;
               case AUDGETDAT1:
                    auddat1();
                    break;
               case AUDGETDAT2:
                    auddat2();
                    break;
               case AUDGETUID:
                    gtuid();
                    break;
               case AUDSTRSCH:
                    strsch();
                    break;
          }
     }
     mem2scn(scntbl[6],0,GVIDSCNSIZ);
     newpos('1',1);
     auddone=0;
     state=MNMENU;
}

VOID
audmenu(VOID)                      /* handle menu choice                   */
{
     uid[0]='\0';
     casesn=1;
     redir=printer=0;
     mem2scn(scntbl[2],0,GVIDSCNSIZ);
     cursact(1);
     locate(67,19);
     substate=AUDPWHERE2;
     switch (c=toupper(getchc())) {
     case 'A':
          setscn("USER CREDIT TRANSFER","->","All Credit Transfers",1);
          break;
     case 'B':
          setscn("CREDITS POSTED","","All Credit Posts",1);
          break;
     case 'C':
          setscn("CREDITS POSTED","FREE","All FREE Credit Posts",1);
          break;
     case 'D':
          setscn("CREDITS POSTED","PAID","All PAID Credit Posts",1);
          break;
     case 'E':
          setscn("UPLOAD","","All Uploads To System",0);
          break;
     case 'F':
          setscn("DOWNLOAD","","All Downloads From System",0);
          break;
     case 'G':
          setscn("Console","","All Main Console Activity",0);
          break;
     case 'H':
          setscn("SERVER UP: V","","All SERVER-UP Entries",0);
          break;
     case 'I':
          setscn("SERVER SHUTDOWN","","All SHUTDOWN Entries",0);
          break;
     case 'J':
          setscn("Cleanup","","All Auto-Cleanup Entries",0);
          break;
     case 'K':
          setscn("USER ACCOUNT DELETED","","All User-ID Deletions",0);
          break;
     case 'L':
          setscn("USER ACCOUNT SUSPENDED","","All User-ID Suspensions",0);
          break;
     case 'M':
          setscn("USER ACCOUNT UNSUSPENDED","","All User-ID Un-suspensions",0);
          break;
     case 'N':
          setscn("NEW USER SIGNUP","","All New Sign-Ups",0);
          break;
     case 'O':
          setscn("TELECONFERENCE LINK-UP","","All \"LINKED\" Entries",0);
          break;
     case 'P':
          if (agetstr()) {
               setscn("",search,search,0);
               casesn=0;
          }
          break;
     case 'Q':
          setscn("USER ACCOUNT PROTECTED","","All User-ID Protections",0);
          break;
     case 'R':
          setscn("USER ACCOUNT UNPROTECTED","","All User-ID Un-protections",0);
          break;
     case 'S':
          setscn("","","Entire Audit Trail",0);
          break;
     case 'T':
          substate=AUDGETUID;
          break;
     case 'X':
     case ESCKEY:
          printf("\n\n");
          auddone=1;
          break;
     default:
          substate=AUDMENU;
          printf("\7");
     }
}

VOID
audumenu(VOID)                     /* handle USER menu entry               */
{
     casesn=0;
     wchmnu=1;
     mem2scn(scntbl[3],0,GVIDSCNSIZ);
     locate(36,4);
     setatr(0x1f);
     printf("%s",uid);
     cursact(1);
     locate(54,18);
     substate=AUDPWHERE2;
     switch (c=toupper(getchc())) {
     case 'A':
          strcpy(srcstg,"->");
          strcat(srcstg,uid);
          setscn("USER CREDIT TRANSFER",srcstg,spr("Credit Transfers TO %s",
                                 uid),1);
          break;
     case 'B':
          strcpy(srcstg,uid);
          strcat(srcstg,"->");
          setscn("USER CREDIT TRANSFER",srcstg,spr("Credit Transfers FROM %s",
                                 uid),1);
          break;
     case 'C':
          setscn("USER CREDIT TRANSFER",uid,spr("Credit Transfers With %s",
                              uid),1);
          break;
     case 'D':
          setscn("CREDITS POSTED",uid,spr("Credit Posts To %s",uid),1);
          break;
     case 'E':
          setscn("FREE",uid,spr("FREE Credit Posts To %s",uid),1);
          break;
     case 'F':
          setscn("PAID",uid,spr("PAID Credit Posts To %s",uid),1);
          break;
     case 'G':
          setscn("DOWNLOAD",uid,spr("Downloads To %s",uid),0);
          break;
     case 'H':
          setscn("UPLOAD",uid,spr("Uploads From %s",uid),0);
          break;
     case 'I':
          setscn("LOGON",uid,spr("Logons For %s",uid),0);
          break;
     case 'J':
          setscn("LOGOFF",uid,spr("Logoffs For %s",uid),0);
          break;
     case 'K':
          setscn(uid,"",uid,0);
          break;
     case 'X':
     case ESCKEY:
          wchmnu=0;
          substate=AUDPRTMNU;
          break;
     default:
          substate=AUDUMENU;
          printf("\7");
     }
}

VOID
auddat1(VOID)
{
     INT chkdon=0;
     INT mon=0,day=0,year=0;

     explodeto(scntbl[0],38,18,77,22,25,6);
     locate(27,7);
     printf("Enter the STARTING date for search\n");
     locate(27,8);
     printf("in the form MM/DD/YYYY, OR");
     locate(27,9);
     printf("<RETURN> for none: ");
     locate(46,9);
     setatr(0x0f);
     printf("  /  /    ");
     locate(46,9);
     while (!chkdon) {
          switch (getdat()) {
          case -2:
               substate=wchmnu == 0  ? AUDMENU : AUDUMENU;
               chkdon=1;
               break;
          case -1:
               baddat();
               break;
          case 0:
               strcpy(datnone,fward == 0 ? "99999999" : "00000000");
               strcpy(datone,"<NONE>");
               locate(46,9);
               setatr(0x2f);
               printf("<NONE>    ");
               substate=AUDGETDAT2;
               chkdon=1;
               break;
          case 1:
               locate(46,9);
               setatr(0x2f);
               printf("%s",retdat);
               strcpy(datone,retdat);
               sscanf(datone,"%d/%d/%d",&mon,&day,&year);
               sprintf(datnone,"%04d%02d%02d",year,mon,day);
               chkdon=1;
               substate=AUDGETDAT2;
               break;
          }
     }
}

VOID
auddat2(VOID)                           /* get second date for audscan     */
{
     INT chkdon=0;
     INT mon=0,day=0,year=0;
     unsigned edat,bdat;

     explodeto(scntbl[0],38,18,77,22,35,10);
     setatr(0x2f);
     locate(37,11);
     printf("Enter the ENDING date for search  ");
     locate(37,12);
     printf("in the form MM/DD/YYYY, OR");
     locate(37,13);
     printf("<RETURN> for none: ");
     locate(56,13);
     setatr(0x0f);
     printf("  /  /    ");
     locate(56,13);
     while (!chkdon) {
          switch (getdat()) {
          case -2:
               substate=wchmnu == 0  ? AUDMENU : AUDUMENU;
               chkdon=1;
               break;
          case -1:
               baddat();
               break;
          case 0:
               strcpy(datntwo,fward == 0 ? "00000000" : "99999999");
               locate(56,13);
               setatr(0x2f);
               printf("<NONE>    ");
               strcpy(dattwo,"<NONE>");
               substate=AUDSTRSCH;
               chkdon=1;
               break;
          case 1:
               locate(56,13);
               setatr(0x2f);
               printf("%s",retdat);
               strcpy(dattwo,retdat);
               sscanf(dattwo,"%d/%d/%d",&mon,&day,&year);
               sprintf(datntwo,"%04d%02d%02d",year,mon,day);
               if (!sameas(datone,"<NONE>")
                && !sameas(dattwo,"<NONE>")) {
                    bdat=(unsigned)dcdate(datone);
                    edat=(unsigned)dcdate(dattwo);
                    if ((fward && edat < bdat) || (!fward && bdat < edat)) {
                         baddat();
                    }
                    else {
                         substate=AUDSTRSCH;
                    }
               }
               else {
                    substate=AUDSTRSCH;
               }
               chkdon=1;
               break;
          }
     }
}

VOID
setscn(stg1,stg2,desc,addcrd) /* Set Search Parameters for scan            */
CHAR *stg1,*stg2,*desc;
INT addcrd;
{
     strcpy(search1,stg1);
     strcpy(search2,stg2);
     strcpy(search3,desc);
     credit=addcrd;
}

VOID
pwhere(VOID)                       /* Prompt for where to send output      */
{
     substate=(whrout() == 0 ? (wchmnu == 0 ? AUDMENU : AUDUMENU)
            : AUDFOWARD);
}

VOID
foward(VOID)                       /* Search Forward or Backward           */
{
     explodeto(scntbl[0],38,10,77,13,10,3);
     strcpy(forwrd,"Forward");
     do {
          if (!(edtval(22,5,sizeof(forwrd),forwrd,fwdchk,MCHOICE))) {
               substate=wchmnu == 0  ? AUDMENU : AUDUMENU;
               return;
          }
     } while (forwrd[0] == '\0');
     fward=forwrd[0] == 'F' ? 1 : 0;
     substate=AUDGETDAT1;
}

GBOOL
fwdchk(                            /* check routine for forward backward   */
INT c,
CHAR *stg)
{
     if (tolower(c) == 'f') {
          strcpy(stg,"Forward");
     }
     else if (tolower(c) == 'b') {
          strcpy(stg,"Backward");
     }
     else {
          if (*stg == 'F') {
               strcpy(stg,"Backward");
          }
          else {
               strcpy(stg,"Forward");
          }
     }
     return(FALSE);
}

VOID
audprtmnu(VOID)                    /* Print Main Menu                      */
{
     scblank(0,0x0f);
     explodeto(scntbl[2],0,0,79,21,0,0);
     cursact(1);
     locate(67,19);
     substate=AUDMENU;
}

VOID
audprtumnu(VOID)                   /* Print User Search Menu               */
{
     scblank(0,0x0f);
     explode(scntbl[3],0,0,79,20);
     cursact(1);
     locate(54,18);
     substate=AUDUMENU;
}

VOID
strsch(VOID)                      /* Start searching the audit trail      */
{
     HAUDFILE haud;
     ULONG nStart,nFinish,recNum,direction;
     INT c,abt;
     USHORT dosDate,dosTime;
     GBOOL noRecFlg,done;
     struct audEntry entry;
     CHAR buf[AUDRECLEN+1];

     abt=0;
     found=0;
     stop=0;
     form=0;
     credits=0L;
     locate(0,25);
     cursact(0);

     explode(scntbl[5],0,0,79,24);
     locate(30,1);
     setatr(0x1f);
     printf("\"%s\"",search3);
     if ((c=audfOpen(&haud,AUDITFILE,AUDMODE_READONLY)) < AUDERR_OK) {
          catastro("ERROR OPENNING AUDIT TRAIL (%d)",c);
     }
     setwin(0L,2,3,77,22,1);
     locate(2,3);
     setatr(0x1f);
     if (redir) {
          fprintf(outf,"\nSearching Audit Trail for \"%s\"\n",search3);
          fprintf(outf,"Searching %sWARDS ",fward ? "FOR" : "BACK");
          fprintf(outf,"Starting Date: %s Ending Date: %s \n\n",datone,dattwo);
     }
     noRecFlg=(audfNumRecs(haud) == 0);
     if (!noRecFlg) {
          audfFindEntryStr(haud,datnone,fward ? "000000" : "999999",
                           &nStart,&entry,sizeof(entry));
          entry.stamp[CSTRLEN("YYYYMMDD")]='\0';
          if (!fward) {
               if (stricmp(datnone,entry.stamp) < 0) {
                    if (nStart == 0) {
                         noRecFlg=TRUE;
                    }
                    else {
                         --nStart;
                    }
               }
          }
          audfFindEntryStr(haud,datntwo,fward ? "999999" : "000000",
                           &nFinish,&entry,sizeof(entry));
          entry.stamp[CSTRLEN("YYYYMMDD")]='\0';
          if (fward) {
               if (stricmp(datntwo,entry.stamp) < 0) {
                    if (nFinish == 0) {
                         noRecFlg=TRUE;
                    }
                    else {
                         --nFinish;
                    }
               }
          }
     }
     if (noRecFlg) {
          norecs();
          eofrpt(FALSE);
          return;
     }
     done=FALSE;
     direction=(fward ? 1 : -1);
     for (recNum=nStart ; !done ; recNum+=direction) {
          audfReadLowLevel(haud,recNum,buf,sizeof(buf));
          buf[AUDRECLEN]='\0';
          if (stgsbs(buf,search1,casesn)
           && (*search2 == '\0' || stgsbs(buf,search2,casesn))) {
               found=1;
               audfCvtRawToEntry(buf,&entry,sizeof(entry));
               sDecodeDTDOS(entry.stamp,&dosDate,&dosTime);
               prtsp("\n%s %s %-32.32s %s\n",
                     prntim(15,dosTime),prndat(20,dosDate,0),
                     entry.brief,entry.channel);
               if (redir) {
                    prtsp("     %s",entry.detail);
               }
               else {
                    if (strlen(entry.detail) > 70) {
                         strcpy(&entry.detail[69],"*");
                    }
                    prtsp("     %s",entry.detail);
               }
               stop+=2;
               form+=2;
               if (credit) {
                    credits+=scncrd(entry.detail);
               }
          }
          if (kbhit()) {
               if ((c=getchc()) == ' ' || c == CTRLS) {
                    stop=0;
                    finup2();
               }
               else {
                    abt=1;
                    prtsp("\n                          "
                          "*** REPORT ABORTED ***\n");
                    break;
               }
          }
          if (printer && form >= 54) {
               fprintf(outf,"\f\n\n\n");
               form=0;
          }
          if (!redir && stop >= 18) {
               finup2();
               stop=0;
          }
          done=(recNum == nFinish);
     }
     audfClose(haud);
     if (!found) {
          norecs();
     }
     if (found && credit) {
          printf("\n\n");
          printf("               Total amount of %s: %s",
                 search3,l2as(credits));
          printf("\n");
          if (redir) {
               fprintf(outf,"\n\nTotal amount of %s: %s\n",
                       search3,l2as(credits));
          }
     }
     eofrpt(abt);
}

VOID
eofrpt(abt)                        /* End of report printing               */
INT abt;
{
     if (!abt) {
          prtsp("\n                          *** END OF REPORT ***");
     }
     if (redir) {
          if (printer) {
               fprintf(outf,"\f");
          }
          fclose(outf);
     }
     finup2();
     substate=wchmnu == 0 ? AUDMENU : AUDUMENU;
}

VOID
norecs(VOID)                       /* No records found                     */
{
     printf("\n                           No Matching Records\n\n");
     if (redir) {
          fprintf(outf,"\n                       No Matching Records\n");
     }
}

LONG
scncrd(                            /* Scan Auditrail for Credit Amount     */
CHAR *stg)
{
     INT neg=0;
     LONG retval=0L;

     while (*stg != '\0') {
          if (*stg == '-') {
               neg=1;
               stg++;
               continue;
          }
          if (isdigit(*stg)) {
               do {
                    retval=(retval*10)+(*stg-'0');
                    stg++;
                    if (*stg == ' ' || *stg == '\0') {
                         if (neg) {
                              retval=-retval;
                         }
                         return(retval);
                    }
               } while (isdigit(*stg));
               retval=0L;
          }
          stg++;
          neg=0;
     }
     return(0L);
}

VOID
prtcen(INT y,CHAR *stg)            /* Center and print a string            */
{
     CHAR buffer[81];

     sprintf(buffer,stg);
     locate((80-strlen(buffer))/2,(y == -1) ? curcury() : y);
     printf("%s",buffer);
}

INT
finup(VOID)                        /* Press any key to continue            */
{
     INT c;

     printf("          << Press Any Key to Continue or ESC to abort >>");
     c=getchc();
     printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
            "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
            "\b\b\b\b\b\b");
     return(c);
}

VOID
finup2(VOID)                       /* Press any key to continue            */
{
     printf("\n                     << Press Any Key to Continue >>");
     getchc();
     printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
            "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
            "\b\b\b\b");
}

VOID
gtuid(VOID)                        /* get userid for scanning auditrail    */
{
     setmem(uid,UIDSIZ,0);
     scn2mem(scrsav2,0,GVIDSCNSIZ);
     explodeto(scntbl[0],38,6,79,9,19,5);
     do {
          if (!(edtval(26,7,sizeof(uid),uid,isuidc,0))) {
               substate=AUDMENU;
               return;
          }
          if (strlen(uid) < 3) {
               uid[0]='\0';
          }
     } while (uid[0] == '\0');
     mem2scn(scrsav2,0,GVIDSCNSIZ);
     strcpy(search2,uid);
     substate=AUDPRTUMNU;
}

static
INT
agetstr(VOID)                      /* get a string from the user           */
{
     explodeto(scntbl[1],40,0,78,4,19,5);
     setmem(search,SCHSTG,0);
     do {
          if (!edtval(21,8,SCHSTG,search,valsch,0)) {
               substate=AUDMENU;
               return(0);
          }
     } while (search[0] == '\0');
     return(1);
}

static GBOOL
valsch(                            /* validate string search               */
INT c)                             /*   created value from edtval          */
{
     if (c <= 255 && isprint(c)) {
          return(TRUE);
     }
     else {
          return(FALSE);
     }
}

INT
stgsbs(stg1,stg2,cas)              /* Check auditrail entry for strings    */
CHAR *stg1,*stg2;                       /* strings to search for           */
INT cas;                                /* case sensative?                 */
{
     CHAR *startp,*compare;

     startp=stg1;
     compare=stg2;
     while (*startp != '\0') {
          if (cas) {
               while (*stg1 == *stg2 && *stg1 != '\0') {
                    stg1++;
                    stg2++;
               }
          }
          else {
               while (tolower(*stg1) == tolower(*stg2) && *stg1 != '\0') {
                    stg1++;
                    stg2++;
               }
          }
          if (*stg2 == '\0') {
               return(1);
          }
          startp++;
          stg1=startp;
          stg2=compare;
     }
     return(0);
}

INT
whrout(VOID)                       /* find out where to put output         */
{
     scn2mem(scrsav3,0,GVIDSCNSIZ);
     strcpy(repchr,"1");
     explodeto(scntbl[0],0,0,37,9,19,5);
     do {
          cursact(1);
          if (!(edtval(51,13,sizeof(repchr),repchr,myvalid,0))) {
               return(0);
          }
     } while(repchr[0] == '\0');
     switch (repchr[0]) {
     case '1':
          outnam[0]='\0';
          pagbrk=19;
          line=-1;
          redir=0;
          break;
     case '2':
          pagbrk=0;
          line=-1;
          strcpy(inpnam,"PRN");
          if ((outf=fopen(inpnam,FOPWA)) == NULL) {
               scn2mem(scrsav2,0,GVIDSCNSIZ);
               explodeto(scntbl[0],38,0,75,5,19,7);
               getchc();
               mem2scn(scrsav2,0,GVIDSCNSIZ);
               inpnam[0]='\0';
          }
          redir=1;
          break;
     case '3':
          pagbrk=0;
          line=-1;
          if (getfil()) {
               strcpy(outnam,inpnam);
               redir=1;
               }
          else {
               inpnam[0]='\0';
          }
          break;
     }
     mem2scn(scrsav3,0,GVIDSCNSIZ);
     return(1);
}

INT
getfil(VOID)                       /* if out to file, get the file name    */
{
     inpnam[0]='\0';
     scn2mem(scrsav2,0,GVIDSCNSIZ);
     explodeto(scntbl[0],38,14,77,17,19,7);
     do {
          if (!edtval(44,9,sizeof(inpnam),inpnam,valfil,0)) {
               mem2scn(scrsav2,0,GVIDSCNSIZ);
               return(0);
          }
          if (!rsvnam(inpnam)) {
               if ((outf=fopen(inpnam,FOPWA)) == NULL) {
                    scn2mem(scrsav2,0,GVIDSCNSIZ);
                    explodeto(scntbl[0],0,11,37,16,19,7);
                    getchc();
                    mem2scn(scrsav2,0,GVIDSCNSIZ);
                    inpnam[0]='\0';
               }
          }
          else {
               scn2mem(scrsav2,0,GVIDSCNSIZ);
               explodeto(scntbl[0],0,11,37,16,19,7);
               getchc();
               mem2scn(scrsav2,0,GVIDSCNSIZ);
               inpnam[0]='\0';
          }
     } while (inpnam[0] == '\0');
     return(1);
}

GBOOL
valfil(                            /* validate file name                   */
INT c)
{
     if (!isprint(c)) {
          return(FALSE);
     }
     return(TRUE);
}

static
VOID
prtsp(                             /* print to proper places during output */
CHAR *stg,
...)
{
     va_list args;
     CHAR buffer[1024];

     va_start(args,stg);
     vsprintf(buffer,stg,args);
     va_end(args);
     if (redir) {
          fprintf(outf,"%s",buffer);
     }
     printf("%s",buffer);
}

VOID
draw(cleanup)                      /* draw an option on the screen         */
INT cleanup;                            /* is this a reverse option? 1=no  */
{
     locate(cursor->x-1,cursor->y);
     if (cleanup) {
          setatr(0x2f);
     }
     else {
          setatr(0x70);
     }
     printf(" %c ",cursor->stroke);
     if (cleanup) {
          setatr(0x1f);
     }
     else {
          setatr(0x70);
     }
     locate(cursor->x+4,cursor->y);
     printf(" %s ",cursor->title);
}

VOID
newpos(                            /* point to a new option                */
CHAR ch,
INT cleanup)
{
     if (cleanup) {
          draw(1);
     }
     curpos=ch;
     cursor=options+ch-'0';
     setatr(0x70);
     draw(0);
     setwin(NULL,helpx,helpy,75,23,0);
     locate(helpx,helpy);
     setatr(0x2f);
     printf(help[ch-'0'][0]);
     cleareol();
     locate(helpx,helpy+1);
     printf(help[ch-'0'][1]);
     cleareol();
     setatr(0x1f);
     rstwin();
     home();
}

INT
getdat(VOID)                        /* get date from user with validation   */
{
     INT c,i=0,isdon=0;

     do {
          switch (c=getchc()) {
          case RETKEY:
               if (i == 0) {
                    isdon=1;
                    datval=0;
               }
               else if (i == 10) {
                    if (!chkdate(retdat)) {
                         datval=-1;
                         isdon=1;
                    }
                    else {
                         retdat[i]='\0';
                         datval=1;
                         isdon=1;
                    }
               }
               else {
                     printf("\7");
               }
               break;
          case CRSRLF:
          case '\b':
               if (i == 0) {
                    printf("\7");
               }
               else {
                    retdat[i--]='\0';
                    printf("\b");
                    if (i == 2 || i == 5) {
                         retdat[i--]='\0';
                         printf("\b");
                         locate(curcurx()+1,curcury());
                         printf("/");
                         locate(curcurx()-2,curcury());
                    }
               }
               break;
          case ESCKEY:
               return(-2);
          default:
               if (!isascii(c) || !isdigit(c) || i == DATESIZ-1) {
                    printf("\7");
               }
               else {
                    retdat[i++]=c;
                    printf("%c",c);
                    if (i == 2 || i == 5) {
                         retdat[i++]='/';
                         printf("/");
                    }
               }
          }
     } while (!isdon);
     return(datval);
}


GBOOL
chkdate(                           /* check date and make sure it is valid */
CHAR *stg)
{
     static INT mths=12,ndays[]={31,28,31,30,31,30,31,31,30,31,30,31};
     INT mon=0,day=0,year=0;
     INT isleap;
     INT retval=TRUE;

     year=1980;
     if (sscanf(stg,"%d/%d/%d",&mon,&day,&year) != 3
      || sscanf(stg,"%d/%d",&mon,&day) != 2) {
          return(FALSE);
     }
     isleap=isLeapYear(year);
     if (mon < 1 || mon > mths) {
          retval=FALSE;
     }
     else if (day < 1 || (day > ndays[mon-1] && !isleap) ||
                         (day > ndays[mon-1]+1 && isleap)) {
          retval=FALSE;
     }
     return(retval);
}

INT
cancel(VOID)                       /* where should output go?              */
{
     if (!whrout()) {
          state=MNMENU;
          return(1);
     }
     cursact(1);
     locate(0,25);
     cursact(0);
     return(0);
}

VOID
baddat(VOID)                       /* display bad date msg and reprompt    */
{
     INT x,y;

     scn2mem(scrsav3,0,GVIDSCNSIZ);
     locate(0,25);
     explodeto(scntbl[0],0,17,37,22,19,7);
     getchc();
     mem2scn(scrsav3,0,GVIDSCNSIZ);
     if (substate == AUDGETDAT1) {
          x=46;
          y=9;
     }
     else {
          ASSERT(substate == AUDGETDAT2);
          x=56;
          y=13;
     }
     locate(x,y);
     setatr(0x0f);
     printf("  /  /    ");
     locate(x,y);
}

VOID
endrpt(VOID)
{
     printf("\nEnd of report.\n");
     printf("\nHit any key to continue\n");
     getchc();
     state=MNMENU;
}

VOID
shtdwn(VOID)                       /* Close all files for termination      */
{
     if (accbb != NULL) {
          dfaClose(accbb);
          accbb=NULL;
     }
     if (keybb != NULL) {
          dfaClose(keybb);
          keybb=NULL;
     }
     if (outf != NULL) {
          fclose(outf);
          outf=NULL;
     }
}

VOID
initgme(VOID)                      /* initialize the GME                   */
{
     if (!gmeup) {
          iniogme();
          qsptr=(struct qscfg *)alcmem(MAXQSR);
          gmeup=TRUE;
     }
}

VOID
closgme(VOID)                      /* close down the GME                   */
{
     if (gmeup) {
          clsogme(FALSE);
          gmeup=FALSE;
     }
}

VOID
appgprept(VOID)                    /* application-specific GP info (stub)  */
{
}

VOID
appgprecd(VOID)                    /* application-specific GP record (stub)*/
{
}
