home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / MLNK10CS.ZIP / MSGLINK.C < prev    next >
Text File  |  1990-09-17  |  15KB  |  652 lines

  1. /*
  2.                        Message Base Reply Chain Linker
  3.  
  4.               This module was originally written by Bob Hartman
  5.                        Sysop of FidoNet node 1:132/101
  6.  
  7.    Spark Software, 427-3 Amherst St, CS 2032, Suite 232, Nashua, NH 03061
  8.  
  9.  This program source code is being released with the following provisions:
  10.  
  11.  1.  You are  free to make    changes to this source    code for use on your own
  12.  machine,  however,  altered source files may not be distributed without the
  13.  consent of Spark Software.
  14.  
  15.  2.  You may distribute "patches"  or  "diff" files for any changes that you
  16.  have made, provided that the "patch" or "diff" files are also sent to Spark
  17.  Software for inclusion in future releases of the entire package.    A "diff"
  18.  file for the source archives may also contain a compiled version,    provided
  19.  it is    clearly marked as not  being created  from the original source code.
  20.  No other  executable  versions may be    distributed without  the  consent of
  21.  Spark Software.
  22.  
  23.  3.  You are free to include portions of this source code in any program you
  24.  develop, providing:  a) Credit is given to Spark Software for any code that
  25.  may is used, and  b) The resulting program is free to anyone wanting to use
  26.  it, including commercial and government users.
  27.  
  28.  4.  There is  NO  technical support  available for dealing with this source
  29.  code, or the accompanying executable files.  This source  code  is provided
  30.  as is, with no warranty expressed or implied (I hate legalease).    In other
  31.  words, if you don't know what to do with it,  don't use it,  and if you are
  32.  brave enough to use it, you're on your own.
  33.  
  34.  Spark Software may be contacted by modem at (603) 888-8179 (node 1:132/101)
  35.  on the public FidoNet network, or at the address given above.
  36.  
  37. */
  38.  
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <stdio.h>
  42. #include <ctype.h>
  43. #include <fcntl.h>
  44. #include <sys\types.h>
  45. #include <sys\stat.h>
  46. #include <io.h>
  47. #include <dos.h>
  48. #include <direct.h>
  49.  
  50. #ifdef OS_2
  51. #define DOS_INCL_DOSFILEMGR
  52. #include <os2.h>
  53. #endif
  54.  
  55. #include "bbsdev.h"
  56. #ifndef OS_2
  57. #include "diskio.h"
  58. #endif
  59.  
  60. char *REV = "$Revision: 1.0c $";        /* Used in my code for
  61.                                                          * my RCS program */
  62.  
  63. #define MSG_EXISTS         1
  64. #define MSG_LINK_CHANGED 4
  65.  
  66. #ifdef OS_2
  67. #define MAX_FN_LEN 260
  68. #else
  69. #define MAX_FN_LEN 80
  70. #endif
  71.  
  72. char            dir_drive2[MAX_FN_LEN];
  73. char            dir_drive1[MAX_FN_LEN];
  74.  
  75. typedef struct msgtyp
  76. {
  77.    int               msg_num;
  78.    unsigned int    msg_subj;
  79.    int               msg_up;
  80.    int               msg_down;
  81.    int               msg_flags;
  82. }                MSG_TYP;
  83.  
  84. #define MAX_MSGS 2048
  85.  
  86. MSG_TYP         msgs[MAX_MSGS];
  87. SYS             curr_system;
  88. _sys            opus_sys;
  89. MSG             msg_tmp;
  90.  
  91. int             n_msgs, quiet, opus;
  92.  
  93. int             total_reserved;
  94. char            dta[128];
  95. char           *junk;
  96. extern char     tmpjunk[], tmpjunk1[], tmpjunk2[];
  97. AREAS_PTR        areas[MAXAREAS];
  98. int             tot_areas;
  99.  
  100. void main (argc, argv)
  101. int  argc;
  102. char *argv[];
  103. {
  104.     register int i;
  105.     int  j;
  106.     char buff1[20], buff2[20];          /* Junk buffers */
  107.     FILE *f1;
  108.     int  from_file;
  109.     char *p1;
  110.  
  111.     /* Process command line */
  112.     if (((argv[1][0] == '-')||(argv[1][0] == '/')) && (toupper (argv[1][1]) == 'F'))
  113.         {
  114.         --argc;
  115.         ++argv;
  116.         if ((f1 = fopen (argv[1], "rt")) == NULL)
  117.             {
  118.             printf ("Cannot open '%s'- exiting\n", argv[1]);
  119.             exit (2);
  120.             }
  121.         from_file = 1;
  122.         --argc;
  123.         ++argv;
  124.         }
  125.     else
  126.         from_file = 0;
  127.  
  128.     if (((argv[1][0] == '-')||(argv[1][0] == '/')) && (toupper (argv[1][1]) == 'O'))
  129.         {
  130.         --argc;
  131.         ++argv;
  132.         opus = 1;
  133.         }
  134.     else
  135.         opus = 0;
  136.  
  137.     if (((argv[1][0] == '-')||(argv[1][0] == '/')) && (toupper (argv[1][1]) == 'Q'))
  138.         {
  139.         --argc;
  140.         ++argv;
  141.         quiet = 1;
  142.         }
  143.     else
  144.         quiet = 0;
  145.  
  146.     if (argv[1][0] == '+')
  147.         {
  148.         strcpy (tmpjunk, &argv[1][1]);
  149.         --argc;
  150.         ++argv;
  151.         }
  152.     else
  153.         strcpy (tmpjunk, "AREAS.BBS");
  154.  
  155.     if (!quiet)
  156.         {
  157.         /* Say hello to the world */
  158.         sscanf (REV, "$%s %s", buff1, buff2);
  159. #ifdef OS_2
  160.         printf ("MsgLinkOS2 - %s %s by Bill Andrus, SysOp of FidoNet Node 1:109/301.1\n", buff1, buff2);
  161. #else
  162.         printf ("MsgLink - %s %s by Bill Andrus, SysOp of FidoNet Node 1:109/301.1\n", buff1, buff2);
  163. #endif
  164.         printf ("This executable program is based on released sources of Bob Hartman.\n");
  165.         printf ("This executable program is in the Public Domain as part of the BBS project.\n");
  166.         printf ("For information on BBS  (Bit Bucket Software),  contact 132/101 or 141/491.\n");
  167.         printf ("CRC routine copyright Renex Corporation. Used with permission of Ray Gwinn.\n\n");
  168.         }
  169.  
  170.     if (compile_areas (tmpjunk) != 0)
  171.         {
  172.         printf ("Could not process AREAS file\n");
  173.         }
  174.  
  175.     if ((argc < 2) && !from_file)
  176.         {
  177.         msglink_usage ();
  178.         }
  179.  
  180.     while ((--argc > 0) || from_file)
  181.         {
  182.         /* Save where we are */
  183.         getcwd (dir_drive2, MAX_FN_LEN);
  184.         getcwd (dir_drive1, MAX_FN_LEN);
  185.  
  186.         if ((argc <= 0) && from_file)
  187.             {
  188.             if (fgets (tmpjunk1, 128, f1) == NULL)
  189.                 {
  190.                 from_file = 0;
  191.                 fclose (f1);
  192.                 continue;
  193.                 }
  194.             else
  195.                 {
  196.                 /* Null terminate the string */
  197.                 p1 = tmpjunk1;
  198.                 while (*p1)
  199.                     {
  200.                     if ((isspace (*p1)) || (*p1 == 26))
  201.                         {
  202.                         *p1 = '\0';
  203.                         break;
  204.                         }
  205.                     ++p1;
  206.                     }
  207.  
  208.                 /* If we didn't get anything */
  209.                 if (p1 == tmpjunk1)
  210.                     continue;
  211.                 }
  212.             }
  213.         else
  214.             {
  215.             strcpy (tmpjunk1, argv[1]);
  216.             ++argv;
  217.             }
  218.  
  219.         j = 500;
  220.         strcpy (tmpjunk2, tmpjunk1);
  221.         if (!get_fido_sys (tmpjunk2, 0))
  222.             {
  223.             strcpy (tmpjunk1, tmpjunk2);
  224.             }
  225.         else
  226.             {
  227.             /* Now find it in our list of areas */
  228.             for (j = 0; j < tot_areas; j++)
  229.                 {
  230.                 if (stricmp (areas[j]->area_name, tmpjunk2) == 0)
  231.                     {
  232.                     /* Found it */
  233.                     strcpy (tmpjunk1, areas[j]->msg_path);
  234.                     break;
  235.                     }
  236.                 }
  237.             if (j == tot_areas)
  238.                 {
  239.                 if (!(filedir (tmpjunk2, 0, tmpjunk2, ST_DIRECT) & ST_DIRECT))
  240.                     {
  241.                     printf ("Unknown Area Name '%s'\n", tmpjunk1);
  242.                     continue;
  243.                     }
  244.                 }
  245.             }
  246.  
  247.         if (opus)
  248.             {
  249.             if (get_opus (tmpjunk1,(_sys *)&opus_sys) < 0)
  250.                 {
  251.                 printf ("Cannot make sense of '%s'\n", tmpjunk1);
  252.                 continue;
  253.                 }
  254.             }
  255.         else
  256.             {
  257.             if (get_system (tmpjunk1,(SYS *)&curr_system) < 0)
  258.                 {
  259.                 printf ("Cannot make sense of '%s'\n", tmpjunk1);
  260.                 continue;
  261.                 }
  262.             }
  263.  
  264.  
  265.         n_msgs = 0;
  266.  
  267.         /* Read in all message data */
  268.         if (!quiet)
  269.             printf ("Reading in message data...\n");
  270.         read_msg_data ();
  271.  
  272.         /* Process message data */
  273.         if (n_msgs > 0)
  274.             {
  275.                 if ((msgs[0].msg_num != 1) && (msgs[0].msg_down != 0))
  276.                     {
  277.                     msgs[0].msg_down = 0;
  278.                     msgs[0].msg_flags = MSG_LINK_CHANGED;
  279.                     }
  280.                 if ((n_msgs == 1) && (msgs[0].msg_up != 0))
  281.                     {
  282.                     msgs[0].msg_up = 0;
  283.                     msgs[0].msg_flags = MSG_LINK_CHANGED;
  284.                     }
  285.             }
  286.  
  287.         for (i = 1; i < n_msgs; i++)
  288.             {
  289.             /* If they have the same subject, try to link them */
  290.             if (msgs[i].msg_subj == msgs[i - 1].msg_subj)
  291.                 {
  292.                 /* Is the back one linked? */
  293.                 if (msgs[i - 1].msg_up != msgs[i].msg_num)
  294.                     {
  295.                     /* Link it up and mark it for later */
  296.                     msgs[i - 1].msg_up = msgs[i].msg_num;
  297.                     msgs[i - 1].msg_flags = MSG_LINK_CHANGED;
  298.                     }
  299.                 /* Is this one linked? */
  300.                 if (msgs[i].msg_down != msgs[i - 1].msg_num)
  301.                     {
  302.                     /* Link it up and mark it for later */
  303.                     msgs[i].msg_down = msgs[i - 1].msg_num;
  304.                     msgs[i].msg_flags = MSG_LINK_CHANGED;
  305.                     }
  306.                 }
  307.             else
  308.                 {
  309.                 /* Unlink it if necessary */
  310.                 if (msgs[i].msg_down != 0)
  311.                     {
  312.                     msgs[i].msg_down = 0;
  313.                     msgs[i].msg_flags = MSG_LINK_CHANGED;
  314.                     }
  315.                 if (msgs[i - 1].msg_up != 0)
  316.                     {
  317.                     msgs[i - 1].msg_up = 0;
  318.                     msgs[i - 1].msg_flags = MSG_LINK_CHANGED;
  319.                     }
  320.                 }
  321.             }
  322.  
  323.         /* Re-link the reply chains */
  324.         relink ();
  325.  
  326.         if (go_directory (dir_drive2, NULL))
  327.             {
  328.             printf ("Cannot seem to change directories back to %s\n", dir_drive2);
  329.             }
  330.         if (go_directory (dir_drive1, NULL))
  331.             {
  332.             printf ("Cannot seem to change directories back to %s\n", dir_drive1);
  333.             exit (1);
  334.             }
  335.         if (!quiet)
  336.             printf ("\n");
  337.         }
  338.  
  339.     if (!quiet)
  340.        printf ("Done!\n");
  341.     exit (0);
  342. }
  343.  
  344. unsigned int calcrc(ptr)
  345. char *ptr;
  346. {
  347.     unsigned int crc;
  348.     int j;
  349.     unsigned char r;
  350.  
  351.     crc = 0;
  352.     j = 0;
  353.     while (j++ <= 40)
  354.         {
  355.         if (*ptr)
  356.             {
  357.             r = toupper (*ptr);
  358.             ++ptr;
  359.             }
  360.         else
  361.             r = 0;
  362.  
  363.         crc = xcrc (crc, r);
  364.         }
  365.     return (crc);
  366. }
  367.  
  368. int compare (arg1, arg2)
  369. MSG_TYP     *arg1, *arg2;
  370. {
  371.     if (arg1->msg_subj != arg2->msg_subj)
  372.         return (arg1->msg_subj - arg2->msg_subj);
  373.     else
  374.         return (arg1->msg_num - arg2->msg_num);
  375. }
  376.  
  377. void update ()
  378. {
  379.     int f, st;
  380.     char junk[64];
  381.  
  382.     sprintf (junk, "%d.MSG", msgs[n_msgs].msg_num);
  383.  
  384.     if ((f = fast_open (junk, O_RDONLY|O_BINARY)) == -1)
  385.         {
  386.         printf ("Error opening '%s'\n", junk);
  387.         msgs[n_msgs].msg_num = 0;
  388.         return;
  389.         }
  390.  
  391.     if (fast_read (f, (char *) &msg_tmp, sizeof (MSG)) != sizeof (MSG))
  392.         {
  393.         printf ("Error reading '%s'\n", junk);
  394.         msgs[n_msgs].msg_num = 0;
  395.         (void) fast_close (f);
  396.         return;
  397.         }
  398.     (void) fast_close (f);
  399.     /* Get CRC of Subj: field */
  400.     if ((toupper(msg_tmp.subj[0]) == 'R') &&
  401.         (toupper(msg_tmp.subj[1]) == 'E') &&
  402.         (msg_tmp.subj[2] == ':') &&
  403.         (msg_tmp.subj[3] == ' '))
  404.         {
  405.         st = 4;
  406.         }
  407.     else
  408.         st = 0;
  409.     msgs[n_msgs].msg_subj = calcrc (&(msg_tmp.subj[st]));
  410.     msgs[n_msgs].msg_up = msg_tmp.up;
  411.     msgs[n_msgs].msg_down = msg_tmp.reply;
  412. }
  413.  
  414. void read_msg_data ()
  415. {
  416.     int i;
  417.     char junk[64];
  418.     char name[20];
  419.  
  420.     sprintf (junk, "*.MSG");
  421.     (void) filedir (junk, 0, name, 0);
  422.     while (name[0] != '\0')
  423.         {
  424.         i = 0;
  425.         sscanf (name, "%d.", &i);
  426.         if (i > 1)
  427.             {
  428.             msgs[n_msgs].msg_num = i;
  429.             msgs[n_msgs].msg_flags = MSG_EXISTS;
  430.             update ();
  431.             ++n_msgs;
  432.             if (n_msgs >= MAX_MSGS)
  433.                 {
  434.                 break;
  435.                 }
  436.             }
  437.         (void) filedir (junk, 1, name, 0);
  438.         }
  439.    (void) qsort ((char *) msgs, n_msgs, sizeof (MSG_TYP), compare);
  440. }
  441.  
  442. void fancy_str (value)
  443. char *value;
  444. {
  445.     register char  *sptr;
  446.     char    lower = 0;
  447.  
  448.     sptr = value;
  449.  
  450.     if (sptr)
  451.         {                          /* don't touch any NULL pointers */
  452.         while (*sptr)
  453.             {
  454.             if (lower)
  455.                 {
  456.                 *sptr = tolower (*sptr);
  457.                 }
  458.             else
  459.                 {
  460.                 *sptr = toupper (*sptr);
  461.                 }
  462.  
  463.             lower = (isalnum (*sptr++));
  464.             }
  465.         }
  466. }
  467.  
  468. int get_system (where, ret_system)
  469. char *where;
  470. SYS  *ret_system;
  471. {
  472.     char     sys_file[64];
  473.     int      sys_input;
  474.     int      num;
  475.     int      ret;
  476.     char     *p;
  477.  
  478.     ret = ALL_OK;
  479.     sys_file[0] = '\0';
  480.     num = atoi (where);
  481.     if (!isdigit (where[0]))
  482.         {
  483.         strupr (where);
  484.         strcpy (ret_system->msgpath, where);
  485.         }
  486.     else
  487.     if (num == 0)
  488.         {
  489.         sprintf (sys_file, "%s%s", SYSNAME, DEF_EXT);
  490.         }
  491.     else
  492.         {
  493.         sprintf (sys_file, "%s%d%s", SYSNAME, num, DEF_EXT);
  494.         }
  495.  
  496.     if (sys_file[0] != '\0')
  497.         {
  498.         if ((sys_input = fast_open (sys_file, O_RDONLY|O_BINARY)) == -1)
  499.             {
  500.             printf ("\nError %d openning '%s', aborting.\n", sys_input, sys_file);
  501.             return (NO_SYSTEM);
  502.             }
  503.         else
  504.             {
  505.             if ((fast_read (sys_input, (char *) ret_system, sizeof (SYS))) == -1)
  506.                 {
  507.                 printf ("\nError -1 reading '%s', aborting.\n", sys_file);
  508.                 fast_close (sys_input);
  509.                 return (NO_SYSTEM);
  510.                 }
  511.             strupr (ret_system->msgpath);
  512.             fast_close (sys_input);
  513.             }
  514.         }
  515.     p = &(ret_system->msgpath[strlen (ret_system->msgpath) - 1]);
  516.     if ((*p == '\\') || (*p == '/'))
  517.         {
  518.         if ((p > ret_system->msgpath) && (*(p - 1) != ':'))
  519.             *p = '\0';
  520.         }
  521.     fancy_str (ret_system->msgpath);
  522.     num = go_directory (ret_system->msgpath, dir_drive2);
  523.     if (num == 0)
  524.         {
  525.         if (!quiet)
  526.             printf ("MsgLink using directory '%s'\n", ret_system->msgpath);
  527.         return (ret);
  528.         }
  529.     else
  530.         return (NO_GO);
  531. }
  532.  
  533. int get_opus (where, ret_system)
  534. char *where;
  535. _sys *ret_system;
  536. {
  537.     char sys_file[64];
  538.     int sys_input;
  539.     int num;
  540.     int ret;
  541.     char *p;
  542.  
  543.     ret = ALL_OK;
  544.     sys_file[0] = '\0';
  545.     num = atoi (where);
  546.     if (!isdigit (where[0]))
  547.         {
  548.         strupr (where);
  549.         strcpy (ret_system->msgpath, where);
  550.         }
  551.     else
  552.         sprintf (sys_file, "SYSTEM%02X.DAT", num);
  553.  
  554.     if (sys_file[0] != '\0')
  555.         {
  556.         if ((sys_input = fast_open (sys_file, O_RDONLY|O_BINARY)) == -1)
  557.             {
  558.             printf ("\nError %d openning '%s', aborting.\n", sys_input, sys_file);
  559.             return (NO_SYSTEM);
  560.             }
  561.         else
  562.             {
  563.             if ((fast_read (sys_input, (char *) ret_system, sizeof (_sys))) == -1)
  564.                 {
  565.                 printf ("\nError -1 reading '%s', aborting.\n", sys_file);
  566.                 fast_close (sys_input);
  567.                 return (NO_SYSTEM);
  568.                 }
  569.             strupr (ret_system->msgpath);
  570.             fast_close (sys_input);
  571.             }
  572.         }
  573.     p = &(ret_system->msgpath[strlen (ret_system->msgpath) - 1]);
  574.     if ((*p == '\\') || (*p == '/'))
  575.         {
  576.         if ((p > ret_system->msgpath) && (*(p-1) != ':'))
  577.             *p = '\0';
  578.         }
  579.     fancy_str (ret_system->msgpath);
  580.     num = go_directory (ret_system->msgpath, dir_drive2);
  581.     if (num == 0)
  582.         {
  583.         if (!quiet)
  584.             printf ("MsgLink using directory '%s'\n", ret_system->msgpath);
  585.         return (ret);
  586.         }
  587.     else
  588.         return (NO_GO);
  589. }
  590.  
  591. void relink ()
  592. {
  593.     int i, f;
  594.     MSG_TYP *mptr;
  595.  
  596.     if (!quiet)
  597.         printf ("Relinking reply chains...\n");
  598.     for (mptr = &msgs[1],i = 1; i < n_msgs; mptr++, i++)
  599.         {
  600.         if (mptr->msg_flags & MSG_LINK_CHANGED)
  601.             {
  602.             /* Create the name of this message */
  603.             sprintf (tmpjunk2, "%d.msg", mptr->msg_num);
  604.  
  605.             f = fast_open (tmpjunk2, O_RDWR|O_BINARY);
  606.             (void) fast_read (f, (char *) &msg_tmp, sizeof (MSG));
  607.             (void) fast_lseek (f, 0L, SEEK_SET);
  608.             msg_tmp.up = mptr->msg_up;
  609.             msg_tmp.reply = mptr->msg_down;
  610.             (void) fast_write (f, (char *) &msg_tmp, sizeof(MSG));
  611.             (void) fast_close (f);
  612.             }
  613.         }
  614. }
  615.  
  616. int go_directory (dir, save)
  617. char *dir;
  618. char *save;
  619. {
  620. #ifndef OS_2
  621.     unsigned num_drives;
  622. #endif
  623.     if (dir[1] == ':')
  624.         {
  625. #ifdef OS_2
  626.         (void)DosSelectDisk(toupper (dir[0]) - 'A' + 1);
  627. #else
  628.         _dos_setdrive(toupper (dir[0]) - 'A' + 1, &num_drives);
  629. #endif
  630.         if (save != NULL)
  631.             {
  632.             getcwd (save, 80);
  633.             }
  634.         }
  635.     return (chdir (dir));
  636. }
  637.  
  638. void msglink_usage ()
  639. {
  640.     printf ("/nUsage: MsgLink [-o] [-q] dir [dir] [dir] ...\n");
  641.     printf ("       MsgLink -f areas.lst [-o] [-q] [+areas.bbs]\n\n");
  642.     printf ("       Switches must be given in the order shown\n");
  643.     printf ("       Switches f, o and q can follow '/' or '-'\n");
  644.     printf ("       f = process echomail areas named in the areas.lst specified\n");
  645.     printf ("       o = Opus 1.1 operation\n");
  646.     printf ("       q = quiet operation\n");
  647.     printf ("       dir is a directory path, a SYSTEMxx.BBS/DAT number, or msg area name\n");
  648.     printf ("       areas.lst is a list of echomail areas to process\n");
  649.     printf ("       areas.bbs is the areas.bbs file to read to find the echomail areas\n");
  650.     exit (1);
  651. }
  652.