home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * DCRON.C V2
- *
- * - loads s:crontab or file crontab specified by -f
- * - checks the datestamp on s:crontab every 60 seconds and reloads the file
- * into memory if changed.
- * - every 60 seconds scans the memory-resident image for things to do
- * - checks for date changes and doesn't reexecute if changes are
- * backwards in time.
- *
- * DCRON [-d] [-f crontab] logfile
- */
-
- #include <exec/types.h>
- #include <devices/timer.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <stdio.h>
- #include "protos.h"
-
- typedef struct Node NODE;
- typedef struct List LIST;
- typedef struct DateStamp DATESTAMP;
- typedef struct timerequest IOT;
- typedef struct MsgPort PORT;
- typedef struct Process PROC;
- typedef struct FileInfoBlock FIB;
-
-
- #define CRONTAB "s:crontab"
- #define SIGS (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)
-
- typedef struct {
- short min;
- short hour;
- short day;
- short month;
- short dow;
- } DateAry;
-
- typedef struct {
- NODE Node;
- UBYTE BitMap[8][8]; /* min, hour, day, month, dow */
- char *Command;
- } Command;
-
- extern char *malloc();
-
- DATESTAMP LastDate; /* Date as of last execution */
- DATESTAMP ModDate; /* Check if system time modified */
- DATESTAMP TabDate; /* Check if crontab modified */
-
- LIST CmdList; /* list of commands */
-
- IOT Iot;
- PORT *TPort; /* Collector plate for IO requests */
- short FatalError; /* Uh oh, can't recover */
- char *LogFile;
- char *CronFile = CRONTAB;
- char XDebug;
- long NilFH; /* NIL: file handle */
- short CronFileExists = 0; /* -1, 0, 1 */
-
- void logmessage();
- void LoadCronFile();
- void LoadBitMap();
- void WriteStr();
- void RunCommand();
- void ExecuteCommands();
- void CheckFileModified();
- void DateToDateAry();
- void *GetHead();
- void *GetSucc();
-
- int
- brk()
- {
- return(0);
- }
-
- void
- main(ac, av)
- short ac;
- char *av[];
- {
- PROC *proc = (PROC *)FindTask(NULL);
- APTR oldConsoleTask = proc->pr_ConsoleTask;
-
- onbreak(brk);
- NewList(&CmdList);
- {
- register short i;
-
- for (i = 1; i < ac; ++i) {
- register char *ptr = av[i];
- if (*ptr != '-') {
- LogFile = ptr;
- continue;
- }
- while (*++ptr) {
- switch(*ptr) {
- case 'd':
- ++XDebug;
- break;
- case 'f':
- CronFile = av[++i];
- break;
- default:
- WriteStr(Output(), "bad option\n");
- goto fail;
- }
- }
- }
- if (CronFile == NULL) {
- puts("-f : expected filename");
- exit(1);
- }
- }
- if (!LogFile) {
- fail:
- WriteStr(Output(), "DCron [-d] [-f cronfile] Logfile\n");
- WriteStr(Output(), "DCron, V2.02\n");
- exit(1);
- }
- if (OpenDevice("timer.device", 0, &Iot, UNIT_VBLANK)) {
- logmessage("Unable to open timer.device\n");
- exit(1);
- }
- if (!DeviceProc("NULL:")) {
- logmessage("NULL: device required for dcron to run\n");
- WriteStr(Output(), "NULL: device required to run\n");
- exit(1);
- }
- proc->pr_ConsoleTask = (APTR)DeviceProc("NULL:");
- fclose(stderr);
-
- logmessage("Startup: V2.02 (dist: 29 May 1990)\n");
-
- NilFH = (long)Open("null:", 1006);
- DateStamp(&LastDate);
- DateStamp(&ModDate);
- TPort = CreatePort(NULL,0);
- Iot.tr_time.tv_secs = 2;
- Iot.tr_time.tv_micro= 0;
- Iot.tr_node.io_Message.mn_ReplyPort = TPort;
- Iot.tr_node.io_Command = TR_ADDREQUEST;
- SendIO(&Iot); /* timeout */
-
- for (;;) {
- long mask;
- mask = Wait(SIGS | (1 << TPort->mp_SigBit));
- if (mask & (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D)) {
- logmessage("DCRON: Break\n");
- break;
- }
- if (mask & (SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)) {
- logmessage("^E/F force check\n");
- AbortIO(&Iot); /* force execution */
- }
- if (FatalError)
- break;
- if (CheckIO(&Iot)) { /* if file/date modified, force exec. */
- DATESTAMP Ds;
- DateAry D1, D2;
- int st;
-
- WaitIO(&Iot);
- st = CheckDateChanged();
- CheckFileModified();
- DateStamp(&Ds);
- DateToDateAry(&LastDate, &D1);
- DateToDateAry(&Ds, &D2);
- if (st == 0)
- ExecuteCommands(&D1, &D2);
- LastDate = Ds;
- DateStamp(&Ds);
- Iot.tr_time.tv_secs = 61 - Ds.ds_Tick / 50;
- Iot.tr_time.tv_micro= 0;
- SendIO(&Iot);
- }
- }
- AbortIO(&Iot);
- WaitIO(&Iot);
- CloseDevice(&Iot);
- DeletePort(TPort);
- Close(NilFH);
- proc->pr_ConsoleTask = oldConsoleTask;
- }
-
- /*
- * Returns 0 = execute objects for range
- * 1 = do not execute objects for range
- */
-
- CheckDateChanged()
- {
- DATESTAMP Ds;
- long xold, xnew;
- static char state = 0;
-
- DateStamp(&Ds);
- xold = ModDate.ds_Days * 1440 + ModDate.ds_Minute;
- xnew = Ds.ds_Days * 1440 + Ds.ds_Minute;
-
- /*
- * if backwards or more than T+5min
- */
-
- if (xnew < xold || xnew - 5 > xold) {
- DateStamp(&LastDate);
- if (state == 0)
- logmessage("Date change noted, %d mins\n", xnew - xold + 1);
- state = 1;
- } else {
- state = 0;
- }
-
- /*
- * If all is ok or too far away from old date then set new base
- * date for next comparison (T +/- 10min)
- */
-
- if (state == 0 || xold - xnew > 10 || xold - xnew < -10 ) {
- ModDate = Ds;
- }
- return((int)state);
- }
-
- void
- CheckFileModified()
- {
- char buf[sizeof(FIB)+4];
- long lock;
-
- if (lock = (long)Lock(CronFile, SHARED_LOCK)) {
- register FIB *fib = (FIB *)(((long)buf+3)&~3);
- if (Examine(lock, fib)) {
- if (CronFileExists < 1 ||
- fib->fib_Date.ds_Tick != TabDate.ds_Tick ||
- fib->fib_Date.ds_Minute != TabDate.ds_Minute ||
- fib->fib_Date.ds_Days != TabDate.ds_Days)
- {
- if (TabDate.ds_Days) {
- logmessage("crontab modification noted\n");
- }
- TabDate = fib->fib_Date;
- LoadCronFile();
- }
- }
- UnLock(lock);
- } else {
- if (CronFileExists >= 0) {
- logmessage("unable to lock cronfile %s!\n", CronFile);
- CronFileExists = -1;
- }
- }
- }
-
- /*
- * execute commands that fall d1 < cmd <= d2
- */
-
- void
- ExecuteCommands(d1, d2)
- short *d1, *d2; /* min, hour, day, month, dow */
- {
- Command *cmd;
- short i;
- short n;
-
- for (cmd = GetHead(&CmdList); cmd; cmd = GetSucc(&cmd->Node)) {
- short ok = 1;
- for (i = 0; i < 5; ++i) {
- UBYTE *bitmap = cmd->BitMap[i];
-
- n = d2[i];
- if (n == d1[i]) {
- if ((bitmap[n>>3] & (1 << (n & 7))) == 0) {
- ok = 0;
- break;
- }
- } else {
- while (n != d1[i]) {
- if (bitmap[n>>3] & (1 << (n & 7)))
- break;
- n = (n - 1) & 63;
- }
- if (n == d1[i]) {
- ok = 0;
- break;
- }
- }
- }
- if (ok)
- RunCommand(cmd->Command);
- }
- }
-
- void
- RunCommand(cmd)
- char *cmd;
- {
- char buf[256];
-
- logmessage("%s\n", cmd);
- strcpy(buf, "run ");
- strcat(buf, cmd);
- Execute(buf, NilFH, NilFH);
- }
-
- void
- DateToDateAry(date, da)
- DATESTAMP *date;
- DateAry *da;
- {
- static char dim[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
- long days;
- long years;
- char leap;
- short month;
-
- days = date->ds_Days + 731; /* 1976 */
- years = days / (365*3+366); /* #quad yrs */
- days -= years * (365*3+366);
- leap = (days <= 365); /* is a leap yr*/
- years = 1976 + 4 * years;
- dim[1] = 29;
- if (leap == 0) {
- dim[1] = 28;
- days -= 366;
- ++years;
- years += days / 365;
- days %= 365;
- }
- for (month = 0; (month==1) ? (days >= 28 + leap) : (days >= dim[month]); ++month)
- days -= (month==1) ? (28 + leap) : dim[month];
-
- da->min = date->ds_Minute % 60;
- da->hour = date->ds_Minute / 60;
- da->day = days + 1;
- da->month = month + 1;
- da->dow = date->ds_Days % 7; /* 0 = sunday */
- }
-
- void
- LoadCronFile()
- {
- char buf[256];
- long fh;
- Command *cmd;
-
- while (cmd = (Command *)RemHead(&CmdList))
- free(cmd);
-
- ReadLn(NULL, NULL, 0);
- fh = (long)Open(CronFile, 1005);
- if (fh == NULL) {
- if (CronFileExists != -1)
- logmessage("unable to open cronfile %s!\n", CronFile);
- CronFileExists = -1;
- return;
- }
- while (ReadLn(fh, buf, 256)) {
- char *ptr = buf;
- short i;
-
- if (buf[0] == 0 || buf[0] == '#')
- continue;
- cmd = (Command *)malloc(sizeof(Command));
- setmem(cmd, sizeof(Command), 0);
-
- for (i = 0; i < 5; ++i) { /* 5 time fields */
- /*
- printf("lb %d\n", i);
- */
- LoadBitMap(&ptr, cmd->BitMap[i]);
- }
-
- while (*ptr == ' ' || *ptr == 9)
- ++ptr;
- cmd->Command = malloc(strlen(ptr) + 1);
- strcpy(cmd->Command, ptr);
-
- /*
- for (i = 0; i < 5; ++i) {
- for (j = 0; j < 4; ++j)
- printf("%02x", cmd->BitMap[i][j]);
- printf(" ");
- for (j = 4; j < 8; ++j)
- printf("%02x", cmd->BitMap[i][j]);
- puts("");
- }
-
- printf("cmd = %s\n", cmd->Command);
- */
-
- AddTail(&CmdList, &cmd->Node);
- }
- Close(fh);
- CronFileExists = 1;
- }
-
- void
- LoadBitMap(pptr, bm)
- char **pptr;
- UBYTE *bm; /* 8 bytes = 64 entries */
- {
- register char *ptr = *pptr;
-
- while (*ptr == ' ' || *ptr == 9)
- ++ptr;
-
- /*
- * looking for *, number range n-n, single numbers, etc... 1,2,8-10 ...
- */
-
- while (*ptr == '*' || (*ptr >= '0' && *ptr <= '9')) {
- short v1, v2;
-
- v1 = 0;
- while (*ptr >= '0' && *ptr <= '9') {
- v1 = v1 * 10 + *ptr - '0';
- ++ptr;
- }
- if (*ptr == '-') {
- ++ptr;
- v2 = 0;
- while (*ptr >= '0' && *ptr <= '9') {
- v2 = v2 * 10 + *ptr - '0';
- ++ptr;
- }
- } else {
- v2 = v1;
- }
- if (*ptr == '*') {
- v1 = 0;
- v2 = 63;
- ++ptr;
- }
- if (v1 < 0)
- v1 = 0;
- if (v1 > 63)
- v1 = 63;
- if (v2 < 0)
- v2 = 0;
- if (v2 > 63)
- v2 = 63;
-
- --v1;
- do {
- v1 = (v1 + 1) & 63;
- bm[v1>>3] |= (1 << (v1 & 7));
- } while (v1 != v2);
- if (*ptr == ',')
- ++ptr;
- }
- *pptr = ptr;
- }
-
- /*
- * Poor man's log. Note that the log file is not left open ... this allows
- * one to read or tail it at any time.
- */
-
- void
- logmessage(ptr, a, b, c, d, e)
- char *ptr;
- {
- char *buf = malloc(512);
- DATESTAMP date;
- DateAry da;
- long fh;
- static char *Dow[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
- static char *Miy[] = { "---", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
- if (!buf)
- return;
-
- DateStamp(&date);
- DateToDateAry(&date, &da);
-
- sprintf(buf, "dcron: %s %2ld %s %02ld:%02ld ",
- Dow[da.dow], da.day, Miy[da.month], da.hour, da.min
- );
- sprintf(buf+strlen(buf), ptr, a, b, c, d, e);
- if ((fh = (long)Open(LogFile, 1005)) == NULL)
- fh = (long)Open(LogFile, 1006);
- if (fh) {
- Seek(fh, 0L, 1);
- WriteStr(fh, buf);
- Close(fh);
- }
- free(buf);
- }
-
- void
- WriteStr(fh, buf)
- long fh;
- char *buf;
- {
- Write(fh, buf, strlen(buf));
- }
-
- ReadLn(fh, buf, max)
- long fh;
- char *buf;
- short max;
- {
- static char Data[1024];
- static short RIdx, RLen;
- register short i;
-
- if (fh == NULL) {
- RIdx = RLen = 0;
- return(0);
- }
- for (--max, i = 0; i < max; ++i) {
- if (RIdx == RLen) {
- RLen = Read(fh, Data, 1024);
- RIdx = 0;
- if (RLen <= 0) {
- buf[i] = 0;
- return(0);
- }
- }
- if ((buf[i] = Data[RIdx++]) == '\n')
- break;
- }
- buf[i] = 0;
- return(1);
- }
-
-