SRI-NOSC/s1/cron.c
#/*
Module Name:
cron.c -- clock daemon
Installation:
if $1x = finalx goto final
cc cron.c
exit
: final
cc -O -s cron.c
su cp a.out /etc/cron
rm -f a.out
Synopsis:
/etc/cron
Function:
Executes commands at specified dates and times according to the
instructions in the file /usr/lib/crontab. Documentation may be
found in cron (VIII).
Files:
/usr/lib/crontab
Module History:
Derived from original distribution from Bell Labs.
Modified 15Feb78 by Greg Noel so that the hourly reinitialization
from /usr/lib/crontab occurs on the hour.
Modified 13Sep78 by Greg Noel to use long arithmetic on the time so
that setting the date forward a long time (more than 18.2 hours)
does not cause it to become confused. Also added a test to see
if the crontab has been changed since we last looked at it so
that we only re-initialize if it actually changed.
*/
#define ANY -1
#define LIST -2
#define RANGE -3
#define EOF -4
char *crontab "/usr/lib/crontab";
char *crontmp "/tmp/crontmp";
char *aend;
long itime;
int *localtime();
int reset();
int flag;
main()
{
register *loct, t;
register char *cp;
extern char end[];
setuid(1);
if(fork()) exit();
chdir("/");
close(0);
close(1);
close(2);
t = open("/", 0);
dup(t);
dup(t);
setexit();
signal(1, reset);
time(&itime);
itime =- *(loct=localtime(&itime)); /* remove any seconds */
for(;;) { /* do forever */
init(); /* setup tables from file */
do { /* once for every minute */
loct[4]++; /* 1-12 for month */
for(cp = end; *cp != EOF;) {
flag = 0;
cp = cmp(cp, loct[1]); /* minute */
cp = cmp(cp, loct[2]); /* hour */
cp = cmp(cp, loct[3]); /* day */
cp = cmp(cp, loct[4]); /* month */
cp = cmp(cp, loct[6]); /* day of week */
if(flag == 0) {
slp();
ex(cp);
}
while(*cp++ != 0)
;
}
itime =+ 60;
loct = localtime(&itime);
} while(loct[1]); /* re-init each hour on the hour */
slp();
} /* end of do forever */
}
cmp(p, v)
char *p;
{
register char *cp;
cp = p;
switch(*cp++) {
case ANY:
return(cp);
case LIST:
while(*cp != LIST)
if(*cp++ == v) {
while(*cp++ != LIST)
;
return(cp);
}
flag++;
return(cp+1);
case RANGE:
if(*cp > v || cp[1] < v)
flag++;
return(cp+2);
}
if(cp[-1] != v)
flag++;
return(cp);
}
slp()
{
register i;
long t;
time(&t);
if(itime > t) {
i = itime - t;
sleep(i);
}
}
ex(s)
char *s;
{
register i;
if(fork()) {
wait();
return;
}
for(i=0; s[i]; i++);
close(0);
creat(crontmp, 0600);
write(0, s, i);
close(0);
open(crontmp, 0);
unlink(crontmp);
if(fork())
exit();
execl("/bin/sh", "sh", "-t", 0);
exit();
}
init()
{
int ib[259], t[10];
register i, c;
register char *cp;
char *ocp;
int n;
extern char end[];
struct { long L[]; }; /* for accessing long variables */
static long modtim; /* last mod time of crontab */
if(stat(crontab, ib) < 0) {
write(1, "cannot access table\n", 20);
exit();
}
if(modtim == ib->L[8]) return; /* file hasn't changed */
modtim = ib->L[8];
if(fopen(crontab, ib) < 0) {
write(1, "cannot open table\n", 18);
exit();
}
cp = end;
if(aend == 0)
aend = cp;
loop:
ocp = cp;
if(cp+100 > aend) {
aend =+ 512;
brk(aend);
}
for(i=0;; i++) {
do
c = getc(ib);
while(c == ' ' || c == '\t');
if(c <= 0 || c == '\n')
goto ignore;
if(i == 5)
break;
if(c == '*') {
*cp++ = ANY;
continue;
}
n = 0;
while(c >= '0' && c <= '9') {
n = n*10 + c-'0';
c = getc(ib);
}
if(n < 0 || n > 100)
goto ignore;
if(c == ',')
goto list;
if(c == '-')
goto range;
if(c != '\t' && c != ' ')
goto ignore;
*cp++ = n;
continue;
list:
*cp++ = LIST;
*cp++ = n;
list1:
n = 0;
c = getc(ib);
while(c >= '0' && c <= '9') {
n = n*10 + c-'0';
c = getc(ib);
}
if(n < 0 || n > 100)
goto ignore;
*cp++ = n;
if(c == ',')
goto list1;
if(c != '\t' && c != ' ')
goto ignore;
*cp++ = LIST;
continue;
range:
*cp++ = RANGE;
*cp++ = n;
n = 0;
c = getc(ib);
while(c >= '0' && c <= '9') {
n = n*10 + c-'0';
c = getc(ib);
}
if(n < 0 || n > 100)
goto ignore;
if(c != '\t' && c != ' ')
goto ignore;
*cp++ = n;
}
while(c != '\n') {
if(c <= 0)
goto ignore;
if(c == '%')
c = '\n';
*cp++ = c;
c = getc(ib);
}
*cp++ = '\n';
*cp++ = 0;
goto loop;
ignore:
cp = ocp;
while(c != '\n') {
if(c <= 0) {
close(ib[0]);
*cp++ = EOF;
*cp++ = EOF;
aend = cp;
brk(aend);
return;
}
c = getc(ib);
}
goto loop;
}