simmy@ocean.ocean.fsu.edu (Simmule Turner) (07/31/89)
Here is my first posting! This is a version of the cron daemon, that I fixed up. I'm planning on adding user crontab's in the near future. Please send bug fixes to me(see the address in the .signature). I use 4k of stack space. char scid[]="$Header: cron.c,v 1.5 89/05/08 17:55:40 SrT$"; /* #define DEBUG /* Only define when testing */ /* * Version 1.5 SrT 89/05/08 * Changed sleep code. * * Version 1.4 SrT 89/03/17 * Fixed a pointer problem, when reloading crontab. * * Version 1.3 SrT 89/03/16 * Loads crontab, into memory and only rereads the disk * version if it changes. (Free up those CPU cycles!) * * Fixed 03/10/89, by Simmule Turner, simmy@nu.cs.fsu.edu * Now correctly cleans up zombie processes * Logs actions to /usr/adm/cronlog * Syncs with clock after each minute * Comments allowed in crontab * Fixed bug that prevented month, from matching */ /* cron - clock daemon Author: S.R. Sampson */ /* Cron is the clock daemon. It is typically started up from the * /etc/rc file by the line: * /usr/bin/cron * Cron automatically puts itself in the background, so no & is needed. * If cron is used, it runs all day, spending most of its time asleep. * Once a minute it wakes up and examines /usr/lib/crontab to see if there * are any commands to be executed. The format of this table is the same * as in UNIX, except that % is not allowed to indicate 'new line.' * * Each crontab entry has six fields: * minute hour day-of-the-month month day-of-the-week command * Each entry is checked in turn, and any entry matching the current time * is executed. The entry * matches anything. Some examples: * * min hr dat mo day command * * * * * * /usr/bin/date >/dev/tty0 #print date every minute * 0 * * * * /usr/bin/date >/dev/tty0 #print date on the hour * 30 4 * * 1-5 /bin/backup /dev/fd1 #do backup Mon-Fri at 0430 * 30 19 * * 1,3,5 /etc/backup /dev/fd1 #Mon, Wed, Fri at 1930 * 0 9 25 12 * /usr/bin/sing >/dev/tty0 #Xmas morning at 0900 only */ #include <stdio.h> #include <signal.h> #include <errno.h> #include <time.h> #include <setjmp.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #ifndef DEBUG #define CRONTAB "/usr/lib/crontab" #define LOGFILE "/usr/adm/cronlog" #else #define LOGFILE "/usr/adm/cronlog.dbg" #define CRONTAB "/usr/adm/crontab.dbg" #endif #define NULLDEV "/dev/null" #define SEPARATOR " \t" #define CRONSIZE 2048 #define CRONSTRUCT struct cron_entry #define TRUE 1 #define FALSE 0 struct cron_entry { char *mn; char *hr; char *day; char *mon; char *wkd; char *cmd; struct cron_entry *next; } *head, *p; char crontab[CRONSIZE], *ctime(); FILE *cronlog; int wakeup(), nothing(); long previous_time = 0L; extern int errno; main() { int status, pid; long clock; status=fork(); if ( status == -1 ) { fprintf(stderr,"Can't fork cron\n"); exit(1); } if (status > 0) exit(0); signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGQUIT, SIG_IGN); close(0); close(1); close(2); open(NULLDEV,0); if ((cronlog = fopen(LOGFILE,"a")) == (FILE *) NULL) { open(NULLDEV,1); open(NULLDEV,1); } else { setbuf(cronlog,(char *)NULL); dup(fileno(cronlog)); } p = (CRONSTRUCT *) malloc (sizeof(CRONSTRUCT)); p->next = (CRONSTRUCT *) NULL; head = p; while (TRUE) { signal(SIGALRM, wakeup); time(&clock); alarm(60 - clock % 60); pause(); signal(SIGALRM, nothing); alarm(1); while (wait((int *) NULL) != -1) ; } } nothing(){} wakeup() { register struct tm *tm; long cur_time; extern struct tm *localtime(); CRONSTRUCT *this_entry = head; load_crontab(); time(&cur_time); tm = localtime(&cur_time); while (this_entry->next && this_entry->mn) { if (match(this_entry->mn, tm->tm_min) && match(this_entry->hr, tm->tm_hour) && match(this_entry->day, tm->tm_mday) && match(this_entry->mon, tm->tm_mon+1) && match(this_entry->wkd, tm->tm_wday)) { fprintf(cronlog,"%02d/%02d-%02d:%02d %s", tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, this_entry->cmd); if (fork() == 0) { execl("/bin/sh", "/bin/sh", "-c", this_entry->cmd, 0); exit(1); } } this_entry = this_entry->next; } } /* * This routine will match the left string with the right number. * * The string can contain the following syntax: * * * This will return TRUE for any number * x,y [,z, ...] This will return TRUE for any number given. * x-y This will return TRUE for any number within * the range of x thru y. */ match(left, right) register char *left; register int right; { register int n; register char c; n = 0; if (!strcmp(left, "*")) return(TRUE); while ((c = *left++) && (c >= '0') && (c <= '9')) n = (n * 10) + c - '0'; switch (c) { case '\0': return (right == n); case ',': if (right == n) return(TRUE); do { n = 0; while ((c = *left++) && (c >= '0') && (c <= '9')) n = (n * 10) + c - '0'; if (right == n) return(TRUE); } while (c == ','); return(FALSE); case '-': if (right < n) return(FALSE); n = 0; while ((c = *left++) && (c >= '0') && (c <= '9')) n = (n * 10) + c - '0'; return(right <= n); } } load_crontab() { int pos = 0; FILE *cfp; struct stat buf; if (stat(CRONTAB,&buf)) { if (previous_time == 0L) printf("Can't stat crontab"); previous_time = 0L; return; } if (buf.st_mtime <= previous_time) return; #ifdef DEBUG printf("Crontab Time:%D In_Core:%D\n",buf.st_mtime,previous_time); #endif if ((cfp = fopen(CRONTAB,"r")) == (FILE *) NULL) { if (previous_time == 0L) printf("Can't open crontab"); previous_time = 0L; return; } previous_time = buf.st_mtime; p = head; while (fgets(&crontab[pos],CRONSIZE-pos,cfp) != (char *) NULL) { int len; if (crontab[pos] == '#') continue; len = strlen(&crontab[pos]); assign(p,&crontab[pos]); if (p->next == (CRONSTRUCT *)NULL) { p->next = (CRONSTRUCT *) malloc(sizeof(CRONSTRUCT)); p->next->next = (CRONSTRUCT *) NULL; } p = p->next; pos += ++len; if (pos >= CRONSIZE) break; } fclose(cfp); while (p) { p->mn = (char *) NULL; p = p->next; } #ifdef DEBUG printf("Crontab uses %d/%d bytes\n",pos,CRONSIZE); { CRONSTRUCT *start = head; dumptable(start); } #endif } assign(entry,line) CRONSTRUCT *entry; char *line; { static char buf[256]; int where; strcpy(buf,line); entry->mn = strtok(line,SEPARATOR); entry->hr = strtok((char *) NULL,SEPARATOR); entry->day = strtok((char *) NULL,SEPARATOR); entry->mon = strtok((char *) NULL,SEPARATOR); entry->wkd = strtok((char *) NULL,SEPARATOR); entry->cmd = strtok((char *) NULL,SEPARATOR); where = entry->cmd - line; strcpy(&line[where],&buf[where]); } #ifdef DEBUG dumptable(table) CRONSTRUCT *table; { long clock; time(&clock); printf("\nContents of crontab at: %s",ctime(&clock)); printf("Minute\tHour\tDay\tMonth\tWeekday\tCommand\n"); while (table->next && table->mn) { printf("%s\t%s\t%s\t%s\t%s\t%s", table->mn,table->hr,table->day,table->mon, table->wkd,table->cmd); table = table->next; } } #endif -- Simmule Turner |Arpa: simmy@nu.cs.fsu.edu | "Wait until it is Florida State Univ |Uucp: gatech!nu.cs.fsu.edu!simmy | finished, it will 444 OSB | Cis: 70651,67 Genie:simmy | be great" Tallahassee, FL 32306 | Tel: +1 904 644 1573 | simmy