[alt.sources] REMIND 2.2 05/05

dfs@doe.carleton.ca (David F. Skoll) (11/17/90)

#!/bin/sh
# This is part 05 of Remind-2.2
if touch 2>&1 | fgrep 'amc' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= timed.c ==============
if test X"$1" != X"-c" -a -f 'timed.c'; then
	echo "File already exists: skipping 'timed.c'"
else
echo "x - extracting timed.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > timed.c &&
X#include <stdio.h>
X#include <signal.h>
X#include <malloc.h>
X#include "defines.h"
X#include "globals.h"
X#include "protos.h"
X
X/***************************************************************/
X/*                                                             */
X/*  TIMED.C                                                    */
X/*                                                             */
X/*  Contains routines for triggering timed reminders           */
X/*                                                             */
X/*  By David Skoll - 12 Nov 1990                               */
X/*                                                             */
X/*  (C) 1990 by David Skoll                                    */
X/*                                                             */
X/***************************************************************/
X
X/* Global pointer to AT reminders */
X 
Xstatic AtEntry AtQueue =
X{
X   0, 0, 0, 0, 0, NULL, NULL
X};
X
X/***************************************************************/
X/*                                                             */
X/*  AddEntry                                                   */
X/*                                                             */
X/*  Add an entry to the AT queue, keeping things sorted by     */
X/*  trigger time.                                              */
X/*                                                             */
X/*  Returns 0 for success, nonzero for failure                 */
X/*                                                             */
X/***************************************************************/
Xint AddEntry(e)
XAtEntry *e;
X{
X   AtEntry *current, *prev;
X   prev = &AtQueue;
X   current = prev->next;
X   while (current) {
X      if (e->firsttime < current->firsttime) {
X         prev->next = e;
X         e->next = current;
X         break;
X      } else {
X         prev = current;
X         current = prev->next;
X      }
X   }
X   if (!current) {
X      prev->next = e;
X      e->next = NULL;
X   }
X}
X
X/***************************************************************/
X/*                                                             */
X/* DoAt                                                        */
X/* Creates an entry for an At reminder, puts it on the queue   */
X/* Updates the global variable NumAtsQueued                    */
X/*                                                             */
X/***************************************************************/
X#ifndef UNIX
Xint DoAt(int tim, int tdelta, int trep, char *body, enum Token_t type)
X#else
Xint DoAt(tim, tdelta, trep, body, type)
Xint tim, tdelta, trep;
Xchar *body;
Xenum Token_t type;
X#endif
X{
X   AtEntry *e;
X   int curtime;
X
X   curtime = (int) (SystemTime() / 60);
X   
X   /* If the trigger time is in the past, don't add to the at queue */     
X   if (tim < curtime) return 0;
X
X   /* Allocate space for the entry */
X   e = (AtEntry *) malloc(sizeof(AtEntry));
X   if (e == (AtEntry *) NULL) {
X      Eprint("Can't malloc memory for AT!\n");
X      return 1;
X   }
X   e->text = malloc(strlen(body)+1);
X   if (e->text == NULL) {
X      Eprint("Can't malloc memory for body of AT!\n");
X      return 1;
X   }
X   strcpy(e->text, body);
X
X   /* Find out the next trigger time */
X   e->firsttime = FindNextTriggerTime(tim, trep, tdelta, curtime);
X   e->repeat    = trep;
X   e->type      = type;
X   e->time      = tim;
X   e->delta     = tdelta;
X   AddEntry(e);
X   NumAtsQueued++;
X   return 0;
X}
X
X/***************************************************************/
X/*                                                             */
X/* int FindNextTriggerTime                                     */
X/*                                                             */
X/* Returns the next time a queued AT should be triggered.      */
X/* Returns -1 if the AT has expired.                           */
X/*                                                             */
X/***************************************************************/
X#ifndef UNIX
Xint FindNextTriggerTime(int tim, int rep, int delta, int curtime)
X#else
Xint FindNextTriggerTime(tim, rep, delta, curtime)
Xint tim, rep, delta, curtime;
X#endif
X{
X   int trigger = tim;
X   
X   if (delta <= 0)
X      if (trigger < curtime) return -1; else return trigger;
X   
X   trigger -= delta;
X   if (rep == -1) rep = delta;
X
X   if (trigger < curtime) trigger += ((curtime - trigger) / rep) * rep;
X   if (trigger < curtime) trigger += rep;
X   if (trigger > tim) trigger = tim;
X   if (trigger < curtime) return -1; else return trigger;
X}
X
X/***************************************************************/
X/*                                                             */
X/* HandleQueuedAts                                             */
X/*                                                             */
X/* Handles all the queued AT reminders.  Sits in a sleep loop  */
X/* to trigger reminders.                                       */
X/*                                                             */
X/***************************************************************/
Xvoid HandleQueuedAts()
X{
X   AtEntry *e;
X   long TimeToSleep;
X   unsigned SleepTime;
X   long now;
X
X   signal(SIGHUP, SigHupHandler);
X
X   while (e = AtQueue.next) {
X      /* Check if the user has logged off.  If so, die gracefully. */
X      if (!isatty(1)) {
X        exit(0);
X      }
X      now = SystemTime();
X      TimeToSleep = (long) e->firsttime * 60L - now;
X      if (TimeToSleep < 0L) TimeToSleep = 0L;
X
X      /* Be paranoid and assume that unsigneds are only two bytes long -
X         therefore, do the sleeping in 30000-second chunks. */  
X     
X      while (TimeToSleep) {
X         if (TimeToSleep > 30000L) SleepTime = 30000;
X                              else SleepTime = (unsigned) TimeToSleep;
X         sleep(SleepTime);
X         TimeToSleep -= (long) SleepTime;
X      }
X
X      /* Over here, we trigger the reminder */
X      DoSubst(e->text, WorkBuf, CurDay, CurMon, CurYear, JulianToday, e->type, e->time);
X      if (e->type == Run_t) system(WorkBuf);
X      else printf("%s\n", WorkBuf);
X
X      /* Remove the entry from the queue */
X      AtQueue.next = e->next;
X
X      /* Check if this reminder should be re-triggered */
X      e->firsttime = FindNextTriggerTime(e->time, e->repeat, 
X                                        e->delta, e->firsttime + 1);
X
X      if (e->firsttime != -1) AddEntry(e);
X      else {
X      /* Not to be added - free the memory */
X         free(e->text);
X         free(e);
X      }
X   }
X}
X
X/***************************************************************/
X/*                                                             */
X/* SigHupHandler                                               */
X/*                                                             */
X/* For debugging purposes, when sent a HUP, we print the       */
X/* contents of the queue.                                      */
X/*                                                             */
X/***************************************************************/
Xvoid SigHupHandler()
X{
X   AtEntry *e;
X
X   printf("Contents of AT queue:\n");
X
X   e = AtQueue.next;
X   while (e) {
X      printf("Trigger: %02d:%02d  Activate: %02d:%02d  Rep: %d  Delta: %d\n",
X              e->time / 60, e->time % 60, e->firsttime / 60, e->firsttime % 60,
X              e->repeat, e->delta);
X      printf("Text: %s %s\n\n", ((e->type == Msg_t) ? "MSG" : "RUN"), e->text);
X      e = e->next;
X   }
X   printf("\n");
X}
SHAR_EOF
$TOUCH -am 1115093590 timed.c &&
chmod 0600 timed.c ||
echo "restore of timed.c failed"
set `wc -c timed.c`;Wc_c=$1
if test "$Wc_c" != "7436"; then
	echo original size 7436, current size $Wc_c
fi
fi
exit 0