SRI-NOSC/s1/cron.c

Compare this file to the similar file:
Show the results in this format:

#/*
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;
}