/***************************************************************************
 *                                                                         *
 *   GMEUTL.H                                                              *
 *                                                                         *
 *   Copyright (c) 1994-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This file contains declarations for common and utility functions used *
 *   by and for the GME (from GMEUTL.C and GMEONL.C)                       *
 *                                                                         *
 *                                           - J. Alvrus   8/4/94          *
 *                                                                         *
 ***************************************************************************/

#ifndef __GMEUTL_H
#define __GMEUTL_H

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

#define GMEMDF "galme.mdf"         /* GME .MDF file name                   */
#define XINFSZ 1024                /* extended return info buffer size     */

                                   /* general-purpose GME states           */
#define START    0                 /*   starting state for all GME requests*/
#define READING  1                 /*   reading something                  */
#define WRITING  2                 /*   writing something                  */
#define SRCHING  3                 /*   searching for something            */

                                   // HACK - REORGANIZED STRUCTURE RECHECK!
struct rdctx {                     /* message reading context              */
     INT seq;                      /*   sequence in use                    */
     USHORT fid;                   /*   current forum ID                   */
     LONG mid;                     /*   current message ID                 */
     LONG tid;                     /*   current thread ID                  */
     CHAR uid[UIDSIZ];             /*   User-ID doing reading              */
};

struct qikwork {                   /* !QUICK list distribution state info  */
     INT qikctr;                   /*   index of last addr used            */
     struct qikdat *qikbuf;        /*   pointer to !QUICK list buffer      */
};

struct msswork {                   /* !MASS list distribution state info   */
     LONG fpos;                    /*   accbb file position                */
     GBOOL more;                   /*   is there another address?          */
};

struct syswork {                   /* sysop list distribution state info   */
     FILE *fp;                     /*   list file                          */
     LONG fpos;                    /*   list file position                 */
};

union diststf {                    /* dist list state info structure       */
     struct qikwork q;
     struct msswork m;
     struct syswork s;
};

struct gmework {                   /* GME per-request work area            */
     INT state1;                   /*   state of current level 1 request   */
     INT state2;                   /*   state of current level 2 request   */
     INT state3;                   /*   state of current level 3 request   */
     INT flags;                    /*   flags field                        */
     VOID (*callback)(INT,INT);    /*   callback handler for request status*/
     const CHAR *appinf;           /*   ptr to app-defined info (write)    */
     FILE *fp;                     /*   source or general use file         */
     FILE *fpout;                  /*   destination file                   */
     LONG fpos;                    /*   general use file position          */
     LONG rdfpos;                  /*   btrieve file pos of current msg    */
     LONG basechg;                 /*   base or total write-message charge */
     LONG rcpchg;                  /*   what to charge recip for autofwd   */
     LONG attsiz;                  /*   size of attachment                 */
     LONG orgmid;                  /*   original message ID                */
     LONG dstprim;                 /*   msg ID of primary distributed msg  */
     SHORT attchg;                 /*   charge for attachment              */
     SHORT apkchg;                 /*   per-k charge for attachment        */
     SHORT rrrchg;                 /*   charge for return receipt          */
     SHORT prichg;                 /*   charge for "priority"              */
     INT orgflg;                   /*   original message flags             */
     INT tmpflg;                   /*   temporary storage for flags        */
     INT counter;                  /*   general use counter                */
     INT fdfnum;                   /*   forum data file being examined     */
     INT reclen;                   /*   general use record length          */
     INT echonum;                  /*   echo number being processed        */
     INT ccidx;                    /*   current cc: list position          */
     INT curhook;                  /*   current GME hook index             */
     UINT rqid;                    /*   request ID of this work area       */
     UINT antirq;                  /*   bitwise inverse of request ID      */
     USHORT orgfor;                /*   original forum ID of message       */
     USHORT cfdate;                /*   copied file date stamp             */
     USHORT cftime;                /*   copied file time stamp             */
     CHAR dstdly;                  /*   distribution delay counter         */
     struct otscan *curscn;        /*   scan context of work area          */
     CHAR dlstnam[DLNMSZ];         /*   current dist list name             */
     CHAR auxto[UIDSIZ];           /*   auxiliary to field (for autofwd)   */
     CHAR auxhist[HSTSIZ];         /*   auxiliary history field (for dist) */
     CHAR orgatt[GCMAXPTH];        /*   original attachment path+file name */
     CHAR auxatt[GCMAXPTH];        /*   auxiliary attachment name          */
     CHAR cpyatt[GCMAXPTH];        /*   destination path when copying atts */
     struct rdctx rdctx;           /*   read context of work area          */
     union diststf d;              /*   distribution state info buffer     */
};
                                   /* work area flags                      */
#define ADROK    0x0001            /*   to address is valid & accessible   */
#define ATTOK    0x0002            /*   ok to attach a file to message     */
#define RRROK    0x0004            /*   ok to request return receipt       */
#define PRIOK    0x0008            /*   ok to send message as priority     */
#define QIKLST   0x0010            /*   message is to !QUICK dist list     */
#define MASSLST  0x0020            /*   message is to !MASS dist list      */
#define SYSLST   0x0040            /*   message is to sysop dist list      */
#define CPY2E    0x0080            /*   copy forum message to E-mail       */
#define FWDMSG   0x0100            /*   message being auto-forwarded       */
#define CYCFLG   0x0200            /*   cycle necessary or performed       */
#define NOECHO   0x0400            /*   do not echo this message           */
#define HASAPI   0x0800            /*   copy/fwded msg has app-defined info*/
#define YESECHO  0x1000            /*   force echo of imported message     */
#define PRIMDONE 0x8000            /*   finished writing "primary" message */

#define STATE_ERROR "GME level %d state corrupted in %s, state=%d"
#define state_error(n,f,s) catastro(STATE_ERROR,(n),(f),(s))

extern UINT _reclen;               /* message file record length           */
extern HMCVFILE gmemb;             /* GME CNF options file block handle    */
extern CHAR *utltxt;               /* GME utility message text buffer      */
extern struct message *utlmsg;     /* GME utility message header structure */
extern struct gmework *utlwork;    /* GME utility work area                */
extern struct fordef *utldef;      /* GME utility forum definition         */
extern CHAR *extinf;               /* extended return information buffer   */
extern UINT hirqidx;               /* highest request array index          */
extern CHAR *gmerqarr;             /* pointer to open request array        */
extern INT ngmelk;                 /* number of slots in lock array        */
extern
struct gmelock {                   /* GME lock structure                   */
     UINT rqid;                    /*   request ID associated with lock    */
     USHORT forum;                 /*   forum ID locked                    */
     LONG msgid;                   /*   message ID locked                  */
} *gmelkarr;                       /* pointer to lock array                */
extern INT numsl;                  /* number of sysop dist lists           */
extern
struct slinfo {                    /* sysop dist list info structure       */
     CHAR name[DLNMSZ];            /*   list name                          */
     CHAR key[KEYSIZ];             /*   list key                           */
     SHORT surchg;                 /*   list surcharge                     */
} *losl;                           /* array of sysop dist list info structs*/

extern INT ngmehooks;              /* number of GME hooks                  */
extern
struct gmehook {                   /* GME hook info structure              */
     INT hooktype;                 /*   hook type code                     */
     voidfunc hookfunc;            /*   hook function pointer              */
} *gmehooks;                       /* array of hook info structures        */

extern INT ngmephooks;             /* number of prioritized GME hooks      */
extern
struct gmephook {                  /* prioritized GME hook info structure  */
     voidfunc hookfunc;            /*   hook function pointer              */
     SHORT hooktype;               /*   hook type code                     */
     SHORT hookpri;                /*   hook priority                      */
} *gmephooks;                      /* array of hook info structures        */

VOID
iniutl(VOID);                      /* initialize GME utilities             */

VOID
inidft(VOID);                      /* initialize default forum/preferences */

VOID
clsutl(VOID);                      /* close GME utilities                  */

VOID
addrq(                             /* add request to list of OK requests   */
VOID *pWork);                      /*   pointer to request work area       */

VOID
remrq(                             /* remove request from OK list          */
VOID *pWork);                      /*   pointer to request work area       */

VOID
callback(                          /* call callback handler if any         */
VOID *pWork,                       /*   being used by this work area       */
INT evt,                           /*   event to report                    */
INT res,                           /*   result code to report              */
const CHAR *info);                 /*   string to put in extinf            */

GBOOL                              /*   returns TRUE if a conflict         */
gmecfl(                            /* check for any conflict               */
VOID *pWork,                       /*   work area in use                   */
USHORT forum,                      /*   forum ID w/possible conflict       */
LONG msgid);                       /*   message ID w/possible conflict     */

GBOOL                              /*   was lock successful?               */
gmelok(                            /* put a lock on a message or forum     */
VOID *pWork,                       /*   work area associated w/lock        */
USHORT forum,                      /*   forum ID to lock                   */
LONG msgid);                       /*   message ID to lock                 */

VOID
gmeulk(                            /* unlock a message or forum            */
VOID *pWork,                       /*   work area associated w/lock        */
USHORT forum,                      /*   forum ID to lock                   */
LONG msgid);                       /*   message ID to lock                 */

VOID
gmeulkr(                           /* remove all locks assoc with a request*/
VOID *pWork);                      /*   work area associated w/request     */

ULONG
cyccnt(VOID);                      /* get system cycle count               */

VOID
noticu(                            /* handle user init/close notification  */
INT hookType,                      /*   type of hook to process            */
const CHAR *userid);               /*   User-ID being initialized          */

VOID
notnwm(                            /* handle new message notification hook */
INT nwmtyp,                        /*   new message type code              */
VOID *pWork,                       /*   work area in use                   */
struct message *msg,               /*   header of new message              */
const CHAR *text);                 /*   message text                       */

INT                                /*   returns updated hook index         */
notnwml(                           /* low-level new message notification   */
INT curidx,                        /*   current hook index (NOIDX == first)*/
const struct message *msg,         /*   header of new message              */
const CHAR *text,                  /*   message text                       */
const CHAR *appinf);               /*   app-defined info ("" if none)      */

INT                                /*   returns updated hook index         */
notnwf(                            /* handle new forum notification hooks  */
INT curidx,                        /*   current hook index (NOIDX == first)*/
const struct fordsk *newdef,       /*   new forum definition structure     */
const CHAR *desc,                  /*   descriptive text                   */
const CHAR *echoes);               /*   pointer to array of echo addresses */

INT                                /*   returns updated hook index         */
notnwg(                            /* handle new group notification hooks  */
INT curidx,                        /*   current hook index (NOIDX == first)*/
const struct forgrp *grpbuf);      /*   new forum group structure          */

VOID
notudm(                            /* handle message update notification   */
INT updtyp,                        /*   update type code                   */
VOID *pWork,                       /*   work area in use                   */
const struct message *msg,         /*   header of new message              */
const CHAR *text);                 /*   message text                       */

INT                                /*   returns updated hook index         */
notmdf(                            /* handle forum update notification     */
INT curidx,                        /*   current hook index (NOIDX == first)*/
const struct fordef *def,          /*   forum definition structure         */
const CHAR *desc,                  /*   descriptive text                   */
const CHAR *echoes);               /*   pointer to array of echo addresses */

INT                                /*   returns updated hook index         */
notmodg(                           /* handle group modify notification     */
INT curidx,                        /*   current hook index (NOIDX == first)*/
const struct forgrp *grpbuf);      /*   new forum group structure          */

VOID
notdlm(                            /* handle message delete notification   */
INT deltyp,                        /*   delete type code                   */
VOID *pWork,                       /*   work area in use                   */
struct message *msg,               /*   header of new message              */
const CHAR *text);                 /*   message text                       */

VOID
notdlml(                           /* low-level message delete notification*/
USHORT forum,                      /*   forum ID                           */
LONG msgid);                       /*   message ID                         */

VOID
notdlf(                            /* handle forum delete notification     */
const struct fordsk *def,          /*   forum definition structure         */
const CHAR *desc,                  /*   descriptive text                   */
const CHAR *echoes);               /*   pointer to array of echo addresses */

INT                                /*   returns updated hook index         */
notdlfl(                           /* low-level forum delete notification  */
INT curidx,                        /*   current hook index (NOIDX == first)*/
USHORT forum);                     /*   forum ID of deleted forum          */

VOID
notdlg(                            /* handle group delete notification     */
const struct forgrp *grpbuf);      /*   new forum group structure          */

INT                                /*   returns updated hook index         */
notdlgl(                           /* low-level group delete notification  */
INT curidx,                        /*   current hook index (NOIDX == first)*/
USHORT grpid);                     /*   group ID of deleted group          */

INT                                /*   returns index or NOIDX if not found*/
nexthook(                          /* find next GME hook function          */
INT hooktype,                      /*   of a given type                    */
INT curidx);                       /*   after this index (NOIDX == first)  */

VOID
hdlafwd(                           /* call autoforward handlers            */
CHAR * fwdee,                      /*   buf containing proposed forwardee  */
struct message const * pMsg,       /*   message being sent                 */
VOID *pWork);                      /*   GME work space                     */

INT                                /*   returns index or NOIDX if not found*/
nextphook(                         /* find next prioritized GME hook       */
INT hooktype,                      /*   of a given type                    */
INT curidx);                       /*   after this index (NOIDX == first)  */

const CHAR *
nwmtyps(                           /* get new message type string          */
INT nwmtyp);                       /*   given new message type code        */

GBOOL                              /*   returns TRUE if change made        */
addgrpf(                           /* add a forum to a group               */
struct forgrp *grpptr,             /*   group info record                  */
USHORT forum);                     /*   forum ID to add                    */

GBOOL                              /*   returns TRUE if change made        */
delgrpf(                           /* delete a forum from a group          */
struct forgrp *grpptr,             /*   group info record                  */
USHORT forum);                     /*   forum ID to add                    */

INT
neargrpi(                          /* get index of "nearest" forum in group*/
INT *cond,                         /*   buffer for result of last stricmp()*/
const CHAR *name,                  /*   name to search for                 */
const struct forgrp *grpbuf);      /*   group info buffer                  */

struct qscfg *                     /*   pointer to quickscan data          */
othqsp(                            /* get a user's quickscan configuration */
const CHAR *uid);                  /*   User-ID to find                    */
                                   /* (for one-cycle, no qscbb access only)*/

struct qscfg *                     /*   returns qscan if loaded, else NULL */
GetOnlineQS(                       /* internal onsqsp() replacement        */
CHAR const * uid);                 /*   User-ID to find                    */
                                   /* (returned ptr only valid one cycle)  */

INT                                /*   returns index or NOIDX if none     */
qsoldest(                          /* get oldest real entry w/ or w/out acc*/
const struct qscfg *qsc);          /*   pointer to quickscan               */

LONG
newmid(VOID);                      /* generate a new message ID            */

VOID
clrwrt(                            /* clr write-specific flds of work area */
VOID *pWork);                      /*   GME work space in use              */

LONG
cmptid(                            /* compute thread ID                    */
const struct message *msg);        /*   message header                     */

LONG
emltid(                            /* generate an E-mail thread ID         */
const struct message *msg);        /*   message header (to,from,topic)     */

LONG
fortid(                            /* generate a forum thread ID           */
const struct message *msg);        /*   message header (topic)             */

VOID
addhist(                           /* add to message history               */
CHAR *history,                     /*   current history string             */
const CHAR *newhist);              /*   string to add                      */

GBOOL                              /*   returns FALSE if couldn't open     */
opn4cpy(                           /* open files for copy                  */
VOID *pWork,                       /*   work area to open files for        */
const CHAR *srcfil);               /*   source file name                   */
                                   /*   (work->cpyatt is always dest)      */

INT                                /*   returns standard GME status codes  */
copychunk(                         /* cycled file copy utility             */
VOID *pWork);                      /*   work area in use                   */

VOID
wracc(                             /* write access level in compressd array*/
CHAR *acarpt,                      /*   pointer to access-level array      */
INT value,                         /*   value to write                     */
INT idx);                          /*   index in array                     */

INT
acclvl(                            /* get acc level from compressed array  */
const CHAR *acarpt,                /*   pointer to array                   */
INT idx);                          /*   index of access level              */

INT                                /*   returns standard GME status codes  */
chkread(                           /* check access/credits when reading    */
VOID *pWork);                      /*   GME work space (provided by caller)*/

VOID
ininew(                            /* initialize fields of a new message   */
struct message *msg);              /*   new message structure              */

VOID
iniamsg(                           /* init auto-filled fields of a message */
struct message *msg);              /*   new message structure              */

VOID
inicfmsg(                          /* init auto-filled fields for copy/fwd */
struct message *msg);              /*   message header structure           */

VOID
setggid(                           /* set global ID as local system        */
struct message *msg);              /*   message structure to set up        */

VOID
setflgs(                           /* set only appropriate message flags   */
struct message *msg,               /*   for new message                    */
CHAR *userid);                     /*   user-id sending message            */

GBOOL                              /*   returns TRUE if a cc: to send      */
nextcc(                            /* set up to send next cc:              */
VOID *pWork,                       /*   GME work space in use              */
struct message *msg,               /*   message header structure           */
const CHAR *cclist);               /*   cc: list string                    */

INT                                /*   idx of next entry (NOIDX if done)  */
nxtccidx(                          /* parse next cc: from list             */
CHAR *addr,                        /*   buffer to put cc: address into     */
const CHAR *list,                  /*   ';'-delimited list of addresses    */
INT curidx);                       /*   current index in cc: list          */

GBOOL                              /*   returns FALSE if can't send at all */
stripit(                           /* val a msg & strip unavail features   */
VOID *pWork,                       /*   GME work space (provided by caller)*/
struct message *msg);              /*   message header to strip            */

VOID
wrtaud(                            /* do new-message audit stuff           */
VOID *pWork,                       /*   GME work space (provided by caller)*/
const struct message *msg);        /*   new message structure              */

const CHAR *
curuid(VOID);                      /* get current User-ID if any           */

INT                                /*   returns standard GME status codes  */
chkdel(                            /* check access before deleting         */
VOID *pWork,                       /*   GME work space (provided by caller)*/
struct message *msg);              /*   message to check                   */

INT                                /*   returns standard GME status codes  */
chksnd(                            /* check credits/access before sending  */
VOID *pWork,                       /*   GME work space (provided by caller)*/
struct message *msg,               /*   new message structure              */
const CHAR *filatt);               /*   file attachment (if any)           */

INT                                /*   returns standard GME status codes  */
chkcf(                             /* check credits/access for copy/forward*/
VOID *pWork,                       /*   GME work space (provided by caller)*/
struct message *msg,               /*   message header being sent          */
const CHAR *filatt);               /*   file attachment (if any)           */

VOID
addchg(                            /* add up charges for current message   */
VOID *pWork,                       /*   work area in use                   */
const struct message *msg);        /*   new message structure              */

LONG
normchg(                           /* compute charges for a "normal" msg   */
const struct message *msg,         /*   message header to check            */
LONG attsiz);                      /*   size of attachment (if any)        */

VOID
chkrqs(                            /* check recipient's quickscan          */
VOID *pWork,                       /*   work area in use                   */
struct message *msg);              /*   new message structure              */
                                   /* (checks autofwd & forum to E-mail)   */

VOID
chkafwd(                           /* check out auto forwarding            */
VOID *pWork,                       /*   work area in use                   */
struct qscfg *rcpqsp,              /*   pointer to recipient's quickscan   */
struct message *msg);              /*   new message structure              */

VOID
rstafwd(                           /* restore msg->to after auto-forward   */
VOID *pWork,                       /*   work area in use                   */
struct message *msg);              /*   message structure                  */

VOID
swapto(                            /* swap between msg->to and work->auxto */
VOID *pWork,                       /*   work area in use                   */
struct message *msg);              /*   message structure                  */

VOID
chkfor(                            /* check for E-mail to a forum          */
struct message *msg);              /*   new message structure              */

VOID
cantopen(                          /* audit failed file open               */
const CHAR *fname,                 /*   file that couldn't be opened       */
GBOOL waswrt);                     /*   was the open for write             */

const CHAR *                       /*   path & file name of attachment     */
gdlname(                           /* gen path & file name to dnload att   */
GBOOL indirect,                    /*   attachment is indirect             */
USHORT forum,                      /*   forum message is in                */
LONG msgid);                       /*   message ID                         */

CHAR *                             /*   pointer to string buffer           */
indasp(                            /* get path+file name of indirect att   */
CHAR *buf,                         /*   string buffer to path              */
USHORT forum,                      /*   forum message is in                */
LONG msgid);                       /*   message ID of message              */

CHAR *                             /*   pointer to string buffer           */
dirasp(                            /* get path+file name of direct att     */
CHAR *buf,                         /*   string buffer to path              */
USHORT forum,                      /*   forum message is in                */
LONG msgid);                       /*   message ID of message              */

VOID
dlaud(                             /* audit a download                     */
const CHAR *userid,                /*   User-ID attachment downloaded for  */
CHAR *tag);                        /*   tag used for download              */

VOID
dlaudabt(                          /* audit an aborted download            */
const CHAR *userid,                /*   User-ID attachment downloaded for  */
CHAR *tag);                        /*   tag used for download              */

INT                                /*   returns appropriate GME work flag  */
dlstyp(                            /* get dist list type                   */
const CHAR *to);                   /*   given to address                   */

INT                                /*   returns standard GME status codes  */
inidist(                           /* initialize sending a dist list       */
VOID *pWork,                       /*   GME work space (provided by caller)*/
struct message *msg);              /*   new message structure              */

GBOOL                              /*   returns TRUE there was another     */
nxtdist(                           /* get next entry in dist list          */
VOID *pWork,                       /*   GME work space (provided by caller)*/
struct message *msg);              /*   message header structure           */

VOID
clsdist(                           /* finish up distribution               */
VOID *pWork);                      /*   GME work space (provided by caller)*/

GBOOL                              /*   returns TRUE if started OK         */
inimssnd(                          /* start up !MASS dist                  */
VOID *pWork);                      /*   work area to initialize            */

GBOOL                              /*   returns TRUE if started OK         */
nxtmass(                           /* get next !MASS entry                 */
VOID *pWork,                       /*   work area to use                   */
CHAR *addr);                       /*   buffer for address                 */

VOID
clsmass(                           /* shut down !MASS distribution         */
VOID *pWork);                      /*   work area used                     */

VOID
inilosl(VOID);                     /* initialize list of sysop lists       */

GBOOL                              /*   returns TRUE if added or updated   */
add2losl(                          /* add to list of sysop dist lists      */
const CHAR *lstnam,                /*   list name                          */
const CHAR *lstkey,                /*   list key                           */
SHORT lstchg);                     /*   list surcharge                     */

GBOOL                              /*   returns TRUE if successful         */
rdlstinf(                          /* return key/charge info from list file*/
FILE *fp,                          /*   stream to read from                */
CHAR *tmpkey,                      /*   key buffer                         */
SHORT *tmpchg);                    /*   charge buffer                      */

GBOOL                              /*   returns TRUE if started OK         */
inislsnd(                          /* start up sysop list dist             */
VOID *pWork,                       /*   work area to initialize            */
const CHAR *lstnam);               /*   name of list                       */

VOID
clssys(                            /* close sysop distribution list        */
VOID *pWork);                      /*   work area in use                   */

INT
dlstidx(                           /* get index of list in list of lists   */
const CHAR *name);                 /*   sysop list name                    */

const CHAR *                       /*   returns pointer to path & file name*/
dlstpfn(                           /* get path & file name of dist list    */
const CHAR *name);                 /*   complete name (including @)        */

VOID
clrfrom(                           /* "clear" from field of message        */
struct message *msg);              /*   message to clear                   */

VOID
uclfrom(                           /* un-"clear" from field of message     */
struct message *msg);              /*   message to unclear                 */

VOID
clrto(                             /* "clear" to field of message          */
struct message *msg);              /*   message to clear                   */

VOID
uclto(                             /* un-"clear" to field of message       */
struct message *msg);              /*   message to unclear                 */

CHAR
lwclch(                            /* reversable clobber/unclobber of char */
CHAR c);                           /*   character to clobber/unclobber     */

GBOOL
samepath(                          /* are two path+file names the same dir?*/
const CHAR *path1,                 /*   one path+file name                 */
const CHAR *path2);                /*   second path+file name              */

GBOOL
isfnmc(                            /* is this a valid file name character? */
CHAR c);                           /*   character to check                 */

CHAR *                             /*   copy of pointer to destination     */
prf2str(                           /* copy prfbuf contents to a string     */
CHAR *str,                         /*   string to copy into                */
UINT len);                         /*   length of string                   */

CHAR *                             /*   copy of pointer to string          */
new2ret(                           /* replace '\n' with '\r' in string     */
CHAR *str);                        /*   string to replace                  */

CHAR *                             /*   pointer to start of section name   */
findsect(                          /* find a section in app-defined info   */
const CHAR *src,                   /*   app-defined info buffer            */
const CHAR *sect);                 /*   section name                       */

CHAR *                             /*   returns pointer to destination     */
addsect(                           /* add a new section                    */
CHAR *dst,                         /*   buffer to add to                   */
const CHAR *src,                   /*   contents of new section            */
const CHAR *sect);                 /*   new section name                   */

CHAR *                             /*   returns pointer to destination     */
remsect(                           /* remove a section                     */
CHAR *dst,                         /*   buffer containing app-defined info */
const CHAR *sect);                 /*   section name                       */

CHAR *                             /*   returns pointer to name string     */
mksectnam(                         /* make section name string             */
CHAR *buf,                         /*   buffer to put name string into     */
const CHAR *sect);                 /*   section name                       */

GBOOL
gmeoffl(VOID);                     /* is the GME running in offline mode?  */

#ifdef DEBUG
GBOOL
seqok(                             /* check for valid sequence code        */
INT sequence,                      /*   sequence code                      */
USHORT forum);                     /*   forum ID                           */

GBOOL
ctxok(                             /* check for valid context setup        */
const struct rdctx *ctx);          /*   context structure                  */
#endif                             /* DEBUG                                */

GBOOL
thisexp(                           /* does address refer to this exporter? */
const struct exporter *exp,        /*   pointer to exporter control block  */
const CHAR *to);                   /*   address to check                   */

struct expinfo *                   /*   returns pointer to destination     */
exp2inf(                           /* copy exporter struct to expinfo      */
const struct exporter *exp,        /*   exporter structure                 */
struct expinfo *info);             /*   expinfo structure                  */

#ifdef __cplusplus
}; // extern "C"
#endif // __cplusplus

#endif                             /* __GMEUTL_H                           */
