/*--------------------------------------------------------------------------*/ /* */ /* */ /* ------------ Bit-Bucket Software, Co. */ /* \ 10001101 / Writers and Distributors of */ /* \ 011110 / Freely Available Software. */ /* \ 1011 / */ /* ------ */ /* */ /* (C) Copyright 1987-96, Bit Bucket Software Co. */ /* */ /* 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.260. */ /* */ /* 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:42/1491 */ /* 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 09"; /* 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)); start_hist = hist; 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 (); /* Do this first ... if any $.. to kill, do it */ if (e_ptrs[i].behavior & MAT_KILLBAD) kill_bad (); /* If we are supposed to exit, then do it */ if (evt.errlevel[0]) { if (errlvlshell[evt.errlevel[0] - 1] == NULL) { status_line (MSG_TXT (M_EVENT_EXIT), evt.errlevel[0]); screen_blank = 0; errl_exit (evt.errlevel[0]); } else { status_line (MSG_TXT (M_EVENT_SHELL), evt.errlevel[0]); errl_shell (evt.errlevel[0]); } } else if (packer != NULL || cleanup != 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); } if (packer != NULL) { (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; unsigned long 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 = (HFILE) open (temp1, O_RDONLY | O_BINARY)) == (HFILE) - 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)); start_hist = hist; /* Note, we do not use "got". Some platforms want it to be a long and some want it to be a int. We don't care, so we make it a long (see above) so there's enough room, then use a void * so the compiler won't complain about an argument we don't even want */ (void) _dos_read (stream, (char far *) e_ptrs, (USHORT) (buffer1.st_size - 16 - sizeof (HISTORY)), (void *)&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; unsigned long 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 ((time_t) 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 = (HFILE) open (temp1, O_CREAT | O_RDWR | O_BINARY, S_IREAD | S_IWRITE)) == (HFILE) - 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; } } /* Note, we do not use "got". Some platforms want it to be a long and some want it to be a int. We don't care, so we make it a long (see above) so there's enough room, then use a void * so the compiler won't complain about an argument we don't even want */ (void) _dos_write (stream, (char far *) e_ptrs, (USHORT) (num_events * sizeof (BINK_EVENT)), (void *)&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, write_binary)) == 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); }