home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR24
/
REMIN301.ZIP
/
REMIN300.ZIP
/
QUEUE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-10
|
10KB
|
304 lines
/***************************************************************/
/* */
/* QUEUE.C */
/* */
/* Queue up reminders for subsequent execution. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992 by David F. Skoll. */
/* */
/***************************************************************/
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "config.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include "globals.h"
#include "err.h"
#include "types.h"
#include "protos.h"
/* List structure for holding queued reminders */
typedef struct _queuedrem {
struct _queuedrem *next;
int typ;
int RunDisabled;
char *text;
TimeTrig tt;
} QueuedRem;
/* Global variables */
static QueuedRem *QueueHead;
static time_t FileModTime;
static struct stat StatBuf;
PRIVATE void CheckInitialFile ARGS ((void));
PRIVATE int CalculateNextTime ARGS ((QueuedRem *q));
PRIVATE QueuedRem *FindNextReminder ARGS ((void));
PRIVATE void SigIntHandler ARGS ((void));
/***************************************************************/
/* */
/* QueueReminder */
/* */
/* Put the reminder on a queue for later, if queueing is */
/* enabled. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int QueueReminder(ParsePtr p, int typ, TimeTrig *tim)
#else
int QueueReminder(p, typ, tim)
ParsePtr p;
int typ;
TimeTrig *tim;
#endif
{
QueuedRem *qelem;
if (DontQueue ||
tim->ttime == NO_TIME ||
typ == CAL_TYPE ||
tim->ttime < SystemTime() / 60 ||
((typ == RUN_TYPE) && RunDisabled)) return OK;
qelem = NEW(QueuedRem);
if (!qelem) {
Eprint("No memory to queue reminder.");
return E_NO_MEM;
}
qelem->text = StrDup(p->pos); /* Guaranteed that parser is not nested. */
if (!qelem->text) {
free(qelem);
Eprint("No memory to queue reminder.");
return E_NO_MEM;
}
qelem->typ = typ;
qelem->tt = *tim;
qelem->next = QueueHead;
qelem->RunDisabled = RunDisabled;
QueueHead = qelem;
NumQueued++;
return OK;
}
/***************************************************************/
/* */
/* HandleQueuedReminders */
/* */
/* Handle the issuing of queued reminders in the background */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void HandleQueuedReminders(void)
#else
void HandleQueuedReminders()
#endif
{
QueuedRem *q = QueueHead;
long TimeToSleep;
unsigned SleepTime;
Parser p;
Trigger trig;
/* Suppress the BANNER from being issued */
NumTriggered = 1;
/* If we are not connected to a tty, then we must close the
* standard file descriptors. This is to prevent someone
* doing:
* remind file | <filter> | >log
* and have <filter> hung because the child (us) is still
* connected to it. This means the only commands that will be
* processed correctly are RUN commands, provided they mail
* the result back or use their own resource (as a window).
*/
if (!DontFork && (!isatty(1) || !isatty(2))) {
close(1);
close(2);
}
/* If we're a daemon, get the mod time of initial file */
if (Daemon) {
if (stat(InitialFile, &StatBuf)) {
fprintf(ErrFp, "Cannot stat %s - not running as daemon!\n",
InitialFile);
Daemon = 0;
} else FileModTime = StatBuf.st_mtime;
}
/* Initialize the queue - initialize all the entries time of issue */
while (q) {
q->tt.nexttime = (int) (SystemTime()/60 - 1);
q->tt.nexttime = CalculateNextTime(q);
q = q->next;
}
if (!DontFork || Daemon) signal(SIGINT, SigIntHandler);
/* Sit in a loop, issuing reminders when necessary */
while(1) {
q = FindNextReminder();
/* If no more reminders to issue, we're unless we're a daemon. */
if (!q && !Daemon) exit(0);
if (Daemon && !q)
TimeToSleep = (long) 60*Daemon;
else
TimeToSleep = (long) q->tt.nexttime * 60L - SystemTime();
while (TimeToSleep > 0L) {
SleepTime = (unsigned) ((TimeToSleep > 30000L) ? 30000 : TimeToSleep);
if (Daemon && SleepTime > 60*Daemon) SleepTime = 60*Daemon;
sleep(SleepTime);
if (Daemon && SleepTime) CheckInitialFile();
if (Daemon && !q)
TimeToSleep = (long) 60*Daemon;
else
TimeToSleep = (long) q->tt.nexttime * 60L - SystemTime();
}
/* Trigger the reminder */
CreateParser(q->text, &p);
trig.typ = q->typ;
(void) TriggerReminder(&p, &trig, &q->tt, JulianToday);
fflush(stdout);
/* Calculate the next trigger time */
q->tt.nexttime = CalculateNextTime(q);
}
}
/***************************************************************/
/* */
/* CalculateNextTime */
/* */
/* Calculate the next time when a reminder should be issued. */
/* Return NO_TIME if reminder expired. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int CalculateNextTime(QueuedRem *q)
#else
static int CalculateNextTime(q)
QueuedRem *q;
#endif
{
int tim = q->tt.ttime;
int rep = q->tt.rep;
int delta = q->tt.delta;
int curtime = q->tt.nexttime+1;
if (delta == NO_DELTA)
if (tim < curtime) return NO_TIME; else return tim;
tim -= delta;
if (rep == NO_REP) rep = delta;
if (tim < curtime) tim += ((curtime - tim) / rep) * rep;
if (tim < curtime) tim += rep;
if (tim > q->tt.ttime) tim = q->tt.ttime;
if (tim < curtime) return NO_TIME; else return tim;
}
/***************************************************************/
/* */
/* FindNextReminder */
/* */
/* Find the next reminder to trigger */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE QueuedRem *FindNextReminder(void)
#else
static QueuedRem *FindNextReminder()
#endif
{
QueuedRem *q = QueueHead;
QueuedRem *ans = NULL;
while (q) {
if (q->tt.nexttime != NO_TIME) {
if (!ans) ans = q;
else if (q->tt.nexttime < ans->tt.nexttime) ans = q;
}
q = q->next;
}
return ans;
}
/***************************************************************/
/* */
/* SigIntHandler */
/* */
/* For debugging purposes, when sent a SIGINT, we print the */
/* contents of the queue. This does NOT work when the -f */
/* command-line flag is supplied. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void SigIntHandler(void)
#else
static void SigIntHandler()
#endif
{
QueuedRem *q = QueueHead;
#ifdef SYSV
signal(SIGINT, SigIntHandler);
#endif
printf("Contents of AT queue:%s", NL);
while (q) {
printf("Trigger: %02d:%02d Activate: %02d:%02d Rep: %d Delta: %d%s",
q->tt.ttime / 60, q->tt.ttime % 60,
q->tt.nexttime / 60, q->tt.nexttime % 60,
q->tt.rep, q->tt.delta, NL);
printf("Text: %s %s%s%s", ((q->typ == MSG_TYPE) ? "MSG" : "RUN"),
q->text,
NL, NL);
q = q->next;
}
printf(NL);
}
/***************************************************************/
/* */
/* CheckInitialFile */
/* */
/* If the initial file has been modified, then restart the */
/* daemon. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void CheckInitialFile(void)
#else
static void CheckInitialFile()
#endif
{
/* If date has rolled around, or file has changed, spawn a new version. */
time_t tim = FileModTime;
int y, m, d;
if (stat(InitialFile, &StatBuf) == 0) tim = StatBuf.st_mtime;
if (tim != FileModTime ||
RealToday != SystemDate(&y, &m, &d))
execvp(ArgV[0], ArgV);
}