home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / sqdev200.zip / features / msgtrack.c < prev    next >
C/C++ Source or Header  |  1994-05-23  |  12KB  |  541 lines

  1. #pragma off(unreferenced)
  2. static char rcs_id[]="$Id: MSGTRACK.C 1.4 1994/02/17 01:12:34 sjd Exp sjd $";
  3. #pragma on(unreferenced)
  4.  
  5. /* Copyright 1992 by Scott J. Dudley.
  6.    Portions copyright 1987-1991 by Bit Bucket Software.
  7. */
  8.  
  9. #define INCL_NOPM
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <stddef.h>
  13. #include <string.h>
  14. #include <io.h>
  15. #include <fcntl.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <share.h>
  19. #include <os2.h>
  20. #include <time.h>
  21. #include "msgtrack.h"
  22. #include "msgapi.h"
  23. #include "sqfeat.h"
  24.  
  25. typedef NETADDR *NETADDRP;
  26.  
  27.  
  28. static char szNodexName[120]="nodex.ndx";   /* Nodelist index name */
  29. static USHORT fKill=FALSE;                  /* Kill bounced msgs? */
  30. void (cdecl far *pfnLogMsg)(char far *line);/* Write to Squish log. */
  31.  
  32.  
  33. union stamp_combo * _fast TmDate_to_DosDate(struct tm *tmdate,
  34.                                              union stamp_combo *dosdate)
  35. {
  36.   dosdate->msg_st.date.da=tmdate->tm_mday;
  37.   dosdate->msg_st.date.mo=tmdate->tm_mon+1;
  38.   dosdate->msg_st.date.yr=tmdate->tm_year-80;
  39.  
  40.   dosdate->msg_st.time.hh=tmdate->tm_hour;
  41.   dosdate->msg_st.time.mm=tmdate->tm_min;
  42.   dosdate->msg_st.time.ss=tmdate->tm_sec >> 1;
  43.  
  44.   return dosdate;
  45. }
  46.  
  47.  
  48. union stamp_combo * _fast Get_Dos_Date(union stamp_combo *st)
  49. {
  50.   time_t timeval;
  51.   struct tm *tim;
  52.  
  53.   timeval=time(NULL);
  54.   tim=localtime(&timeval);
  55.  
  56.   return (TmDate_to_DosDate(tim,st));
  57. }
  58.  
  59. /* Turn a binary address into a string */
  60.  
  61. byte * _fast Address(NETADDR *a)
  62. {
  63.   static char temp[30];
  64.   char point[10];
  65.  
  66.   sprintf(point, ".%hu", (unsigned)a->point);
  67.  
  68.   sprintf(temp, "%hu:%hu/%hu%s",
  69.           (unsigned)a->zone, (unsigned)a->net, (unsigned)a->node,
  70.           a->point ? point : "");
  71.  
  72.   return temp;
  73. }
  74.  
  75.  
  76. /* Initialization routine: entrypoint */
  77.  
  78. word FEATENTRY _export FeatureInit(struct _feat_init far *pfi)
  79. {
  80.   char far *p="MsgTrack";
  81.  
  82.   pfnLogMsg=pfi->pfnLogMsg; /* Save log message function pointer */
  83.   strcpy(pfi->szConfigName, p);
  84.   pfi->ulFlag=FFLAG_NETSENT | /*FFLAG_NETRECD |*/ FFLAG_NETNOTTOUS;
  85.   return 0;
  86. }
  87.  
  88.  
  89. /* Configuration routine: entrypoint */
  90.  
  91. word FEATENTRY _export FeatureConfig(struct _feat_config far *pfc)
  92. {
  93.   NW(pfc);
  94.  
  95.   if (stricmp(pfc->ppszArgs[1], "Nodelist")==0)
  96.     strcpy(szNodexName, pfc->ppszArgs[2]);
  97.   else if (stricmp(pfc->ppszArgs[1], "Kill")==0)
  98.     fKill=TRUE;
  99.   else
  100.   {
  101.     char temp[120];
  102.  
  103.     sprintf(temp, "!Unknown keyword: \"MsgTrack %s\"\n", pfc->ppszArgs[1]);
  104.     (*pfnLogMsg)(temp);
  105.     return 1;
  106.   }
  107.  
  108.   return 0;
  109. }
  110.  
  111.  
  112.  
  113. /* Get a version 7 nodelist node entry */
  114.  
  115. static struct _ndx * near get7node(int stream, dword pos, struct _ndx *ndx)
  116. {
  117.   lseek (stream, (long) pos, SEEK_SET);
  118.  
  119.   if (read(stream, (char *)ndx, sizeof(struct _ndx)) != sizeof(struct _ndx))
  120.   {
  121.     close(stream);
  122.     return NULL;
  123.   }
  124.   
  125.   return ndx;
  126. }
  127.  
  128.  
  129.  
  130. /* Do a btree lookup on a V7 nodelist index */
  131.  
  132. static long near btree(char *filename, void *desired, int (near *compare)(void *key, void *desired, int len))
  133. {
  134.   int j, k, l;
  135.   struct _ndx *nodeidx = NULL;
  136.   struct _ndx *noderef = NULL;
  137.   struct _IndxRef *ip = NULL;
  138.   struct _LeafRef *lp = NULL;
  139.   char aline[160];
  140.   char *tp;
  141.   char *np;
  142.  
  143.   long record, foundrec = -1L;
  144.   int count;
  145.  
  146.   int stream;
  147.  
  148.   if ((stream = sopen(filename, O_RDONLY | O_BINARY | O_NOINHERIT, SH_DENYNO,
  149.                       S_IREAD|S_IWRITE))==-1)
  150.   {
  151.     return (-1L);                            /* no file, no work to do */
  152.   }
  153.  
  154.   if ((nodeidx=malloc(sizeof(struct _ndx)))==NULL ||
  155.       (noderef=malloc(sizeof(struct _ndx)))==NULL)
  156.   {
  157.     if (nodeidx)
  158.       free(nodeidx);
  159.  
  160.     close(stream);
  161.     return -1L;
  162.   }
  163.  
  164.  
  165.   /* Get CtlRec */
  166.  
  167.   if (get7node (stream, 0L, noderef) != noderef)
  168.   {
  169.     free(noderef);
  170.     free(nodeidx);
  171.     close(stream);
  172.     return -1L;
  173.   }
  174.  
  175.  
  176.   /* The guts of the matter -- walk from CtlRec to Leaf */
  177.  
  178.   record=noderef->ndx.CtlBlk.CtlRoot;
  179.  
  180.   /* Read the first Index node. */
  181.   
  182.   if (get7node(stream, 
  183.                (unsigned long) (record * noderef->ndx.CtlBlk.CtlBlkSize),
  184.                nodeidx) != nodeidx)
  185.   {
  186.     free(noderef);
  187.     free(nodeidx);
  188.     close (stream);
  189.     return -1L;
  190.   }
  191.  
  192.  
  193.   /* Follow the node tree until we either match a key right in the index    *
  194.    * node, or locate the leaf node which must contain the entry.            */
  195.  
  196.   while (nodeidx->ndx.INodeBlk.IndxFirst != -1)
  197.   {
  198.     if ((count=nodeidx->ndx.INodeBlk.IndxCnt) == 0)
  199.     {
  200.       free(noderef);
  201.       free(nodeidx);
  202.       close (stream);
  203.       return (-1L);
  204.     }
  205.  
  206.     /* check 20 or less */
  207.     
  208.     for (j=0; j < count; j++)
  209.     {
  210.       ip=&(nodeidx->ndx.INodeBlk.IndxRef[j]);
  211.       tp=(char *) nodeidx + ip->IndxOfs;
  212.  
  213.       k=l=ip->IndxLen;
  214.  
  215.       for (np=aline; k > 0; k--)
  216.         *np++=*tp++;
  217.  
  218.       *np='\0'; /*SJD Mon  07-06-1992  10:57:52 */
  219.  
  220.       k=(*compare)((void *)aline, desired, l);
  221.  
  222.       if (k > 0)
  223.         break;
  224.  
  225.       if (k == 0)
  226.       {
  227.  
  228.         /* Key matches in the index node. Since we're just doing lookup, we *
  229.          * can assume its pointer is valid. If we were doing updates, that  *
  230.          * assumption would not work, because leaf nodes update first. So   *
  231.          * in an update environment, the entire code segment relating to    *
  232.          * k == 0 should not execute, and we should walk the tree all the   *
  233.          * way down.                                                        */
  234.  
  235.         free(noderef);
  236.         free(nodeidx);
  237.         close(stream);
  238.  
  239.         return (nodeidx->ndx.INodeBlk.IndxRef[j].IndxData);
  240.       }
  241.     }
  242.  
  243.     if (j == 0)
  244.        record=nodeidx->ndx.INodeBlk.IndxFirst;
  245.     else record=(nodeidx->ndx.INodeBlk.IndxRef[--j]).IndxPtr;
  246.  
  247.     if (get7node(stream, 
  248.                 (unsigned long) (record * noderef->ndx.CtlBlk.CtlBlkSize),
  249.                 nodeidx) != nodeidx)
  250.     {
  251.       free(noderef);
  252.       free(nodeidx);
  253.       close (stream);
  254.       return (-1L);
  255.     }
  256.   }
  257.  
  258.   /* We can only get here if we've found the leafnode which contains our    *
  259.    * entry.                                                                 */
  260.  
  261.   /* Find our guy here or die trying. */
  262.  
  263.   if ((count=nodeidx->ndx.LNodeBlk.IndxCnt) != 0)
  264.   {
  265.     /* Search for a higher key */
  266.  
  267.     for (j=0; j < count; j++) /* check 30 or less */
  268.     {
  269.       lp=&(nodeidx->ndx.LNodeBlk.LeafRef[j]);
  270.       tp=(char *) nodeidx + lp->KeyOfs;
  271.  
  272.       k=l=lp->KeyLen;
  273.  
  274.       for (np=aline; k > 0; k--)
  275.         *np++ = *tp++;
  276.  
  277.       *np='\0'; /*SJD Mon  07-06-1992  10:58:01 */
  278.  
  279.       k=(*compare)((void *)aline, desired, l);
  280.  
  281.       if (k > 0)
  282.         break;
  283.        
  284.       if (k == 0)
  285.       {
  286.         foundrec=(nodeidx->ndx.LNodeBlk.LeafRef[j]).KeyVal;
  287.         break;
  288.       }
  289.     }
  290.   }
  291.  
  292.   free(noderef);
  293.   free(nodeidx);
  294.   close (stream);
  295.  
  296.   return (foundrec);
  297. }
  298.  
  299.  
  300.  
  301. /* Static comparison function for nodelist addresses */
  302.  
  303. static int near addr_compare(void *key, void *desired, int len)
  304. {
  305.   int k;
  306.  
  307.   if ((k = ((NETADDRP)key)->zone - ((NETADDRP)desired)->zone) != 0)
  308.     return (k);
  309.  
  310.   if ((k=((NETADDRP)key)->net - ((NETADDRP)desired)->net) != 0)
  311.     return (k);
  312.  
  313.   if ((k = ((NETADDRP)key)->node - ((NETADDRP)desired)->node) != 0)
  314.     return (k);
  315.  
  316.   if (len == 6)
  317.     ((NETADDRP)key)->point=0;
  318.  
  319.   return ((NETADDRP)key)->point - ((NETADDRP)desired)->point;
  320.  
  321.  
  322. /* Determine whether or not the message's destination address is            *
  323.  * listed in our nodelist.                                                  */
  324.  
  325. static unsigned near FeatListed(struct _feat_netmsg far *pfn)
  326. {
  327.   NETADDR n=pfn->pMsg->dest;
  328.   long rec;
  329.  
  330.  
  331.   rec=btree(szNodexName, (void *)&n, addr_compare);
  332.  
  333.   if (rec != -1)
  334.     return TRUE;
  335.  
  336.   if (n.point)
  337.   {
  338.     n.point=0;
  339.     rec=btree(szNodexName, (void *)&n, addr_compare);
  340.   }
  341.  
  342.   return (rec != -1);
  343. }
  344.  
  345.  
  346.  
  347. /* Bounce a message back to the sender */
  348.  
  349. static void near BounceMessage(struct _feat_netmsg far *pfn)
  350. {
  351.   char far *p;
  352.   char *bounce;
  353.   char trailer[]="\r================= e n d   o f   b o u n c e d   m e s s a g e ================\r\r";
  354.   XMSG msg;
  355.   HMSG hmsg;
  356.  
  357.   /* Set the orig and dest addresses accordingly */
  358.  
  359.   memset(&msg, 0, sizeof msg);
  360.   msg.orig=pfn->us;
  361.   msg.dest=pfn->pMsg->orig;
  362.  
  363.   printf("msg orig=%s\n", Address(&msg.orig));
  364.   printf("msg dest=%s\n", Address(&msg.dest));
  365.  
  366.   /* Reverse the to/from fields */
  367.  
  368.   strcpy(msg.from, "SquishMail");
  369.   strcpy(msg.to, pfn->pMsg->from);
  370.   sprintf(msg.subj, "NetMail bounced by %s", Address(&msg.orig));
  371.  
  372.   Get_Dos_Date(&msg.date_written);
  373.   msg.date_arrived=msg.date_written;
  374.   msg.attr=MSGLOCAL;
  375.  
  376.   if ((bounce=malloc(1024)) != NULL)
  377.   {
  378.     sprintf(bounce,
  379.       "The destination address of the following message was not listed "
  380.       "in the nodelist at %s, so the message below was not sent.  "
  381.       "Please correct the destination address before attempting to send "
  382.       "the message again.\r\r"
  383.  
  384.       "- SquishMail at %s\r\r"
  385.  
  386.       "================ b o u n c e d   m e s s a g e   f o l l o w s ===============\r\r"
  387.  
  388.       "From: %s (%u:%u/%u.%u)\r"
  389.       "  To: %s (%u:%u/%u.%u)\r"
  390.       "Subj: %s\r\r",
  391.  
  392.       Address(&msg.orig), Address(&msg.orig),
  393.       pfn->pMsg->from,                    
  394.       pfn->pMsg->orig.zone, pfn->pMsg->orig.net, pfn->pMsg->orig.node,
  395.       pfn->pMsg->orig.point,
  396.       pfn->pMsg->to,
  397.       pfn->pMsg->dest.zone, pfn->pMsg->dest.net, pfn->pMsg->dest.node,
  398.       pfn->pMsg->dest.point,
  399.       pfn->pMsg->subj);
  400.   }
  401.  
  402.  
  403.   if ((hmsg=MsgOpenMsg(pfn->ha, MOPEN_CREATE, 0))==NULL)
  404.   {
  405.     printf("MsgTrack:  Couldn't create bounce message.\n");
  406.     return;
  407.   }
  408.  
  409.  
  410.   /* Write the first part of the bounced message */
  411.  
  412.   MsgWriteMsg(hmsg, FALSE, &msg, bounce,
  413.               strlen(bounce),
  414.               strlen(bounce)+strlen(pfn->pszMsgTxt)+strlen(trailer)+1,
  415.               0, NULL);
  416.  
  417.   if (bounce)
  418.     free(bounce);
  419.  
  420.   /* Convert all control-A's to at-signs */
  421.  
  422.   for (p=pfn->pszMsgTxt; (p=strchr(p, '\x01')) != NULL; p++)
  423.     *p='@';
  424.  
  425.   /* Now write the rest of the message body */
  426.  
  427.   MsgWriteMsg(hmsg, TRUE, NULL, pfn->pszMsgTxt, strlen(pfn->pszMsgTxt),
  428.               0, 0, NULL);
  429.  
  430.   MsgWriteMsg(hmsg, TRUE, NULL, trailer, strlen(trailer)+1,
  431.               0, 0, NULL);
  432.  
  433.   /* Close the message */
  434.  
  435.   MsgCloseMsg(hmsg);
  436.  
  437.   /* Make sure that this message is not processed */
  438.  
  439.   pfn->ulAction=FACT_SKIP | FACT_HIDE;
  440.  
  441.   if (fKill)
  442.     pfn->ulAction |= FACT_KILL;
  443.   else
  444.   {
  445.     pfn->ulAction |= FACT_RWMSG;
  446.     pfn->pMsg->attr |= MSGSENT | MSGORPHAN;
  447.   }
  448. }
  449.  
  450.  
  451.  
  452. /* Entry point - packing netmail message */
  453.  
  454. word FEATENTRY _export FeatureNetMsg(struct _feat_netmsg far *pfn)
  455. {
  456.   char temp[120];
  457.   static int configured=FALSE;
  458.   static int done_err=FALSE;
  459.  
  460.   /* Validate the nodelist index */
  461.  
  462.   if (!configured)
  463.   {
  464.     if (access(szNodexName, 0)==-1)
  465.     {
  466.       if (!done_err)
  467.       {
  468.         printf("Error!  Nodelist index `%s' does not exist!\n", szNodexName);
  469.         done_err=TRUE;
  470.       }
  471.  
  472.       return 0;
  473.     }
  474.  
  475.     configured=TRUE;
  476.   }
  477.  
  478. /*  printf("Scanning msg from: %-20.20s, to: %s\n",
  479.          pfn->pMsg->from, pfn->pMsg->to);
  480. */
  481.  
  482.   /* If the message is addressed to a listed address, get out */
  483.  
  484.   if (FeatListed(pfn))
  485.   {
  486.     sprintf(temp, "@Listed dest address %u:%u/%u.%u",
  487.             pfn->pMsg->dest.zone, pfn->pMsg->dest.net,
  488.            pfn->pMsg->dest.node, pfn->pMsg->dest.point);
  489.  
  490.     (*pfnLogMsg)(temp);
  491.  
  492.     return 0;
  493.   }
  494.  
  495.   sprintf(temp, "@UNLISTED dest address %u:%u/%u.%u",
  496.           pfn->pMsg->dest.zone, pfn->pMsg->dest.net,
  497.           pfn->pMsg->dest.node, pfn->pMsg->dest.point);
  498.  
  499.   (*pfnLogMsg)(temp);
  500.  
  501.   fflush(stdout);
  502.  
  503.   /* Bounce this message */
  504.  
  505.   BounceMessage(pfn);
  506.  
  507.   return 0;
  508. }
  509.  
  510.  
  511. word FEATENTRY _export FeatureTossMsg(struct _feat_toss far *pft)
  512. {
  513.   NW(pft);
  514.   return 0;
  515. }
  516.  
  517.  
  518. word FEATENTRY _export FeatureScanMsg(struct _feat_scan far *pfs)
  519. {
  520.   NW(pfs);
  521.   return 0;
  522. }
  523.  
  524. word FEATENTRY _export FeatureTerm(struct _feat_term far *pft)
  525. {
  526.   NW(pft);
  527.   return 0;
  528. }
  529.  
  530.  
  531. #ifdef __FLAT__
  532. void FEATENTRY _export Feature32Bit(void)
  533. #else
  534. void FEATENTRY _export Feature16Bit(void)
  535. #endif
  536. {
  537. }
  538.  
  539.  
  540.