/***************************************************************************
 *                                                                         *
 *   SMNNUTIL.C                                                            *
 *                                                                         *
 *   Copyright (c) 1998 Galacticomm, Inc.         All rights reserved.     *
 *                                                                         *
 *   Utility functions common to SMTP and NNTP.                            *
 *                                                                         *
 *                                           - J. Alvrus    12/29/1997     *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include <sys\timeb.h>
#include "datstm.h"
#include "tcpip.h"
#include "dns.h"
#include "smnnhook.h"

#define FILREV "$Revision: 2 $"

struct HookItem * HookArr=NULL;    /* array of function hooks              */
INT nHooks=0;                      /* number of function hooks             */

CHAR *                             /*   (returns passed value)             */
nmsgid(                            /* generate an rfc822 message-id        */
CHAR *cp)                          /*   destination (max room=MAXADR+24)   */
{
#ifdef UNIX
     struct timeval tv;
     static UINT tiebrk;

     gettimeofday(&tv,NULL);
     sprintf(cp,"<%ld%d%u@%s>",tv.tv_sec,tv.tv_usec,++tiebrk,hstdom);
#else
     struct timeb tb;
     static UINT tiebrk;

     ftime(&tb);
     sprintf(cp,"<%ld%d%u@%s>",tb.time,tb.millitm,++tiebrk,hstdom);
     return(cp);
#endif
}

GBOOL                              /*   returns FALSE if too many files    */
makeUniqueFName(                   /* create unique temporary file name    */
CHAR *fpath,                       /*   path prefix with FNEXSZ extra room */
CHAR *extName)                     /*   extension name (e.g. "$$$")        */
{
     CHAR *ptr;
     USHORT tiebrk;

     ptr=fpath+strlen(fpath);
     for (tiebrk=0 ; tiebrk < 1000 ; tiebrk++) {
          sprintf(ptr,"%04hX%04hX.%s",now(),tiebrk,extName);
          if (access(fpath,0) == -1) {
               return(TRUE);
          }
     }
     return(FALSE);
}

CHAR *
crpstr(                            /* crops string after passed character  */
const CHAR *string,                /*   string to crop                     */
CHAR cropch)                       /*   crop character                     */
{
     CHAR *ptr;

     if ((ptr=strchr(string,cropch)) != NULL) {
          do {
               ptr++;
          } while (isspace(*ptr));
          return(ptr);
     }
     return((CHAR *)string);
}

/*
 * Hook Management Functions
 */

static
INT                                /*   > 0 = target > test, etc.          */\
phookcmp(                          /* prioritized hook comparison function */
VOID const * target,               /*   target object                      */
VOID const * array,                /*   array object                       */
ULONG index)                       /*   index of array element to test     */
{
     /* NOTE: sorts in reverse order (highest first) */
     return(((struct HookItem const *)array)[index].hookpri-((SHORT)target));
}

GBOOL                              /*   returns TRUE if hook set           */
HookAdd(                           /* add a function hook                  */
USHORT hooktype,                   /*   type of hook to set                */
voidfunc hookfunc,                 /*   hook function pointer              */
SHORT priority)                    /*   priority                           */
{
     INT i,cmp;

     ASSERT(hookfunc != NULL);
     if (alcarr((VOID **)&HookArr,sizeof(struct HookItem),nHooks,SMLBLK)) {
          i=binFindNear(&cmp,(VOID *)priority,HookArr,nHooks,phookcmp);
          memmove(&HookArr[i+1],&HookArr[i]
                 ,(nHooks-i)*sizeof(struct HookItem));
          HookArr[i].hookfunc=hookfunc;
          HookArr[i].hooktype=hooktype;
          HookArr[i].hookpri=priority;
          ++nHooks;
          return(TRUE);
     }
     return(FALSE);
}

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

     for (i=(curidx == NOIDX ? 0 : curidx+1) ; i < nHooks ; ++i) {
          if (HookArr[i].hooktype == hooktype) {
               return(i);
          }
     }
     return(NOIDX);
}
