Category : C Source Code
Archive   : BSRC_140.ZIP
Filename : SCHED.C
/* */
/* */
/* ------------ Bit-Bucket Software
/* \ 10001101 / Writers and Distributors of */
/* \ 011110 / No-Cost
/* \ 1011 / */
/* ------ KopyRong (K) 1987. ALL RIGHTS REVERSED. */
/* */
/* */
/* This module was written by Bob Hartman */
/* */
/* */
/* BinkleyTerm Scheduler Routines */
/* */
/* */
/* This software package is being distributed WITH FULL SOURCE CODE */
/* with the following conditions: 1) If anything awful happens */
/* because you use it (or don't use it), you accept full */
/* responsibility; 2) you don't start making tons of voice calls to */
/* the authors to complain or make suggestions about enhancements, */
/* useful or otherwise; 3) you do not reuse this code in commercial */
/* products without specific permission to do so from the authors; */
/* 4) If you find any problems you send fixes to the authors for */
/* inclusion in updates; 5) You find some way to express your */
/* appreciation for this method of distribution, either by writing */
/* code or application notes, or just sending along a "Thank You" */
/* message. */
/* */
/* There is copyrighted code in this product. We either wrote it */
/* ourselves or got permission to use it. Please don't force us to */
/* pay a lawyer -- have some respect for our motives and don't abuse */
/* this "license". */
/* */
/* */
/*--------------------------------------------------------------------------*/
#include
#include
#include
#include
#include
#include "com.h"
#include "xfer.h"
#include "sched.h"
extern char *skip_blanks ();
extern char *BINKpath;
EVENT *e_ptrs[256];
int num_events = 0;
int cur_event = -1;
int got_sched = 0;
int noforce = 0;
int max_connects = 3;
int max_noconnects = 10000;
static char *BinkSched = "BinkSchedule 01"; /* Version of scheduler */
extern char no_requests;
extern char *skip_blanks ();
char *
skip_to_blank (string)
char *string;
{
while (*string && (!isspace (*string)))
++string;
return (string);
}
char *
start_time (e, p)
EVENT *e;
char *p;
{
int i, j;
if (sscanf (p, "%d:%d", &i, &j) != 2)
{
return NULL;
}
e->minute = i * 60 + j;
if ((e->minute < 0) || (e->minute > (24 * 60)))
{
return (NULL);
}
p = skip_to_blank (p);
return (p);
}
char *
end_time (e, p)
EVENT *e;
char *p;
{
int i, j, k;
if (sscanf (p, "%d:%d", &i, &j) != 2)
{
return NULL;
}
k = i * 60 + j;
if ((k > (24 * 60)) || (k < 0))
{
return (NULL);
}
if (k < e->minute)
{
printf ("Ending time wraps through midnight - not allowed\n");
return (NULL);
}
e->length = k - e->minute;
p = skip_to_blank (p);
return (p);
}
parse_event (e_line)
char *e_line;
{
int i, j, j1, j2;
char *p, *p1;
EVENT *e;
/* If we already have a schedule, then forget it */
if (got_sched)
return (0);
/* Skip blanks to get to the days field */
p = skip_blanks (e_line);
/* Parse the days field */
e = (EVENT *) calloc (sizeof (EVENT), 1);
e->days = 0;
e->wait_time = 120;
while ((*p) && (!isspace (*p)))
{
switch (toupper (*p))
{
case 'S': /* Sunday or Saturday */
if (!strnicmp (p, "sun", 3))
{
e->days |= DAY_SUNDAY;
}
else
if (!strnicmp (p, "sat", 3))
{
e->days |= DAY_SATURDAY;
}
else /* Error condition */
{
goto err;
}
p += 3;
break;
case 'M': /* Monday */
if (!strnicmp (p, "mon", 3))
{
e->days |= DAY_MONDAY;
}
else /* Error condition */
{
goto err;
}
p += 3;
break;
case 'T': /* Tuesday or Thursday */
if (!strnicmp (p, "tue", 3))
{
e->days |= DAY_TUESDAY;
}
else
if (!strnicmp (p, "thu", 3))
{
e->days |= DAY_THURSDAY;
}
else /* Error condition */
{
goto err;
}
p += 3;
break;
case 'W': /* Wednesday, Week or Weekend */
if (!strnicmp (p, "wed", 3))
{
e->days |= DAY_WEDNESDAY;
p += 3;
}
else
if (!strnicmp (p, "week", 4))
{
e->days |= DAY_WEEK;
p += 4;
}
else
if (!strnicmp (p, "wkend", 5))
{
e->days |= DAY_WKEND;
p += 5;
}
else /* Error condition */
{
goto err;
}
break;
case 'F': /* Friday */
if (!strnicmp (p, "fri", 3))
{
e->days |= DAY_FRIDAY;
}
else /* Error condition */
{
goto err;
}
p += 3;
break;
case 'A': /* All */
if (!strnicmp (p, "all", 3))
{
e->days |= (DAY_WEEK | DAY_WKEND);
}
else /* Error condition */
{
goto err;
}
p += 3;
break;
default: /* Error condition */
goto err;
}
if (*p == '|')
++p;
}
/* Did we get something valid? */
if (e->days == 0)
{
goto err;
}
/* Skip blanks to get to the start-time field */
p = skip_blanks (p);
/* Parse the start-time field */
if ((p = start_time (e, p)) == NULL)
{
printf ("'%s' has an invalid START-TIME\n", e_line);
free (e);
return (1);
}
/* Give each event a default of 60 minutes */
e->length = 60;
/* Give each event a local cost of 0 */
e->node_cost = 0;
/* Give each event a default of T=3,10000 */
e->with_connect = 3;
e->no_connect = 10000;
/* While there are still things on the line */
while (*p)
{
/* Skip blanks to get to the next field */
p = skip_blanks (p);
/* switch to find what thing is being parsed */
switch (tolower (*p))
{
case '\0': /* No more stuff */
break;
case '0': /* Digits must be an ending time */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
/* Parse ending time */
if ((p = end_time (e, p)) == NULL)
{
printf ("'%s' has an invalid END-TIME\n", e_line);
free (e);
return (1);
}
break;
case ';': /* Comment */
case '%':
*p = '\0';
break;
case 'a': /* Average wait */
++p;
if (*p == '=')
{
++p;
if (isdigit (*p))
{
i = atoi (p);
if ((i > 1800) || (i < 0))
{
printf ("'%s' has bad AvgWait (higher than max of 1800 or less than min of 0)\n", e_line);
free (e);
return (1);
}
e->wait_time = i;
p = skip_to_blank (p);
break;
}
}
printf ("'%s' has a bad AvgWait code\n", e_line);
free (e);
return (1);
case 'b': /* BBS type event */
p = skip_to_blank (p);
e->behavior |= MAT_BBS;
break;
case 'c': /* #CM event */
p = skip_to_blank (p);
e->behavior |= MAT_CM;
break;
case 'd': /* Dynamic event */
p = skip_to_blank (p);
e->behavior |= MAT_DYNAM;
break;
case 'e': /* An errorlevel exit */
++p;
if (isdigit (*p))
{
i = *p - '0';
++p;
if ((*p == '=') && (i <= 5) && (i > 0))
{
++p;
if (isdigit (*p))
{
j = atoi (p);
e->errlevel[i - 1] = j;
p = skip_to_blank (p);
break;
}
}
}
printf ("'%s' has a bad Errorlevel code\n", e_line);
free (e);
return (1);
case 'f': /* Forced event */
p = skip_to_blank (p);
e->behavior |= MAT_FORCED;
break;
case 'l': /* Local only mail */
++p;
if (*p == '=')
{
++p;
if (isdigit (*p))
{
e->node_cost = atoi (p);
}
}
p = skip_to_blank (p);
e->behavior |= MAT_LOCAL;
break;
case 'm': /* Mailable 24 hours */
p = skip_to_blank (p);
e->behavior |= MAT_NOMAIL24;
break;
case 'n': /* No requests */
p = skip_to_blank (p);
e->behavior |= MAT_NOREQ;
break;
case 'r': /* Receive only */
p = skip_to_blank (p);
e->behavior |= MAT_NOOUT;
break;
case 's': /* Send only */
p = skip_to_blank (p);
e->behavior |= MAT_OUTONLY;
break;
case 't': /* Tries */
++p;
if (sscanf (p, "=%d,%d", &j1, &j2) != 2)
{
printf ("'%s' has a bad number of Tries\n", e_line);
return (1);
}
else
{
if ((j1 > 8) || (j1 < 1))
{
printf ("'%s' has a bad number of Tries\n", e_line);
return (1);
}
e->with_connect = j1;
e->no_connect = j2;
}
p = skip_to_blank (p);
break;
default: /* Error condition */
printf ("'%s' has something indecipherable\n", e_line);
free (e);
return (1);
}
}
/* Save it in the array of pointers */
e_ptrs[num_events++] = e;
/* Return that everything is cool */
return (0);
err:
printf ("'%s' has an invalid DAY field\n", e_line);
free (e);
return (1);
}
find_event ()
{
int cur_day;
int cur_hour;
int cur_minute;
int cur_mday;
int cur_mon;
int cur_year;
int junk, junk1;
int our_time;
int i;
int j;
/* Get the current time in minutes */
dostime (&cur_hour, &cur_minute, &junk, &junk);
our_time = cur_hour * 60 + cur_minute;
/* Get the current day of the week */
dosdate (&cur_mon, &cur_mday, &cur_year, &cur_day);
/* Make the month 0 based */
--cur_mon;
cur_day = 1 << cur_day;
cur_event = -1;
/* Go through the events from top to bottom */
for (i = 0; i < num_events; i++)
{
if (our_time >= e_ptrs[i]->minute)
{
if (cur_day & e_ptrs[i]->days)
{
if (((our_time - e_ptrs[i]->minute) < e_ptrs[i]->length) ||
((our_time == e_ptrs[i]->minute) && (e_ptrs[i]->length == 0)) ||
((e_ptrs[i]->behavior & MAT_FORCED) && (e_ptrs[i]->last_ran != cur_mday)))
{
/* Are we not supposed to force old events */
if (((our_time - e_ptrs[i]->minute) > e_ptrs[i]->length) && (noforce))
{
e_ptrs[i]->last_ran = cur_mday;
continue;
}
if (e_ptrs[i]->last_ran != cur_mday)
{
set_xy ("");
status_line (":Starting Event %d", i + 1);
/* Mark that this one is running */
e_ptrs[i]->last_ran = cur_mday;
/* Write out the schedule */
write_sched ();
/* If we are supposed to exit, then do it */
if (e_ptrs[i]->errlevel[0])
{
status_line ("#Exit at start of event with errorlevel %d",
e_ptrs[i]->errlevel[0]);
errl_exit (e_ptrs[i]->errlevel[0]);
}
}
else
{
/* Don't do events that have been exited already */
if (e_ptrs[i]->behavior & MAT_SKIP)
continue;
}
cur_event = i;
if (e_ptrs[i]->behavior & MAT_NOREQ)
{
ctl.matrix_mask &= ~TAKE_REQ;
no_requests = 1;
}
else
{
ctl.matrix_mask |= TAKE_REQ;
no_requests = 0;
}
max_connects = e_ptrs[i]->with_connect;
max_noconnects = e_ptrs[i]->no_connect;
break;
}
}
}
}
}
what_event ()
{
int cur_day;
int cur_hour;
int cur_minute;
int cur_mday;
int cur_mon;
int cur_year;
int junk, junk1;
int our_time;
int w_event;
int i;
int j;
/* Get the current time in minutes */
dostime (&cur_hour, &cur_minute, &junk, &junk);
our_time = cur_hour * 60 + cur_minute;
/* Get the current day of the week */
dosdate (&cur_mon, &cur_mday, &cur_year, &cur_day);
/* Make the month 0 based */
--cur_mon;
cur_day = 1 << cur_day;
w_event = -1;
/* Go through the events from top to bottom */
for (i = 0; i < num_events; i++)
{
if (our_time >= e_ptrs[i]->minute)
{
if (cur_day & e_ptrs[i]->days)
{
if (((our_time - e_ptrs[i]->minute) < e_ptrs[i]->length) ||
((our_time == e_ptrs[i]->minute) && (e_ptrs[i]->length == 0)) ||
((e_ptrs[i]->behavior & MAT_FORCED) && (e_ptrs[i]->last_ran != cur_mday)))
{
/* Are we not supposed to force old events */
if (((our_time - e_ptrs[i]->minute) > e_ptrs[i]->length) && (noforce))
{
e_ptrs[i]->last_ran = cur_mday;
continue;
}
if ((e_ptrs[i]->last_ran == cur_mday) &&
(e_ptrs[i]->behavior & MAT_SKIP))
{
/* Don't do events that have been exited already */
continue;
}
w_event = i;
break;
}
}
}
}
return (w_event);
}
read_sched ()
{
char temp1[80], temp2[80];
char *malloc ();
EVENT *sptr;
struct stat buffer1, buffer2;
FILE *f;
int i;
strcpy (temp1, BINKpath);
strcpy (temp2, BINKpath);
strcat (temp1, "Binkley.Scd");
strcat (temp2, "Binkley.Cfg");
if (stat (temp1, &buffer1))
{
return;
}
if (stat (temp2, &buffer2))
{
return;
}
if ((buffer1.st_atime < buffer2.st_atime) ||
(buffer1.st_size < sizeof (EVENT)))
{
return;
}
if ((sptr = (EVENT *) malloc ((int) buffer1.st_size - 16)) == NULL)
{
return;
}
if ((f = fopen (temp1, "rb")) == NULL)
{
return;
}
temp1[0] = '\0';
fread (temp1, 16, 1, f);
if (strcmp (temp1, BinkSched) != 0)
{
fclose (f);
return;
}
fread (sptr, (int) buffer1.st_size - 16, 1, f);
got_sched = 1;
num_events = (buffer1.st_size - 16) / sizeof (EVENT);
for (i = 0; i < num_events; i++)
{
e_ptrs[i] = sptr++;
}
fclose (f);
return;
}
write_sched ()
{
char temp1[80], temp2[80];
FILE *f;
int i;
struct stat buffer1;
struct utimbuf times;
long t;
extern long time ();
/* Get the current time */
t = time (NULL);
strcpy (temp1, BINKpath);
strcpy (temp2, BINKpath);
strcat (temp1, "Binkley.Scd");
strcat (temp2, "Binkley.Cfg");
/* Get the current stat for .Cfg file */
if (!stat (temp2, &buffer1))
{
/*
* 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.actime = buffer1.st_atime;
times.modtime = buffer1.st_atime;
status_line ("!Date rollover problem?");
}
else
{
times.actime = t;
times.modtime = t;
}
}
if ((f = fopen (temp1, "wb")) == NULL)
{
return;
}
fwrite (BinkSched, 16, 1, f);
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;
}
/* Write this one out */
fwrite (e_ptrs[i], sizeof (EVENT), 1, f);
}
fclose (f);
utime (temp1, ×);
return;
}
time_to_next ()
{
int cur_day;
int cur_hour;
int cur_minute;
int cur_mday;
int cur_mon;
int cur_year;
int junk, junk1;
int our_time;
int i;
int time_to;
int guess;
int nmin;
/* Get the current time in minutes */
dostime (&cur_hour, &cur_minute, &junk, &junk);
our_time = cur_hour * 60 + cur_minute;
/* Get the current day of the week */
dosdate (&cur_mon, &cur_mday, &cur_year, &cur_day);
/* Make the month 0 based */
--cur_mon;
cur_day = 1 << cur_day;
/* A ridiculous number */
time_to = 3000;
/* 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 (e_ptrs[i]->behavior & MAT_BBS)
continue;
/* If it was already run today, skip it */
if (e_ptrs[i]->last_ran == cur_mday)
continue;
/* If it doesn't happen today, skip it */
if (!(e_ptrs[i]->days & cur_day))
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;
}
/* 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 = 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 (e_ptrs[i]->behavior & MAT_BBS)
continue;
/* If it doesn't happen today, skip it */
if (!(e_ptrs[i]->days & cur_day))
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;
}
}
if (time_to > 1440)
time_to = 1440;
if (time_to < 1)
time_to = 1;
return (time_to);
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/