home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1996 October / PCO_10.ISO / filesbbs / bsrc_260.arj / SRC.ZIP / b_frproc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-20  |  31.2 KB  |  1,141 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software, Co.                       */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          Freely Available<tm> Software.                 */
  7. /*        \ 1011 /                                                          */
  8. /*         ------                                                           */
  9. /*                                                                          */
  10. /*              (C) Copyright 1987-96, Bit Bucket Software Co.              */
  11. /*                                                                          */
  12. /*                                                                          */
  13. /*                                                                          */
  14. /*                    BinkleyTerm File Request Processor                    */
  15. /*                                                                          */
  16. /*                                                                          */
  17. /*    For complete  details  of the licensing restrictions, please refer    */
  18. /*    to the License  agreement,  which  is published in its entirety in    */
  19. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.260.    */
  20. /*                                                                          */
  21. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  22. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  23. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  24. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  25. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  26. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  27. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  28. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  29. /*                                                                          */
  30. /*                                                                          */
  31. /* You can contact Bit Bucket Software Co. at any one of the following      */
  32. /* addresses:                                                               */
  33. /*                                                                          */
  34. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
  35. /* P.O. Box 460398                AlterNet 7:42/1491                        */
  36. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  37. /*                                Internet f491.n343.z1.fidonet.org         */
  38. /*                                                                          */
  39. /* Please feel free to contact us at any time to share your comments about  */
  40. /* our software and/or licensing policies.                                  */
  41. /*                                                                          */
  42. /*                                                                          */
  43. /*  This module is based largely on a similar module in OPUS-CBCS V1.03b.   */
  44. /*  The original work is (C) Copyright 1987, Wynn Wagner III. The original  */
  45. /*  author has graciously allowed us to use his code in this work.          */
  46. /*                                                                          */
  47. /*--------------------------------------------------------------------------*/
  48.  
  49. /* Include this file before any other includes or defines! */
  50.  
  51. #include "includes.h"
  52.  
  53. #define AREA_ID    0x54414441L    /* "ADAT" */
  54.  
  55. #define MAX_ALEN    10            /* Max length of usr.msg[] and usr.files[]  */
  56. #define MAX_OVR        16            /* Maximum # of override privs per area     */
  57. #define NUM_MENU    256            /* Max. # of options in a menu file         */
  58. #define MAXCLASS    12            /* number of possible priv levels           */
  59.  
  60. /* New Max 2.xx format for MAXFILES.IDX.  The file is simply an array of    *
  61.  * these structures.                                                        */
  62.  
  63. struct _maxfile
  64. {
  65.     byte name[12];
  66.     word areaofs;
  67.     word fileofs;
  68. };
  69.  
  70. struct _override
  71. {
  72.     signed short priv;            /* Override priv level */
  73.     unsigned long lock;            /* Override lock setting */
  74.  
  75.     byte ch;                    /* First letter of menu option to override  */
  76.     byte fill;                    /* Reserved by Maximus */
  77. };
  78.  
  79. struct _area
  80. {
  81.     long id;                    /* Unique identifier for AREA.DAT structure.*
  82.                                  * Should be AREA_ID, above.                */
  83.  
  84.     word struct_len;              /* Length of _area structure -- this needs  *
  85.                                  * only to be read from the first record in *
  86.                                  * an area data file, since it can be       *
  87.                                  * assumed to remain the same throughout the*
  88.                                  * entire file.  This is GUARANTEED to be at*
  89.                                  * offset four for this and all future      *
  90.                                  * versions of this structure.              */
  91.  
  92.     word areano;                  /* OBSOLETE. Two-byte integer representation*
  93.                                  * of the area name. Use area.name instead. */
  94.  
  95.     byte name[40];                  /* String format of area's name.  USE THIS! */
  96.  
  97.     /************************************************************************/
  98.     /**                        Message Area Information                    **/
  99.     /************************************************************************/
  100.  
  101.     word type;                      /* Message base type.  MSGTYPE_SDM = *.MSG. *
  102.                                  * MSGTYPE_SQUISH = SquishMail.  (Constants *
  103.                                  * are in MSGAPI.H)                         */
  104.  
  105.     byte msgpath[80];              /* Path to messages                         */
  106.     byte msgname[40];              /* The 'tag' of area, used in ECHOTOSS.LOG  */
  107.     byte msginfo[80];              /* The DIR.BBS-like desc for msg section    */
  108.     byte msgbar[80];              /* Barricade file for message area          */
  109.     byte origin[62];              /* The ORIGIN line for this area            */
  110.  
  111.     short msgpriv;                  /* This is the priv required to access the  *
  112.                                  * msg section of this area.                */
  113.     byte fill0;                      /* The lock for the message area (obsolete) */
  114.  
  115.     byte fill1;
  116.  
  117.     short origin_aka;            /* The AKA number to use on the origin line.*
  118.                                  * See the normal SysOp documentation on    *
  119.                                  * the "Origin" statement, for info on how  *
  120.                                  * this number is used.                     */
  121.  
  122.     /************************************************************************/
  123.     /**                        File Area Information                       **/
  124.     /************************************************************************/
  125.  
  126.     byte filepath[80];          /* Path for downloads                       */
  127.     byte uppath[80];              /* Path for uploads                         */
  128.     byte filebar[80];              /* Barricade file for file areas            */
  129.     byte filesbbs[80];          /* Path to FILES.BBS-like catalog for area  */
  130.     byte fileinfo[80];          /* The DIR.BBS-like desc for file section   */
  131.  
  132.     short filepriv;                  /* The priv required to access the file     *
  133.                                  * section of this area.                    */
  134.     byte fill15;                  /* The locks for the file area (obsolete)   */
  135.     byte fill2;
  136.  
  137.     /************************************************************************/
  138.     /**                      Miscellaneous Information                     **/
  139.     /************************************************************************/
  140.  
  141.     byte msgmenuname[13];    /* Alternate *.MNU name to use for msg.area     */
  142.     byte filemenuname[13];    /* Alternate *.MNU name to use for file area    */
  143.  
  144.     word attrib[MAXCLASS];    /* This is an array of attributes for the       *
  145.                              * msg/file areas.  These are dependant on PRIV *
  146.                              * level.  Once you have the CLASS number for a *
  147.                              * particular user (via Find_Class_Number()),you*
  148.                              * can find the attributes for that particular  *
  149.                              * priv level like this: "area.attrib[class]"   *
  150.                              * ...which will get you the attribute for that *
  151.                              * priv level.                                  */
  152.  
  153.     /************************************************************************/
  154.     /**                      Stuff hacked on later                         **/
  155.     /************************************************************************/
  156.  
  157.     struct _override movr[MAX_OVR];    /* Override privs for msg/file areas    */
  158.     struct _override fovr[MAX_OVR];
  159.  
  160.     unsigned long msglock;    /* 32-bit locks for message areas               */
  161.     unsigned long filelock;    /* 32-bit locks for file areas                  */
  162.  
  163.     word killbyage;            /* MAXREN: max # of days to keep msgs in area   */
  164.                             /*         (use 0 for no deletion by age)       */
  165.     word killbynum;            /* MAXREN: max # of msgs to keep in area (use 0 */
  166.                             /*         for no deletion by #msgs.)           */
  167.  
  168. };
  169.  
  170. static char *their_pwd;            /* Password in REQ file */
  171. static char required_pwd[10];    /* Password in OK file  */
  172. static int xfer_seconds;
  173.  
  174. int prep_match (char *, char *);
  175. int match (char *, char *);
  176. void run_prog (char *);
  177. int check_password (void);
  178. int freq_abort (long, int (*)(long));
  179. int what_event (int);
  180. int what_event_sub (int, int, int, int, int, int);
  181.  
  182. int 
  183. prep_match (char *template, char *buffer)
  184. {
  185.     register int i, delim;
  186.     register char *sptr;
  187.     int start;
  188.  
  189.     (void) memset (buffer, 0, 11);
  190.  
  191.     i = (int) strlen (template);
  192.     sptr = template;
  193.  
  194.     for (start = i = 0; sptr[i]; i++)
  195.         if ((sptr[i] == '\\') || (sptr[i] == ':'))
  196.             start = i + 1;
  197.  
  198.     if (start)
  199.         sptr += start;
  200.     delim = 8;                    /* last column for ? */
  201.  
  202.     (void) strupr (sptr);
  203.  
  204.     for (i = 0; *sptr && i < 12; sptr++)
  205.         switch (*sptr)
  206.         {
  207.         case '.':
  208.             if (i > 8)
  209.                 return (-1);
  210.             while (i < 8)
  211.             {
  212.                 buffer[i++] = ' ';
  213.             }
  214.             buffer[i++] = *sptr;
  215.             delim = 12;
  216.             break;
  217.  
  218.         case '*':
  219.             while (i < delim)
  220.             {
  221.                 buffer[i++] = '?';
  222.             }
  223.             break;
  224.  
  225.         default:
  226.             buffer[i++] = *sptr;
  227.             break;
  228.  
  229.         }                        /* switch */
  230.  
  231.     while (i < 12)
  232.     {
  233.         if (i == 8)
  234.             buffer[i++] = '.';
  235.         else
  236.             buffer[i++] = ' ';
  237.     }
  238.  
  239.     buffer[i] = '\0';
  240.  
  241.     return 0;
  242. }
  243.  
  244. int 
  245. match (char *s1, char *s2)
  246. {
  247.     register char *i, *j;
  248.  
  249.     i = s1;
  250.     j = s2;
  251.  
  252.     while (*i)
  253.     {
  254.         if ((*j != '?') && (*i != *j))
  255.         {
  256.             return ((int) (*i - *j));
  257.         }
  258.         i++;
  259.         j++;
  260.     }
  261.  
  262.     return 0;
  263. }
  264.  
  265. /*--------------------------------------------------------------------------*/
  266. /* Process file requests from the remote system. The filespec requested is  */
  267. /* turned into a local filespec if possible, then transferred via the       */
  268. /* caller-supplied routine.                                                 */
  269. /*--------------------------------------------------------------------------*/
  270.  
  271. int 
  272. n_frproc (char *request, int nfiles,
  273.     int (*callback) (char *), int (*calltime) (long))
  274. {
  275.     register int i;
  276.     register int j = 0;
  277.     static char s[80];
  278.     static char s1[80];
  279.     static char s2[80];
  280.     char *p;
  281.  
  282.     FILE *approved;
  283.     struct FILEINFO dta = {0};
  284.     struct stat st;
  285.     char *sptr;
  286.  
  287.     char *after_pwd;
  288.     long updreq = 0L;
  289.     char updtype = 0;
  290.     int saved_nfiles;
  291.  
  292.     char our_wildcard[15];
  293.     char their_wildcard[15];
  294.     int mfunc;
  295.     int magic_state = 0;
  296.     int tried_about = 0;
  297.  
  298.     int failure_reason = 1;        /* 1 = not available */
  299.                                 /* 2 = no update     */
  300.                                 /* 3 = bad password  */
  301.     struct _area area;
  302.     struct _maxfile filmax;
  303.     int fmax = 0, fdat = 0, slen = 0;
  304.     long fmaxpos = 0L;
  305.     unsigned int fmaxstep = 30;
  306.     long fmaxmax = 0L;
  307.     long fmaxsiz = (long) sizeof (struct _maxfile);
  308.  
  309.     if (freq_accum.time == 0L)
  310.         freq_accum.time = (long) time (NULL);
  311.  
  312.     approved = NULL;
  313.     their_pwd = NULL;
  314.     after_pwd = NULL;
  315.     (void) strcpy (s1, request);
  316.  
  317.     /*----------------------------------------------------------------------*/
  318.     /* Fix up the file name                                                 */
  319.     /*----------------------------------------------------------------------*/
  320.  
  321.     for (i = 0; request[i]; i++)
  322.     {
  323.         if (request[i] <= ' ')
  324.         {
  325.             request[i++] = '\0';
  326.             j = i;
  327.             break;
  328.         }
  329.  
  330.         if ((request[i] == ':') || (request[i] == '\\'))
  331.         {
  332.             request[0] = '\0';
  333.             j = 0;
  334.             break;
  335.         }
  336.     }
  337.  
  338.     if (j)
  339.     {
  340.       /* If we have a '!', find the end of the password, point j
  341.          past it, then truncate and fold if necessary. This leaves
  342.          j properly aligned for other fields. */
  343.  
  344.         if (request[j] == '!')
  345.         {
  346.             their_pwd = request + (++j);
  347.             for (; request[j]; j++)
  348.             {
  349.                 if (request[j] <= ' ')
  350.                 {
  351.                     request[j++] = '\0';
  352.                     break;
  353.                 }
  354.             }
  355.  
  356.             if (strlen (their_pwd) > 6)
  357.                 their_pwd[6] = '\0';
  358.  
  359.             (void) fancy_str (their_pwd);
  360.         }
  361.  
  362.         /* Test for update/backdate request */
  363.  
  364.         if (request[j] == '+' || request[j] == '-')
  365.         {
  366.             updtype = request[j++];
  367. #ifdef ANSI_TIME_T
  368.             updreq = atol (&request[j]) + ANSI_TIME_T_DELTA;
  369. #else
  370.             updreq = atol (&request[j]);
  371. #endif
  372.         }
  373.     }
  374.  
  375.     if (!request[0])                /* Still any filename?  */
  376.         return (nfiles);            /* If not, return df=0. */
  377.  
  378.     if (freq_abort (0L, calltime))    /* Any reason to abort? */
  379.         return (-2);                /* If so, return error. */
  380.  
  381.     /*----------------------------------------------------------------------*/
  382.     /* Initialization(s)                                                    */
  383.     /*----------------------------------------------------------------------*/
  384.  
  385.     i = 0;
  386.     sptr = NULL;
  387.  
  388.     (void) strupr (request);
  389.     status_line ("*%s %s (%s)", (updreq != 0L) ? MSG_TXT (M_UPDATE) : MSG_TXT (M_FILE), MSG_TXT (M_REQUEST), request);
  390.  
  391.     saved_nfiles = nfiles;
  392.  
  393.     /*----------------------------------------------------------------------*/
  394.     /* Reserved words                                                       */
  395.     /*----------------------------------------------------------------------*/
  396.  
  397.     if (!strcmp (request, "FILES"))
  398.     {
  399.         if (CURRENT.rq_FILES)
  400.             (void) strcpy (s, CURRENT.rq_FILES);
  401.         else
  402.         {
  403.             s[0] = '\0';
  404.             sptr = MSG_TXT (M_NO_AVAIL);
  405.         }
  406.         goto avail;
  407.     }
  408.  
  409.     else if (!strcmp (request, "ABOUT"))
  410.     {
  411.         s[0] = '\0';
  412.         goto avail;
  413.     }
  414.  
  415.     (void) prep_match (request, their_wildcard);
  416.  
  417.     /*----------------------------------------------------------------------*/
  418.     /* See if the file is approved for transmission                         */
  419.     /*----------------------------------------------------------------------*/
  420.  
  421.     if ((approved = share_fopen (CURRENT.rq_OKFile, read_ascii, DENY_WRITE)) == NULL)
  422.     {
  423.         (void) got_error (MSG_TXT (M_OPEN_MSG), CURRENT.rq_OKFile);
  424.         goto err;
  425.     }
  426.  
  427.     while (!feof (approved))
  428.     {
  429.         /* If we were magic, set flag to cause exit if we don't do it again */
  430.  
  431.         if (magic_state)
  432.             magic_state = 1;    /* 1 means done if no @ */
  433.  
  434.         s[0] = required_pwd[0] = '\0';
  435.  
  436.         (void) fgets (s, 78, approved);
  437.  
  438.         for (i = 0; s[i]; i++)
  439.             if (s[i] == 0x09)
  440.                 s[i] = ' ';
  441.             else if (s[i] < ' ')
  442.                 s[i] = '\0';
  443.  
  444.         if (!s[0] || s[0] == ';')
  445.             continue;
  446.  
  447.         /*--------------------------------------------------------------*/
  448.         /* Check for transaction-level password                         */
  449.         /*--------------------------------------------------------------*/
  450.  
  451.         for (i = 0; s[i]; i++)
  452.         {
  453.             if (s[i] == ' ')
  454.             {
  455.                 s[i] = '\0';
  456.                 if (s[i + 1] == '!')
  457.                 {
  458.                     (void) strncpy (required_pwd, s + i + 2, 8);
  459.                     if (strlen (required_pwd) > 6)
  460.                         required_pwd[6] = '\0';
  461.  
  462.                     after_pwd = skip_blanks (s + i + 1);
  463.                     while (*after_pwd && (!isspace (*after_pwd)))
  464.                         ++after_pwd;
  465.  
  466.                     if (*after_pwd)
  467.                         ++after_pwd;
  468.  
  469.                     for (i = 0; required_pwd[i]; i++)
  470.                         if (required_pwd[i] <= ' ')
  471.                             required_pwd[i] = '\0';
  472.  
  473.                     break;
  474.                 }
  475.                 else
  476.                 {
  477.                     after_pwd = skip_blanks (s + i + 1);
  478.                     break;
  479.                 }
  480.             }
  481.             else if (s[i] < ' ')
  482.                 s[i] = '\0';
  483.         }
  484.  
  485.         if (!s[0])
  486.             continue;
  487.  
  488.         if (strchr ("@+$", s[0]) != NULL)
  489.         {
  490.             /* Magic name or function */
  491.  
  492.             if ((s[0] != '>') && stricmp (&s[1], request))
  493.                 continue;
  494.  
  495.             /* Name matches, check password */
  496.  
  497.             if (!(check_password ()))
  498.             {
  499.                 failure_reason = 3;    /* Password doesn't match */
  500.                 continue;            /* Go on                  */
  501.             }
  502.  
  503.             mfunc = 0;
  504.  
  505.             if (s[0] == '$')
  506.             {
  507.                 (void) sprintf (s2, after_pwd, remote_addr.Net,
  508.                     remote_addr.Node, remote_addr.Point);
  509.                 mfunc = 1;
  510.             }
  511.  
  512.             if (s[0] == '+')
  513.             {
  514.                 (void) sprintf (s, " %d %d %d %d", remote_addr.Zone, remote_addr.Net,
  515.                     remote_addr.Node, remote_addr.Point);
  516.                 (void) strcpy (s2, s1);
  517.                 (void) strcat (s2, s);
  518.                 mfunc = 2;
  519.             }
  520.  
  521.             if (mfunc)
  522.             {
  523.                 run_prog (s2);
  524.                 goto check_HLO;
  525.             }
  526.  
  527.             if (s[0] == '@')
  528.             {
  529.                 (void) strcpy (s, after_pwd);
  530.                 magic_state = 2;    /* Will be reset up above */
  531.             }
  532.         }
  533.  
  534.       /*
  535.        * We're past the magic stuff here. So check for whether this is
  536.        * a new iteration of a magic loop that somehow didn't catch.
  537.        * If not, then check out the filespec we have on this line.
  538.        */
  539.  
  540.         if (magic_state == 1)
  541.             goto check_HLO;
  542.  
  543.         j = 1;
  544.  
  545.         if (Netmail_Session == 2)
  546.             SENDBYTE (NUL);
  547.  
  548.         /*--------------------------------------------------------------*/
  549.         /* Check MAXFILES.IDX                                           */
  550.         /*--------------------------------------------------------------*/
  551.  
  552.         if ((s[0] == '*') && (max_areadat != NULL))
  553.         {
  554.  
  555.             p = s;
  556.             p++;
  557.  
  558.             if ((fmax = share_open (p, O_RDONLY | O_BINARY, DENY_NONE)) == -1)
  559.             {
  560.                 (void) got_error (MSG_TXT (M_OPEN_MSG), p);
  561.                 fmax = 0;
  562.                 goto err;
  563.             }
  564.  
  565.             if ((fdat = share_open (max_areadat, O_RDONLY | O_BINARY, DENY_NONE)) == -1)
  566.             {
  567.                 (void) got_error (MSG_TXT (M_OPEN_MSG), max_areadat);
  568.                 (void) close (fmax);
  569.                 fmax = fdat = 0;
  570.                 goto err;
  571.             }
  572.  
  573.         /* Read the first record of the file, to grab the structure-length     *
  574.          * byte.
  575.          */
  576.  
  577.             (void) read (fdat, &area, sizeof (struct _area));
  578.  
  579.             slen = area.struct_len;
  580.  
  581.             (void) stat (p, &st);
  582.             fmaxmax = st.st_size / fmaxsiz;
  583.             if (fmaxmax > 5000L)
  584.                 fmaxstep = 60;
  585.  
  586.             if (abs (loglevel) == 5)
  587.                 status_line (MSG_TXT (M_MAXFILE_SCANNING), fmaxmax, fmaxstep, p);
  588.  
  589.             /* original         while (!eof (fmax)) */
  590.             for (;;)
  591.             {
  592.  
  593.                 if (fmaxstep)
  594.                 {
  595.                     fmaxpos += fmaxstep;
  596.                     if (fmaxpos >= fmaxmax)
  597.                     {
  598.                         fmaxpos -= (long) fmaxstep;
  599.                         fmaxstep = 0;
  600.                     }
  601.                     lseek (fmax, fmaxpos * fmaxsiz, SEEK_SET);
  602.                 }
  603.  
  604.                 /* original         (void) read (fmax, &filmax, (unsigned)fmaxsiz); */
  605.  
  606.                 /* This should work same as the eof test and be more portable */
  607.  
  608.                 if (read (fmax, &filmax, (unsigned) fmaxsiz) != (int) fmaxsiz)
  609.                     break;
  610.  
  611.                 if (!(--j))                        /* If we've looped a bit  */
  612.                 {
  613.                     i = freq_abort (0L, calltime);
  614.                     if (i)                        /* See if we want to quit */
  615.                     {
  616.                         (void) close (fmax);
  617.                         (void) close (fdat);
  618.                         fmax = fdat = 0;
  619.                         if (i == 1)                /* Yes, why? Carrier?     */
  620.                             goto finished;        /* uh-huh -- get out fast */
  621.                         else
  622.                         {
  623.                             failure_reason = i;    /* Not carrier, get reason*/
  624.                             goto make_RSP;        /* Make a .RSP file       */
  625.                         }
  626.                     }
  627.                     j = 10;                        /* No, reset bounds       */
  628.                 }
  629.  
  630.                 filmax.fileofs = filmax.areaofs;/* save the offset... :-) */
  631.                 filmax.name[12] = '\0';
  632.  
  633.                 if (prep_match ((char *) filmax.name, our_wildcard) < 0)
  634.                     continue;
  635.  
  636.                 i = match (our_wildcard, their_wildcard);
  637.  
  638.                 if (i < 0)
  639.                     continue;
  640.                 else
  641.                 {
  642.                     if (fmaxstep)
  643.                     {
  644.                         fmaxpos -= (long) fmaxstep;
  645.                         fmaxstep = 0;
  646.                         lseek (fmax, fmaxpos * fmaxsiz, SEEK_SET);
  647.                         continue;
  648.                     }
  649.                     else
  650.                         if (i > 0)
  651.                             break;
  652.                 }
  653.  
  654.                 fmaxstep = 0;
  655.  
  656.                 /* File names match, check security now */
  657.  
  658.                 lseek (fdat, (long) filmax.fileofs * (long) slen, SEEK_SET);
  659.                 read (fdat, &area, sizeof (struct _area));
  660.  
  661.                 if (CURRENT.security < area.filepriv)
  662.                 {
  663.                     failure_reason = 3;            /* Security doesn't match */
  664.                     if (abs (loglevel) == 5)
  665.                         status_line (MSG_TXT (M_MAX_SECURITY_MISMATCH), (int) CURRENT.security,
  666.                             (int) area.filepriv);
  667.                     continue;                    /* Go on                  */
  668.                 }
  669.  
  670.                 /* Add in the exact name found */
  671.  
  672.                 (void) strcpy (s2, (char *) area.filepath);
  673.                 (void) strcat (s2, (char *) filmax.name);
  674.  
  675.                 /* Now find the "real" file */
  676.  
  677.                 if ((i = stat (s2, &st)) != -1)
  678.                 {
  679.  
  680.                     /* Got full filename, now do file update validation */
  681.  
  682.                     if (updtype && !i)
  683.                     {
  684.                         if ((updtype == '+' && (st.st_atime <= (time_t) updreq)) ||
  685.                             (updtype == '-' && (st.st_atime >= (time_t) updreq)))
  686.                         {
  687.                             failure_reason = 2;    /* No update available    */
  688.                             continue;            /* Go on                  */
  689.                         }
  690.                     }
  691.  
  692.                     i = freq_abort (st.st_size, calltime);    /* Check file size  */
  693.  
  694.                     if (i)                        /* See if we want to quit */
  695.                     {
  696.                         (void) close (fmax);
  697.                         (void) close (fdat);
  698.                         fmax = fdat = 0;
  699.                         if (i == 1)                /* Yes, why? Carrier?     */
  700.                             goto finished;        /* uh-huh -- get out fast */
  701.                         else
  702.                         {
  703.                             failure_reason = i;    /* Not carrier, get reason*/
  704.                             goto make_RSP;        /* Make a .RSP file       */
  705.                         }
  706.                     }
  707.  
  708.                     /* Everything is OK, send the file if we can */
  709.  
  710.                     CLEAR_INBOUND ();
  711.                     if ((*callback) (s2))
  712.                     {
  713.                         ++nfiles;
  714.                         freq_accum.bytes += st.st_size;
  715.                         freq_accum.CumTime += xfer_seconds;
  716.                         ++freq_accum.files;
  717.                     }
  718.                     j = 1;        /* Force abort test */
  719.                 }
  720.  
  721.             }                    /* end of while */
  722.  
  723.             /* close open max files */
  724.             if (fmax)
  725.                 (void) close (fmax);
  726.             if (fdat)
  727.                 (void) close (fdat);
  728.  
  729.         }                        /* end of MAXFILES.IDX check */
  730.         else
  731.         {
  732.             /*--------------------------------------------------------------*/
  733.             /* Check for any other line                                     */
  734.             /*--------------------------------------------------------------*/
  735.             if (!dfind (&dta, s, 0))
  736.             {
  737.                 do
  738.                 {
  739.                     if (!(--j))                    /* If we've looped a bit  */
  740.                     {
  741.                         i = freq_abort (0L, calltime);
  742.                         if (i)                    /* See if we want to quit */
  743.                         {
  744.                             if (i == 1)            /* Yes, why? Carrier?     */
  745.                                 goto finished;    /* uh-huh -- get out fast */
  746.                             else
  747.                             {
  748.                                 failure_reason = i;    /* No, get reason     */
  749.                                 goto make_RSP;    /* Make a .RSP file       */
  750.                             }
  751.                         }
  752.                         j = 10;                    /* No, reset bounds       */
  753.                     }
  754.  
  755.                     if (!magic_state)            /* If not "magic",        */
  756.                     {
  757.                         if (prep_match (dta.name, our_wildcard) < 0)
  758.                             continue;
  759.  
  760.                         if (match (our_wildcard, their_wildcard) != 0)
  761.                             continue;
  762.  
  763.                         /* File names match, check password now */
  764.  
  765.                         if (!check_password ())
  766.                         {
  767.                             failure_reason = 3;    /* Password doesn't match */
  768.                             continue;            /* Go on                  */
  769.                         }
  770.                     }
  771.  
  772.                     /* Good password, get path with wildcard from OKFILE  */
  773.  
  774.                     (void) strcpy (s2, s);
  775.  
  776.                     /* Subtract the wild card file name, keep path */
  777.  
  778.                     if ((p = strrchr (s2, '\\')) != NULL)
  779.                         *++p = '\0';
  780.                     else
  781.                         s2[0] = '\0';
  782.  
  783.                     /* Then add in the exact name found */
  784.  
  785.                     (void) strcat (s2, dta.name);
  786.  
  787.                     /* Got full filename, now do file update validation */
  788.  
  789.                     if (updtype && !stat (s2, &st))
  790.                     {
  791.                         if ((updtype == '+' && (st.st_atime <= (time_t) updreq))
  792.                             || (updtype == '-' && (st.st_atime >= (time_t) updreq)))
  793.                         {
  794.                             failure_reason = 2;    /* No update available    */
  795.                             continue;            /* Go on                  */
  796.                         }
  797.                     }
  798.  
  799.                     i = freq_abort (dta.size, calltime);/* Check file size*/
  800.                     if (i)                        /* See if we want to quit */
  801.                     {
  802.                         if (i == 1)                /* Yes, why? Carrier?     */
  803.                             goto finished;        /* uh-huh -- get out fast */
  804.                         else
  805.                         {
  806.                             failure_reason = i;    /* Not carrier, get reason*/
  807.                             goto make_RSP;        /* Make a .RSP file       */
  808.                         }
  809.                     }
  810.  
  811.                     /* Everything is OK, send the file if we can */
  812.  
  813.                     CLEAR_INBOUND ();
  814.                     if ((*callback) (s2))
  815.                     {
  816.                         ++nfiles;
  817.                         freq_accum.bytes += dta.size;
  818.                         freq_accum.CumTime += xfer_seconds;
  819.                         ++freq_accum.files;
  820.                     }
  821.                     j = 1;                        /* Force abort test */
  822.                 }
  823.                 while (!dfind (&dta, s, 1));
  824.                 (void) dfind (&dta, s, 2);
  825.             }                    /* if dfind */
  826.  
  827.             else
  828.                 status_line (MSG_TXT (M_OKFILE_ERR), s);    /* if not dfind */
  829.         }
  830.  
  831.         s[0] = '\0';
  832.     }    /* while not eof(approved) */
  833.  
  834.     if (saved_nfiles != nfiles)
  835.         failure_reason = 9;
  836.  
  837. make_RSP:
  838.  
  839.     s[0] = '\0';                            /* Initialize string     */
  840.     if ((CURRENT.rq_Template != NULL) && (dexists (CURRENT.rq_Template)))
  841.     {
  842.         Make_Response (s1, failure_reason);    /* Build a response      */
  843.         (void) strcpy (s, s1);                /* Copy it for xmission  */
  844.     }
  845.  
  846.     if ((!s[0]) && (failure_reason > 3))    /* if no .RSP file,      */
  847.         goto finished;                        /* give it up            */
  848.  
  849.     /*--------------------------------------------------------------------*/
  850.     /* File requested not found, send the system ABOUT file.              */
  851.     /*--------------------------------------------------------------------*/
  852.  
  853. avail:
  854.  
  855.     if (!s[0])
  856.     {
  857.         if (CURRENT.rq_About)
  858.             (void) strcpy (s, CURRENT.rq_About);
  859.         else
  860.         {
  861.             if (tried_about)
  862.             {
  863.                 sptr = MSG_TXT (M_NO_ABOUT);
  864.                 goto err;
  865.             }
  866.             else
  867.             {
  868.                 ++tried_about;
  869.                 (void) strcpy (s1, request);
  870.                 failure_reason = 1;    /* Didn't find what we wanted */
  871.                 goto make_RSP;        /* Make a .RSP file           */
  872.             }
  873.         }
  874.     }
  875.  
  876.     CLEAR_INBOUND ();
  877.     if ((*callback) (s))
  878.         ++nfiles;
  879.  
  880.     goto finished;
  881.  
  882.     /*--------------------------------------------------------------------*/
  883.     /* See if we generated a .QLO file somehow, if so send listed files   */
  884.     /*--------------------------------------------------------------------*/
  885.  
  886. check_HLO:
  887.  
  888.     CLEAR_INBOUND ();
  889.     (void) do_FLOfile ("Q", callback);
  890.  
  891.     /*--------------------------------------------------------------------*/
  892.     /* Maybe the magic request made a conventional .FLO file, try that too*/
  893.     /*--------------------------------------------------------------------*/
  894.  
  895.     *ext_flags = 'F';
  896.     (void) do_FLOfile (ext_flags, callback);
  897.     goto finished;
  898.  
  899.     /*--------------------------------------------------------------------*/
  900.     /* Error return                                                       */
  901.     /*--------------------------------------------------------------------*/
  902.  
  903. err:
  904.  
  905.     if (sptr)
  906.         status_line ("!%s %s %s: %s",
  907.             (updreq != 0L) ? MSG_TXT (M_UPDATE) : MSG_TXT (M_FILE),
  908.             MSG_TXT (M_REQUEST), &(MSG_TXT (M_ERROR)[1]), sptr);
  909.  
  910. finished:
  911.  
  912.     if (approved)
  913.         (void) fclose (approved);
  914.  
  915.     return (nfiles);
  916. }
  917.  
  918. void 
  919. run_prog (char *s)
  920. {
  921.     struct baud_str saved_baud;
  922.  
  923.     status_line ("%s '%s'", MSG_TXT (M_EXECUTING), s);
  924.     if (fullscreen && un_attended)
  925.     {
  926.         screen_clear ();
  927.     }
  928.     scr_printf (&(MSG_TXT (M_EXECUTING)[1]));
  929.     scr_printf (s);
  930.     scr_printf ("\r\n");
  931.     vfossil_cursor (1);
  932.     saved_baud = cur_baud;
  933.     b_spawn (s);
  934.     vfossil_cursor (0);
  935.     if (fullscreen && un_attended)
  936.     {
  937.         screen_clear ();
  938.         sb_dirty ();
  939.         opening_banner ();
  940.         mailer_banner ();
  941.     }
  942.  
  943.     (void) set_baud (saved_baud.rate_value, 0);    /* Restore baud rate */
  944. }
  945.  
  946. int 
  947. check_password ()
  948. {
  949.     if (required_pwd != NULL && required_pwd[0])
  950.     {
  951.         if (their_pwd == NULL && remote_password == NULL) 
  952.         {
  953.             status_line (MSG_TXT (M_FREQ_PW_ERR),
  954.                 required_pwd,
  955.                 "(NULL)",
  956.                 "(NULL)"
  957.                 );
  958.             return (0);
  959.         }
  960.         (void) fancy_str (required_pwd);
  961.         if ((stricmp (required_pwd, their_pwd)) &&
  962.             (remote_password == NULL || 
  963.             (remote_password != NULL && stricmp (required_pwd, remote_password))))
  964.         {
  965.             status_line (MSG_TXT (M_FREQ_PW_ERR),
  966.                 required_pwd,
  967.                 their_pwd,
  968.                 remote_password
  969.                 );
  970.  
  971.             return (0);
  972.         }
  973.     }
  974.     return (1);
  975. }
  976.  
  977. int 
  978. freq_abort (long file_size, int (*calltime) (long))
  979. {
  980.     int w_event;
  981.     int xfer_time;
  982.  
  983.     if (!CARRIER)
  984.     {
  985.         status_line (MSG_TXT (M_CARRIER_REQUEST_ERR));
  986.         return (1);
  987.     }
  988.  
  989.     if ((CURRENT.rq_Limit != 0)
  990.         && ((freq_accum.files + 1) >= CURRENT.rq_Limit))
  991.     {
  992.         status_line (MSG_TXT (M_FREQ_LIMIT));
  993.         return (4);
  994.     }
  995.  
  996.     if ((CURRENT.byte_Limit != 0L)
  997.         && ((freq_accum.bytes + file_size) > CURRENT.byte_Limit))
  998.     {
  999.         status_line (MSG_TXT (M_BYTE_LIMIT));
  1000.         return (6);
  1001.     }
  1002.  
  1003.     /* Get file time in seconds for comparison with quota */
  1004.  
  1005.     if (file_size != 0L)
  1006.         xfer_time = calltime (file_size);
  1007.     else
  1008.         xfer_time = 0;
  1009.  
  1010.     xfer_seconds = xfer_time;
  1011.  
  1012.     if ((CURRENT.time_Limit != 0)
  1013.         && (((long) time (NULL) + xfer_time - freq_accum.time) > CURRENT.time_Limit))
  1014.     {
  1015.         status_line (MSG_TXT (M_TIME_LIMIT));
  1016.         return (7);
  1017.     }
  1018.  
  1019.     xfer_time /= 60;            /* We want minutes for event calculations */
  1020.  
  1021.     w_event = what_event (xfer_time);
  1022.     if ((w_event >= 0) && (w_event != cur_event))
  1023.     {
  1024.         if (e_ptrs[w_event].behavior & MAT_NOREQ)
  1025.         {
  1026.             status_line (MSG_TXT (M_EVENT_OVERRUN));
  1027.             return (5);
  1028.         }
  1029.     }
  1030.     else if (w_event == -2)
  1031.     {
  1032.         status_line (MSG_TXT (M_EVENT_OVERRUN));
  1033.         return (5);
  1034.     }
  1035.  
  1036.     return (0);
  1037. }
  1038.  
  1039. int 
  1040. what_event (int delta_time)
  1041. {
  1042.     time_t long_time;
  1043.     struct tm *tm;
  1044.  
  1045.     int now;
  1046.     int tomorrow = 0;
  1047.     int our_time;
  1048.     int w_event;
  1049.     int save_time;
  1050.  
  1051.     /* Get the current time into a structure */
  1052.  
  1053.     (void) time (&long_time);
  1054.     tm = localtime (&long_time);
  1055.  
  1056.     /* Calculate minutes since midnight      */
  1057.  
  1058.     now = tm->tm_hour * 60 + tm->tm_min;
  1059.  
  1060.     /* Then number of minutes past midnight at end of delta_time */
  1061.  
  1062.     save_time = our_time = delta_time + now;
  1063.  
  1064.     /* Is the end in Tomorrow? (Sounds like a soap opera, eh?) */
  1065.  
  1066.     if (1440 < our_time)
  1067.     {
  1068.         tomorrow = 1;            /* Remember that we've wrapped        */
  1069.         our_time = 1439;        /* Set event end = 23:59 for now      */
  1070.     }
  1071.  
  1072.     /* Test "today," and if we find an event, get the hell out                 */
  1073.  
  1074.     w_event = what_event_sub (tm->tm_mon, tm->tm_wday, tm->tm_mday,
  1075.         now, our_time, 0);
  1076.  
  1077.     if (w_event != -1)
  1078.         return w_event;
  1079.  
  1080.    /*
  1081.     * If we need to test tomorrow, figure out all the salient info
  1082.     * on what tomorrow is, and test that.
  1083.     */
  1084.  
  1085.     if (tomorrow)
  1086.     {
  1087.         long_time += 86400L;    /* Any time tomorrow will do.         */
  1088.         tm = localtime (&long_time);
  1089.         w_event = what_event_sub (tm->tm_mon, tm->tm_wday, tm->tm_mday,
  1090.             0, (save_time - 1440), 1);
  1091.     }
  1092.  
  1093.     return w_event;
  1094. }
  1095.  
  1096. int 
  1097. what_event_sub (int cur_mon, int cur_day, int cur_mday,
  1098.     int now, int our_time, int tomorrow)
  1099. {
  1100.     int i;
  1101.  
  1102.     cur_day = 1 << cur_day;        /* Make cur_day a bit mask             */
  1103.  
  1104.     for (i = 0; i < num_events; i++)
  1105.     {
  1106.  
  1107.       /* If this is an event we need to think about (i.e., it started
  1108.        * before the end of the transfer, and ends after "now") ...
  1109.        */
  1110.  
  1111.         if ((our_time >= e_ptrs[i].minute)
  1112.             && (now <= (e_ptrs[i].minute + e_ptrs[i].length)))
  1113.         {
  1114.             /* And if it's on a day we care about ... */
  1115.  
  1116.             if ((cur_day & e_ptrs[i].days)
  1117.                 && ((!e_ptrs[i].day) || (e_ptrs[i].day == (char) cur_mday))
  1118.                 && ((!e_ptrs[i].month) || (e_ptrs[i].month == (char) cur_mon)))
  1119.             {
  1120.                /* Don't do events that have been exited already unless
  1121.                  * the tomorrow flag is set (in which case, no events have
  1122.                 * occurred, have they?)
  1123.                 */
  1124.  
  1125.                 if (!tomorrow
  1126.                     && (e_ptrs[i].last_ran == (char) cur_mday)
  1127.                     && (e_ptrs[i].behavior & MAT_SKIP))
  1128.                     continue;
  1129.  
  1130.                /* If the event we are considering does not allow requests,
  1131.                 * then this is a bugger we are looking for. Return its index.
  1132.                 */
  1133.  
  1134.                 if ((e_ptrs[i].behavior & MAT_NOREQ))
  1135.                     return i;
  1136.             }                    /* end of if ((cur_day & ... ))        */
  1137.         }                        /* end of if ( our_time >= ... )       */
  1138.     }                            /* end of for ( ... )                  */
  1139.     return -1;
  1140. }
  1141.