home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / BSRC_250.LZH / B_FRPROC.C < prev    next >
C/C++ Source or Header  |  1991-09-15  |  25KB  |  792 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-91, Bit Bucket Software Co., a Delaware Corporation. */
  11. /*                                                                          */
  12. /*                                                                          */
  13. /*                   BinkleyTerm File Request Processor                     */
  14. /*                                                                          */
  15. /*                                                                          */
  16. /*    For complete  details  of the licensing restrictions, please refer    */
  17. /*    to the License  agreement,  which  is published in its entirety in    */
  18. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.250.    */
  19. /*                                                                          */
  20. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  21. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  22. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  23. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  24. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  25. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  26. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  27. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  28. /*                                                                          */
  29. /*                                                                          */
  30. /* You can contact Bit Bucket Software Co. at any one of the following      */
  31. /* addresses:                                                               */
  32. /*                                                                          */
  33. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
  34. /* P.O. Box 460398                AlterNet 7:491/0                          */
  35. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  36. /*                                Internet f491.n343.z1.fidonet.org         */
  37. /*                                                                          */
  38. /* Please feel free to contact us at any time to share your comments about  */
  39. /* our software and/or licensing policies.                                  */
  40. /*                                                                          */
  41. /*                                                                          */
  42. /*  This module is based largely on a similar module in OPUS-CBCS V1.03b.   */
  43. /*  The original work is (C) Copyright 1987, Wynn Wagner III. The original  */
  44. /*  author has graciously allowed us to use his code in this work.          */
  45. /*                                                                          */
  46. /*--------------------------------------------------------------------------*/
  47.  
  48. /* Include this file before any other includes or defines! */
  49.  
  50. #include "includes.h"
  51.  
  52. static char *their_pwd;                         /* Password in REQ file */
  53. static char required_pwd[10];                   /* Password in OK file  */
  54. static int xfer_seconds;
  55.  
  56. int prep_match (char *, char *);
  57. int match (char *, char *);
  58. void run_prog (char *);
  59. int check_password (void);
  60. freq_abort (long, int (*)(long));
  61. int what_event (int);
  62. int what_event_sub (int, int, int, int, int, int);
  63.  
  64. int prep_match (char *template, char *buffer)
  65. {
  66.    register int i, delim;
  67.    register char *sptr;
  68.    int start;
  69.  
  70.    (void) memset (buffer, 0, 11);
  71.  
  72.    i = (int) strlen (template);
  73.    sptr = template;
  74.  
  75.  
  76.    for (start = i = 0; sptr[i]; i++)
  77.       if ((sptr[i] == '\\') || (sptr[i] == ':'))
  78.          start = i + 1;
  79.  
  80.    if (start)
  81.       sptr += start;
  82.    delim = 8;                                    /* last column for ? */
  83.  
  84.    (void) strupr (sptr);
  85.  
  86.    for (i = 0; *sptr && i < 12; sptr++)
  87.       switch (*sptr)
  88.          {
  89.          case '.':
  90.             if (i > 8)
  91.                return (-1);
  92.             while (i < 8)
  93.                {
  94.                buffer[i++] = ' ';
  95.                }
  96.             buffer[i++] = *sptr;
  97.             delim = 12;
  98.             break;
  99.  
  100.          case '*':
  101.             while (i < delim)
  102.                {
  103.                buffer[i++] = '?';
  104.                }
  105.             break;
  106.  
  107.          default:
  108.             buffer[i++] = *sptr;
  109.             break;
  110.  
  111.          }                                       /* switch */
  112.  
  113.    while (i < 12)
  114.       {
  115.  
  116. /* dean suggests:
  117.  
  118.       buffer[i++] = (i == delim) ? '.' : ((i > delim) ? '?' : ' ');
  119.  
  120.    to replace the if/else below... 
  121. */
  122.       if (i == 8)
  123.          buffer[i++] = '.';
  124.       else buffer[i++] = ' ';
  125.       }
  126.  
  127.    buffer[i] = '\0';
  128.  
  129.    return 0;
  130. }
  131.  
  132. int match (char *s1, char *s2)
  133. {
  134.    register char *i, *j;
  135.  
  136.    i = s1;
  137.    j = s2;
  138.  
  139.    while (*i)
  140.       {
  141.       if ((*j != '?') && (*i != *j))
  142.          {
  143.          return 1;
  144.          }
  145.       i++;
  146.       j++;
  147.       }
  148.  
  149.    return 0;
  150. }
  151.  
  152. /*--------------------------------------------------------------------------*/
  153. /* Process file requests from the remote system. The filespec requested is  */
  154. /* turned into a local filespec if possible, then transferred via the       */
  155. /* caller-supplied routine.                                                 */
  156. /*--------------------------------------------------------------------------*/
  157.  
  158. int n_frproc (char *request, int nfiles,
  159.               int (*callback)(char *), int (*calltime)(long))
  160. {
  161.    register int i;
  162.    register int j = 0;
  163.    static char s[80];
  164.    static char s1[80];
  165.    static char s2[80];
  166.    char *p;
  167.  
  168.    FILE *approved;
  169.    struct FILEINFO dta;
  170.    struct stat st;
  171.    char *sptr;
  172.  
  173.    char *after_pwd;
  174.    long updreq = 0L;
  175.    char updtype = 0;
  176.    int saved_nfiles;
  177.  
  178.    char our_wildcard[15];
  179.    char their_wildcard[15];
  180.    int mfunc;
  181.    int magic_state = 0;
  182.    int tried_about = 0;
  183.  
  184.    int failure_reason = 1;                      /* 1 = not available */
  185.                                                 /* 2 = no update     */
  186.                                                 /* 3 = bad password  */
  187.    if (freq_accum.time == 0L)
  188.       freq_accum.time = (long)time(NULL);
  189.  
  190.    approved = NULL;
  191.    their_pwd = NULL;
  192.    after_pwd = NULL;
  193.    (void) strcpy (s1, request);
  194.  
  195.    /*--------------------------------------------------------------------*/
  196.    /* Fix up the file name                                               */
  197.    /*--------------------------------------------------------------------*/
  198.    for (i = 0; request[i]; i++)
  199.       {
  200.       if (request[i] <= ' ')
  201.          {
  202.          request[i++] = '\0';
  203.          j = i;
  204.          break;
  205.          }
  206.       }
  207.    
  208.    if (j)
  209.       {
  210.       /* If we have a '!', find the end of the password, point j
  211.          past it, then truncate and fold if necessary. This leaves
  212.          j properly aligned for other fields.
  213.        */
  214.  
  215.       if (request[j] == '!')
  216.          {
  217.          their_pwd = request + (++j);
  218.          for (; request[j]; j++)
  219.             {
  220.             if (request[j] <= ' ')
  221.                {
  222.                request[j++] = '\0';
  223.                break;
  224.                }
  225.             }
  226.  
  227.          if (strlen (their_pwd) > 6)
  228.             their_pwd[6] = '\0';
  229.  
  230.          (void) fancy_str (their_pwd);
  231.          }
  232.  
  233.       /* Test for update/backdate request */
  234.  
  235.       if (request[j] == '+' || request[j] == '-')
  236.          {
  237.          updtype = request[j++];
  238.          updreq = atol (&request[j]);
  239.          }
  240.       }      
  241.  
  242.    if (!request[0])                             /* Still any filename?  */
  243.       return (nfiles);                          /* If not, return df=0. */
  244.  
  245.    if (freq_abort(0L, calltime))                /* Any reason to abort? */
  246.       return (-2);                              /* If so, return error. */
  247.  
  248.  
  249.    /*--------------------------------------------------------------------*/
  250.    /* Initialization(s)                                                  */
  251.    /*--------------------------------------------------------------------*/
  252.    i = 0;
  253.    sptr = NULL;
  254.  
  255.    (void) strupr (request);
  256.    status_line ("*%s %s (%s)", (updreq != 0L) ? MSG_TXT(M_UPDATE) : MSG_TXT(M_FILE), MSG_TXT(M_REQUEST), request);
  257.  
  258.    saved_nfiles = nfiles;
  259.  
  260.    /*--------------------------------------------------------------------*/
  261.    /* Reserved words                                                     */
  262.    /*--------------------------------------------------------------------*/
  263.    if (!strcmp (request, "FILES"))
  264.       {
  265.       if (CURRENT.rq_FILES)
  266.          (void) strcpy (s, CURRENT.rq_FILES);
  267.       else
  268.          {
  269.          s[0] = '\0';
  270.          sptr = MSG_TXT(M_NO_AVAIL);
  271.          }
  272.       goto avail;
  273.       }
  274.  
  275.    else if (!strcmp (request, "ABOUT"))
  276.       {
  277.       s[0] = '\0';
  278.       goto avail;
  279.       }
  280.  
  281.    (void) prep_match (request, their_wildcard);
  282.  
  283.    /*--------------------------------------------------------------------*/
  284.    /* See if the file is approved for transmission                       */
  285.    /*--------------------------------------------------------------------*/
  286.    if ((approved = share_fopen (CURRENT.rq_OKFile, read_ascii, DENY_WRITE)) == NULL)
  287.       {
  288.       (void) got_error (MSG_TXT(M_OPEN_MSG), CURRENT.rq_OKFile);
  289.       goto err;
  290.       }
  291.  
  292.    while (!feof (approved))
  293.       {
  294.       /* If we were magic, set flag to cause exit if we don't do it again */
  295.       if (magic_state)
  296.          magic_state = 1;                       /* 1 means done if no @ */
  297.  
  298.       s[0] = required_pwd[0] = '\0';
  299.  
  300.       (void) fgets (s, 78, approved);
  301.  
  302.       for (i = 0; s[i]; i++)
  303.          if (s[i] == 0x09)
  304.             s[i] = ' ';
  305.          else if (s[i] < ' ')
  306.             s[i] = '\0';
  307.  
  308.       if (!s[0] || s[0] == ';')
  309.          continue;
  310.  
  311.       /*--------------------------------------------------------------*/
  312.       /* Check for transaction-level password                         */
  313.       /*--------------------------------------------------------------*/
  314.       for (i = 0; s[i]; i++)
  315.          {
  316.          if (s[i] == ' ')
  317.             {
  318.             s[i] = '\0';
  319.             if (s[i + 1] == '!')
  320.                {
  321.                (void) strncpy (required_pwd, s + i + 2, 8);
  322.                if (strlen (required_pwd) > 6)
  323.                   required_pwd[6] = '\0';
  324.  
  325.                after_pwd = skip_blanks (s + i + 1);
  326.                while (*after_pwd && (!isspace (*after_pwd)))
  327.                   ++after_pwd;
  328.  
  329.                if (*after_pwd)
  330.                   ++after_pwd;
  331.  
  332.                for (i = 0; required_pwd[i]; i++)
  333.                   if (required_pwd[i] <= ' ')
  334.                      required_pwd[i] = '\0';
  335.  
  336.                break;
  337.                }
  338.             else
  339.                {
  340.                after_pwd = skip_blanks (s + i + 1);
  341.                break;
  342.                }
  343.             }
  344.          else if (s[i] < ' ')
  345.             s[i] = '\0';
  346.          }
  347.  
  348.       if (!s[0])
  349.          continue;
  350.  
  351.       if (strchr ("@+$",s[0]) != NULL)
  352.          {
  353.          /* Magic name or function */
  354.          if ((s[0] != '>') && stricmp (&s[1], request))
  355.             continue;
  356.  
  357.          /* Name matches, check password */
  358.          if (!(check_password ()))
  359.             {
  360.             failure_reason = 3;      /* Password doesn't match */
  361.             continue;                /* Go on                  */
  362.             }
  363.          
  364.          mfunc = 0;
  365.  
  366.          if (s[0] == '$')
  367.             {
  368.             (void) sprintf (s2, after_pwd, remote_addr.Net,
  369.                               remote_addr.Node, remote_addr.Point);
  370.             mfunc = 1;
  371.             }
  372.  
  373.          if (s[0] == '+')
  374.             {
  375.             (void) sprintf (s, " %d %d %d %d", remote_addr.Zone, remote_addr.Net,
  376.                               remote_addr.Node, remote_addr.Point);
  377.             (void) strcpy (s2, s1);
  378.             (void) strcat (s2, s);
  379.             mfunc = 2;
  380.             }
  381.  
  382.          if (mfunc)
  383.             {
  384.             run_prog (s2);
  385.             goto check_HLO;
  386.             }
  387.          
  388.          if (s[0] == '@')
  389.             {
  390.             (void) strcpy (s, after_pwd);
  391.             magic_state = 2;                    /* Will be reset up above */
  392.             }
  393.          }
  394.  
  395.       /*
  396.        * We're past the magic stuff here. So check for whether this is
  397.        * a new iteration of a magic loop that somehow didn't catch.
  398.        * If not, then check out the filespec we have on this line.
  399.        */
  400.  
  401.       if (magic_state == 1)
  402.          goto check_HLO;
  403.  
  404.       j = 1;
  405.  
  406.       if (Netmail_Session == 2)
  407.          SENDBYTE (NUL);
  408.  
  409.       if (!dfind (&dta, s, 0))
  410.          {
  411.          do
  412.             {
  413.             if (!(--j))                         /* If we've looped a bit  */
  414.                {
  415.                i = freq_abort (0L, calltime);
  416.                if (i)                           /* See if we want to quit */
  417.                   {
  418.                   if (i == 1)                   /* Yes, why? Carrier?     */
  419.                      goto finished;             /* uh-huh -- get out fast */
  420.                   else
  421.                      {
  422.                      failure_reason = i;        /* Not carrier, get reason*/
  423.                      goto make_RSP;             /* Make a .RSP file       */
  424.                      }
  425.                   }
  426.                j = 10;                          /* No, reset bounds       */
  427.                }
  428.  
  429.             if (!magic_state)                   /* If not "magic",        */
  430.                {
  431.                if (prep_match (dta.name, our_wildcard) < 0)
  432.                   continue;
  433.  
  434.                if (match (our_wildcard, their_wildcard))
  435.                   continue;
  436.  
  437.                /* File names match, check password now */
  438.  
  439.                if (!check_password ())
  440.                   {
  441.                   failure_reason = 3;      /* Password doesn't match */
  442.                   continue;                /* Go on                  */
  443.                   }
  444.                }
  445.  
  446.             /* Good password, get full path with wildcard from OKFILE */
  447.  
  448.             (void) strcpy (s2, s);
  449.  
  450.             /* Subtract the wild card file name, keep path */
  451.  
  452.             if ((p = strrchr (s2, '\\')) != NULL)
  453.                 *++p = '\0';
  454.             else s2[0] = '\0';
  455.  
  456.             /* Then add in the exact name found */
  457.  
  458.             (void) strcat (s2, dta.name);
  459.  
  460.             /* Got full filename, now do file update validation */
  461.  
  462.             if (updtype && !stat (s2, &st))
  463.                {
  464.                if ((updtype == '+' && (st.st_atime <= updreq))
  465.                ||  (updtype == '-' && (st.st_atime >= updreq)))
  466.                   {
  467.                   failure_reason = 2;      /* No update available    */
  468.                   continue;                /* Go on                  */
  469.                   }
  470.                }
  471.  
  472.             i = freq_abort (dta.size, calltime); /* Check file size  */
  473.             if (i)                         /* See if we want to quit */
  474.                {
  475.                if (i == 1)                 /* Yes, why? Carrier?     */
  476.                   goto finished;           /* uh-huh -- get out fast */
  477.                else
  478.                   {
  479.                   failure_reason = i;      /* Not carrier, get reason*/
  480.                   goto make_RSP;           /* Make a .RSP file       */
  481.                   }
  482.                }
  483.  
  484.             /* Everything is OK, send the file if we can */
  485.             CLEAR_INBOUND ();
  486.             if ((*callback) (s2))
  487.                {
  488.                ++nfiles;
  489.                freq_accum.bytes += dta.size;
  490.                freq_accum.CumTime += xfer_seconds;
  491.                ++freq_accum.files;
  492.                }
  493.             j = 1;                               /* Force abort test */
  494.             }
  495.          while (!dfind (&dta, s, 1));
  496.          }                                       /* if dfind */
  497.  
  498.       else status_line (MSG_TXT(M_OKFILE_ERR), s);  /* if not dfind */
  499.  
  500.       s[0] = '\0';
  501.       }                                          /* while not eof(approved) */
  502.  
  503.    if (saved_nfiles != nfiles)
  504.       failure_reason = 9;
  505.  
  506. make_RSP:
  507.  
  508.    s[0] = '\0';                                  /* Initialize string     */
  509.    if ((CURRENT.rq_Template != NULL) && (dexists(CURRENT.rq_Template )))
  510.       {
  511.       Make_Response(s1, failure_reason);         /* Build a response      */
  512.       (void) strcpy(s, s1);                             /* Copy it for xmission  */
  513.       }
  514.  
  515.    if ((!s[0]) && (failure_reason > 3))          /* if no .RSP file,      */
  516.       goto finished;                             /* give it up            */
  517.  
  518.    /*--------------------------------------------------------------------*/
  519.    /* File requested not found, send the system ABOUT file.              */
  520.    /*--------------------------------------------------------------------*/
  521. avail:
  522.  
  523.    if (!s[0])
  524.       {
  525.       if (CURRENT.rq_About)
  526.          (void) strcpy (s, CURRENT.rq_About);
  527.       else
  528.          {
  529.          if (tried_about)
  530.             {
  531.             sptr = MSG_TXT(M_NO_ABOUT);
  532.             goto err;
  533.             }
  534.          else
  535.             {
  536.             ++tried_about;
  537.             (void) strcpy (s1, request);
  538.             failure_reason = 1;        /* Didn't find what we wanted */
  539.             goto make_RSP;             /* Make a .RSP file       */
  540.             }
  541.          }
  542.       }
  543.  
  544.    CLEAR_INBOUND ();
  545.    if ((*callback) (s))
  546.          ++nfiles;
  547.  
  548.    goto finished;
  549.  
  550.    /*--------------------------------------------------------------------*/
  551.    /* See if we generated a .QLO file somehow, if so send listed files   */
  552.    /*--------------------------------------------------------------------*/
  553. check_HLO:
  554.  
  555.    CLEAR_INBOUND ();
  556.    (void) do_FLOfile ("Q", callback);
  557.  
  558.    /*--------------------------------------------------------------------*/
  559.    /* Maybe the magic request made a conventional .FLO file, try that too*/
  560.    /*--------------------------------------------------------------------*/
  561.  
  562.    *ext_flags = 'F';
  563.    (void) do_FLOfile (ext_flags, callback);
  564.    goto finished;
  565.  
  566.    /*--------------------------------------------------------------------*/
  567.    /* Error return                                                       */
  568.    /*--------------------------------------------------------------------*/
  569. err:
  570.    if (sptr)
  571.       status_line ("!%s %s %s: %s",
  572.          (updreq != 0L) ? MSG_TXT(M_UPDATE) : MSG_TXT(M_FILE),
  573.          MSG_TXT(M_REQUEST), &(MSG_TXT(M_ERROR)[1]), sptr);
  574.  
  575. finished:
  576.    if (approved)
  577.       (void) fclose (approved);
  578.  
  579.    return (nfiles);
  580. }
  581.  
  582. void run_prog (char *s)
  583. {
  584.    struct baud_str saved_baud;
  585.  
  586.    status_line ("%s '%s'", MSG_TXT(M_EXECUTING), s);
  587.    if (fullscreen && un_attended)
  588.       {
  589.       screen_clear ();
  590.       }
  591.    scr_printf (&(MSG_TXT(M_EXECUTING)[1]));
  592.    scr_printf (s);
  593.    scr_printf ("\r\n");
  594.    vfossil_cursor (1);
  595.    saved_baud = cur_baud;
  596.    b_spawn (s);
  597.    vfossil_cursor (0);
  598.    if (fullscreen && un_attended)
  599.       {
  600.       screen_clear ();
  601.       sb_dirty ();
  602.       opening_banner ();
  603.       mailer_banner ();
  604.       }
  605.  
  606.    (void) set_baud (saved_baud.rate_value, 0); /* Restore baud rate */
  607. }
  608.  
  609. int check_password ()
  610. {
  611.    if (required_pwd[0])
  612.       {
  613.       (void) fancy_str (required_pwd);
  614.       if ((stricmp (required_pwd, their_pwd)) &&
  615.           (stricmp (required_pwd, remote_password)))
  616.          {
  617.          status_line (MSG_TXT(M_FREQ_PW_ERR),
  618.                                required_pwd,
  619.                                their_pwd,
  620.                                remote_password
  621.                      );
  622.  
  623.          return (0);
  624.          }
  625.       }
  626.    return (1);
  627. }
  628.  
  629. int freq_abort (long file_size, int (*calltime)(long))
  630. {
  631.    int w_event;
  632.    int xfer_time;
  633.  
  634.    if (!CARRIER)
  635.       {
  636.       status_line (MSG_TXT(M_CARRIER_REQUEST_ERR));
  637.       return (1);
  638.       }
  639.  
  640.    if ((CURRENT.rq_Limit != 0) 
  641.    &&  ((freq_accum.files + 1) >= CURRENT.rq_Limit))
  642.       {
  643.       status_line (MSG_TXT(M_FREQ_LIMIT));
  644.       return (4);
  645.       }
  646.  
  647.    if ((CURRENT.byte_Limit != 0L)
  648.    &&  ((freq_accum.bytes + file_size) > CURRENT.byte_Limit))
  649.       {
  650.       status_line (MSG_TXT(M_BYTE_LIMIT));
  651.       return (6);
  652.       }
  653.  
  654.    /* Get file time in seconds for comparison with quota */
  655.  
  656.    if (file_size != 0L)
  657.       xfer_time = calltime (file_size);
  658.    else
  659.       xfer_time = 0;
  660.  
  661.    xfer_seconds = xfer_time;
  662.  
  663.    if ((CURRENT.time_Limit != 0)
  664.    &&  (((long)time(NULL) + xfer_time - freq_accum.time) > CURRENT.time_Limit))
  665.       {
  666.       status_line (MSG_TXT(M_TIME_LIMIT));
  667.       return (7);
  668.       }
  669.  
  670.    xfer_time /= 60;               /* We want minutes for event calculations */
  671.  
  672.    w_event = what_event (xfer_time);
  673.    if ((w_event >= 0) && (w_event != cur_event))
  674.       {
  675.       if (e_ptrs[w_event].behavior & MAT_NOREQ)
  676.          {
  677.          status_line (MSG_TXT(M_EVENT_OVERRUN));
  678.          return (5);
  679.          }
  680.       }
  681.    else if (w_event == -2)
  682.          {
  683.          status_line (MSG_TXT(M_EVENT_OVERRUN));
  684.          return (5);
  685.          }
  686.  
  687.    return (0);
  688. }
  689.  
  690. int what_event (int delta_time)
  691. {
  692.    time_t long_time;
  693.    struct tm *tm;
  694.    
  695.    int now;
  696.    int tomorrow = 0;
  697.    int our_time;
  698.    int w_event;
  699.    int save_time;
  700.  
  701.    /* Get the current time into a structure */
  702.  
  703.    (void) time (&long_time);
  704.    tm = localtime (&long_time);
  705.  
  706.    /* Calculate minutes since midnight      */
  707.  
  708.    now = tm->tm_hour * 60 + tm->tm_min;
  709.  
  710.    /* Then number of minutes past midnight at end of delta_time */
  711.  
  712.    save_time = our_time = delta_time + now;
  713.  
  714.    /* Is the end in Tomorrow? (Sounds like a soap opera, eh?) */
  715.  
  716.    if (1440 < our_time)
  717.       {
  718.       tomorrow = 1;                     /* Remember that we've wrapped        */
  719.       our_time = 1439;                  /* Set event end = 23:59 for now      */
  720.       }
  721.  
  722.    /* Test "today," and if we find an event, get the hell out                 */
  723.  
  724.    w_event = what_event_sub (tm->tm_mon, tm->tm_wday, tm->tm_mday,
  725.                               now, our_time, 0);
  726.  
  727.    if (w_event != -1)
  728.       return w_event;
  729.  
  730.    /*
  731.     * If we need to test tomorrow, figure out all the salient info
  732.     * on what tomorrow is, and test that.
  733.     */
  734.  
  735.    if (tomorrow)
  736.       {
  737.       long_time += 86400L;              /* Any time tomorrow will do.         */
  738.       tm = localtime (&long_time);
  739.       w_event = what_event_sub (tm->tm_mon, tm->tm_wday, tm->tm_mday,
  740.                                  0, (save_time - 1440), 1);
  741.       }
  742.  
  743.    return w_event;
  744. }
  745.  
  746. int what_event_sub (int cur_mon, int cur_day, int cur_mday,
  747.                     int now, int our_time, int tomorrow)
  748. {
  749.    int i;
  750.  
  751.    cur_day = 1 << cur_day;             /* Make cur_day a bit mask             */
  752.  
  753.    for (i = 0; i < num_events; i++ )
  754.       {
  755.  
  756.       /* If this is an event we need to think about (i.e., it started
  757.        * before the end of the transfer, and ends after "now") ...
  758.        */
  759.  
  760.       if ((our_time >= e_ptrs[i].minute)
  761.       &&  (now <= ( e_ptrs[i].minute + e_ptrs[i].length)))
  762.          {
  763.          /* And if it's on a day we care about ... */
  764.  
  765.          if ((cur_day & e_ptrs[i].days)
  766.          &&  ((!e_ptrs[i].day) || (e_ptrs[i].day == (char)cur_mday))
  767.          &&  ((!e_ptrs[i].month) || (e_ptrs[i].month == (char)cur_mon)))
  768.             {
  769.             /* Don't do events that have been exited already unless
  770.              * the tomorrow flag is set (in which case, no events have
  771.              * occurred, have they?)
  772.              */
  773.  
  774.             if (!tomorrow
  775.             &&  (e_ptrs[i].last_ran == (char) cur_mday)
  776.             &&  (e_ptrs[i].behavior & MAT_SKIP))
  777.                continue;
  778.  
  779.             /* If the event we are considering does not allow requests,
  780.              * then this is a bugger we are looking for. Return its index.
  781.              */
  782.  
  783.             if ((e_ptrs[i].behavior & MAT_NOREQ))
  784.                return i;
  785.             }                          /* end of if ((cur_day & ... ))        */
  786.          }                             /* end of if ( our_time >= ... )       */
  787.       }                                /* end of for ( ... )                  */
  788.    return -1;
  789. }
  790.  
  791.  
  792.