SCHED.C

15.8 KB fc51da7b815dc846…
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*                                                                          */
/*      ------------         Bit-Bucket Software, Co.                       */
/*      \ 10001101 /         Writers and Distributors of                    */
/*       \ 011110 /          Freely Available<tm> Software.                 */
/*        \ 1011 /                                                          */
/*         ------                                                           */
/*                                                                          */
/*  (C) Copyright 1987-91, Bit Bucket Software Co., a Delaware Corporation. */
/*                                                                          */
/*                                                                          */
/*           This module was originally written by Bob Hartman              */
/*                                                                          */
/*                                                                          */
/*                     BinkleyTerm Scheduler Routines                       */
/*                                                                          */
/*                                                                          */
/*    For complete  details  of the licensing restrictions, please refer    */
/*    to the License  agreement,  which  is published in its entirety in    */
/*    the MAKEFILE and BT.C, and also contained in the file LICENSE.250.    */
/*                                                                          */
/*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
/*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
/*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
/*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
/*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
/*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
/*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
/*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
/*                                                                          */
/*                                                                          */
/* You can contact Bit Bucket Software Co. at any one of the following      */
/* addresses:                                                               */
/*                                                                          */
/* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
/* P.O. Box 460398                AlterNet 7:491/0                          */
/* Aurora, CO 80046               BBS-Net  86:2030/1                        */
/*                                Internet f491.n343.z1.fidonet.org         */
/*                                                                          */
/* Please feel free to contact us at any time to share your comments about  */
/* our software and/or licensing policies.                                  */
/*                                                                          */
/*--------------------------------------------------------------------------*/

/* Include this file before any other includes or defines! */

#include "includes.h"


/**************************************************************************/
/*** This MUST be exactly 16 total bytes including the terminating null ***/
/*** or the routines read_sched() and write_sched() must be changed!!!! ***/
/**************************************************************************/
static char *BinkSched = PRDCT_SHRT "Schedule 08";      /* Version of scheduler   */


void find_event ()
{
   time_t long_time;
   struct tm *tm;
   
   int cur_day;
   int our_time;
   int i;
   char cmds[150];

   BINK_EVENT evt;

   /* Get the current time into a structure */

   (void) time (&long_time);
   tm = localtime (&long_time);

   cur_day = 1 << tm->tm_wday;

   our_time = (tm->tm_hour % 24) * 60 + (tm->tm_min % 60);

   cur_event = -1;

   if (tm->tm_mday != hist.which_day)
      {
      write_stats ();
      (void) memset (&hist, 0, sizeof (HISTORY));
      hist.which_day = tm->tm_mday;
      if (un_attended && fullscreen)
         {
         do_today ();
         sb_show ();
         }
      }

   /* Make the month 1-based instead of 0-based */
   tm->tm_mon += 1;

   /* Go through the events from top to bottom */
   for (i = 0; i < num_events; i++)
      {
      if (our_time >= e_ptrs[i].minute)
         {
         evt = e_ptrs[i];

         if ((cur_day & evt.days) &&
             ((!evt.day) || (evt.day == (char)tm->tm_mday)) &&
             ((!evt.month) || (evt.month == (char)tm->tm_mon)))
            {
            if (((our_time - evt.minute) < evt.length) ||
            ((our_time == evt.minute) && (evt.length == 0)) ||
            ((evt.behavior & MAT_FORCED) && (evt.last_ran != (char)tm->tm_mday)))
               {
               /* Are we not supposed to force old events */
               if (((our_time - evt.minute) > evt.length) && (noforce))
                  {
                  e_ptrs[i].last_ran = (char) tm->tm_mday;
                  continue;
                  }

               if (evt.last_ran != (char) tm->tm_mday)
                  {
                  cur_event = i;
                  do_ready (MSG_TXT(M_READY_WAITING));
                  status_line (MSG_TXT(M_STARTING_EVENT), i + 1);

                  if (!blank_on_key)
                     screen_blank = 0;

                  more_mail = 1;

                  /* Mark that this one is running */
                  e_ptrs[i].last_ran = (char) tm->tm_mday;

                  /*
                   * Mark that we have not yet skipped it. After all, it just
                   * started! 
                   */
                  e_ptrs[i].behavior &= ~MAT_SKIP;

                  /* Write out the schedule */
                  write_sched ();

                  /* If we are supposed to exit, then do it */
                  if (evt.errlevel[0])
                     {
                     status_line (MSG_TXT(M_EVENT_EXIT), evt.errlevel[0]);

                     screen_blank = 0;
                     errl_exit (evt.errlevel[0]);
                     }
                  else if (packer != NULL)
                     {
                     if (!blank_on_key)
                        screen_blank = 0;
                     status_line (MSG_TXT(M_CLEAN_PACK));
                     mdm_init (modem_busy);
                     exit_DTR ();
                     screen_clear ();
                     vfossil_cursor (1);
                     if (cleanup != NULL)
                        {
                        (void) strcpy (cmds, cleanup);
                        if (i >= 0)
                           (void) strcat (cmds, evt.cmd);
                        b_spawn (cmds);
                        }
                     (void) strcpy (cmds, packer);
                     if (i >= 0)
                        (void) strcat (cmds, evt.cmd);
                     b_spawn (cmds);
                     if (fullscreen)
                        {
                        screen_clear ();
                        sb_dirty ();
                        opening_banner ();
                        mailer_banner ();
                        }
                     RAISE_DTR ();
                     mdm_init (modem_init);
                     status_line (MSG_TXT(M_AFTER_CLEAN_PACK));
                     waitfor_line = timerset ((unsigned int)6000);
                     }

                  cur_event = i;
                  max_connects = evt.with_connect;
                  max_noconnects = evt.no_connect;
                  set_up_outbound ();
                  }
               else
                  {
                  /* Don't do events that have been exited already */
                  if (evt.behavior & MAT_SKIP)
                     continue;
                  }

               cur_event = i;

               if (evt.behavior & MAT_NOREQ)
                  {
                  matrix_mask &= ~TAKE_REQ;
                  no_requests = 1;
                  }
               else
                  {
                  matrix_mask |= TAKE_REQ;
                  no_requests = 0;
                  }

               if (evt.behavior & MAT_NOOUTREQ)
                  {
                  requests_ok = 0;
                  }
               else
                  {
                  requests_ok = 1;
                  }

               max_connects = evt.with_connect;
               max_noconnects = evt.no_connect;

               break;
               }
            }
         }
      }
}

void read_sched ()
{
   char temp1[80], temp2[80];
   struct stat buffer1, buffer2;

    HFILE stream;
    USHORT got;

   (void) strcpy (temp1, BINKpath);
   (void) strcpy (temp2, BINKpath);
   (void) strcat (temp1, PRDCT_PRFX ".Scd");
   (void) strcat (temp2, PRDCT_PRFX ".Evt");

   if (stat (temp1, &buffer1) == -1)
      {
      return;
      }

   if (stat (temp2, &buffer2) == -1)
      {
      (void) strcpy (temp2, BINKpath);
      (void) strcat (temp2, config_name);
      if (stat (temp2, &buffer2) == -1)
         {
         return;
         }
      }

   if ((buffer1.st_atime < buffer2.st_atime) ||
       (buffer1.st_size < sizeof (BINK_EVENT)))
      {
      return;
      }

  if ((stream = open (temp1, O_RDONLY|O_BINARY)) == -1)
      {
      return;
      }

   temp1[0] = '\0';
   (void) read (stream, temp1, 16);
   if (strcmp (temp1, BinkSched) != 0)
      {
      (void) close (stream);
      return;
      }

   (void) read (stream,  (char *) &hist, (int) sizeof (HISTORY));

   (void) _dos_read (stream, (char far *)e_ptrs, 
           (unsigned int) (buffer1.st_size - 16 - sizeof (HISTORY)), &got);

   got_sched = 1;

   num_events = (int) ((buffer1.st_size - 16 - sizeof (HISTORY)) / sizeof (BINK_EVENT));

   (void) close (stream);
   return;
}

void write_sched ()
{
   char temp1[80], temp2[80];
   int i;
   struct stat buffer1;
   struct utimbuf times;
   long t;

   HFILE stream;
   USHORT got;

   /* Get the current time */
   t = time (NULL);

   (void) strcpy (temp1, BINKpath);
   (void) strcpy (temp2, BINKpath);
   (void) strcat (temp1, PRDCT_PRFX ".Scd");
   (void) strcat (temp2, PRDCT_PRFX ".Evt");

   /* Get the current stat for .Evt file */

   if (stat (temp2, &buffer1) == -1)
      {
      (void) strcpy (temp2, BINKpath);
      (void) strcat (temp2, config_name);
      if (stat (temp2, &buffer1) == -1)
         {
         return;
         }
      }

   /*
    * If it is newer than current time, we have a problem and we must
    * reset the file date - yucky, but it will probably work 
    */
   if (t < buffer1.st_atime)
      {
      times.UT_ACTIME = buffer1.st_atime;
      times.modtime = buffer1.st_atime;
      status_line (MSG_TXT(M_DATE_PROBLEM));
      }
   else
      {
      times.UT_ACTIME = t;
      times.modtime = t;
      }

  if ((stream = open (temp1, O_CREAT|O_RDWR|O_BINARY, S_IREAD|S_IWRITE)) == -1)
      {
      return;
      }

   (void) write (stream, BinkSched, 16);
   (void) write (stream, (char *) &hist, (int) sizeof (HISTORY));

   for (i = 0; i < num_events; i++)
      {
      /* If it is skipped, but not dynamic, reset it */
      if ((e_ptrs[i].behavior & MAT_SKIP) &&
          (!(e_ptrs[i].behavior & MAT_DYNAM)))
         {
         e_ptrs[i].behavior &= ~MAT_SKIP;
         }

      }

   (void) _dos_write (stream, (char far *)e_ptrs, 
           (unsigned int) (num_events * sizeof (BINK_EVENT)), &got);

   (void) close (stream);

   (void) utime (temp1, (UTIMBUF *)&times);

   return;
}

void write_stats ()
{
   char temp1[80];
   FILE *f;

   (void) strcpy (temp1, BINKpath);
   (void) strcat (temp1, PRDCT_PRFX ".Day");

   if ((f = fopen (temp1, "wb")) == NULL)
      {
      return;
      }

   (void) fwrite (&hist, (int) sizeof (HISTORY), 1, f);

   (void) fclose (f);

   return;
}

int time_to_next (int skip_bbs)
{
   time_t long_time;
   struct tm *tm;
   
   int cur_day;
   int our_time;
   int i;
   int time_to;
   int guess;
   int nmin;

   /* Get the current time into a structure */

   (void) time (&long_time);
   tm = localtime (&long_time);

   our_time = tm->tm_hour * 60 + tm->tm_min;

   next_event = -1;
   cur_day = 1 << tm->tm_wday;

   /* A ridiculous number */
   time_to = 3000;

   /* Make the month 1-based instead of 0-based */
   tm->tm_mon += 1;

   /* Go through the events from top to bottom */
   for (i = 0; i < num_events; i++)
      {
      /* If it is the current event, skip it */
      if (cur_event == i)
         continue;

      /* If it is a BBS event, skip it */
      if (skip_bbs && e_ptrs[i].behavior & MAT_BBS)
         continue;

      /* If it was already run today, skip it */
      if (e_ptrs[i].last_ran == (char) tm->tm_mday)
         continue;

      /* If it doesn't happen today, skip it */
      if (!(e_ptrs[i].days & cur_day))
         continue;

      /* If not this day of the month, skip it */
      if ((e_ptrs[i].day) && (e_ptrs[i].day != (char)tm->tm_mday))
         continue;
      
      /* If not this month of the year, skip it */
      if ((e_ptrs[i].month) && (e_ptrs[i].month != (char)tm->tm_mon))
         continue;

      /* If it is earlier than now, skip it unless it is forced */
      if (e_ptrs[i].minute <= our_time)
         {
         if (!(e_ptrs[i].behavior & MAT_FORCED))
            {
            continue;
            }

         /* Hmm, found a forced event that has not executed yet */
         /* Give the guy 2 minutes and call it quits */
         guess = 2;
         }
      else
         {
         /* Calculate how far it is from now */
         guess = e_ptrs[i].minute - our_time;
         }

      /* If less than closest so far, keep it */
      if (time_to > guess)
         {
         time_to = guess;
         next_event = i;
         }
      }

   /* If we still have nothing, then do it again, starting at midnight */
   if (time_to >= 1441)
      {
      /* Calculate here to midnight */
      nmin = 1440 - our_time;

      /* Go to midnight */
      our_time = 0;

      /* Go to the next possible day */
      cur_day = (int) (((unsigned) cur_day) << 1);
      if (cur_day > DAY_SATURDAY)
         cur_day = DAY_SUNDAY;

      /* Go through the events from top to bottom */
      for (i = 0; i < num_events; i++)
         {
         /* If it is a BBS event, skip it */
         if (skip_bbs && e_ptrs[i].behavior & MAT_BBS)
            continue;

         /* If it doesn't happen today, skip it */
         if (!(e_ptrs[i].days & cur_day))
            continue;

         /* If not this day of the month, skip it */
         if ((e_ptrs[i].day) && (e_ptrs[i].day != (char)tm->tm_mday))
            continue;
      
         /* If not this month of the year, skip it */
         if ((e_ptrs[i].month) && (e_ptrs[i].month != (char)tm->tm_mon))
            continue;

         /* Calculate how far it is from now */
         guess = e_ptrs[i].minute + nmin;

         /* If less than closest so far, keep it */
         if (time_to > guess)
            {
            time_to = guess;
            next_event = i;
            }
         }
      }

   if (time_to > 1440)
      time_to = 1440;

   if (skip_bbs && (time_to < 1))
      time_to = 1;

   return (time_to);
}