xref: /original-bsd/usr.sbin/cron/cron.c (revision 8ac030d2)
1 static char *sccsid = "@(#)cron.c	4.6 (Berkeley) 06/28/82";
2 #include <sys/types.h>
3 #include <stdio.h>
4 #include <ctype.h>
5 #include <signal.h>
6 #include <time.h>
7 #include <sys/stat.h>
8 
9 #define	LISTS	(2*BUFSIZ)
10 #define	MAXLIN	BUFSIZ
11 
12 #define	EXACT	100
13 #define	ANY	101
14 #define	LIST	102
15 #define	RANGE	103
16 #define	EOS	104
17 char	crontab[]	= "/usr/lib/crontab";
18 time_t	itime;
19 struct	tm *loct;
20 struct	tm *localtime();
21 char	*malloc();
22 char	*realloc();
23 int	flag;
24 char	*list;
25 unsigned listsize;
26 
27 main()
28 {
29 	register char *cp;
30 	char *cmp();
31 	time_t filetime = 0;
32 
33      /*	setuid(1); */
34 	if (fork())
35 		exit(0);
36 	chdir("/");
37 	freopen(crontab, "r", stdin);
38 	freopen("/", "r", stdout);
39 	freopen("/", "r", stderr);
40 	signal(SIGHUP, SIG_IGN);
41 	signal(SIGINT, SIG_IGN);
42 	signal(SIGQUIT, SIG_IGN);
43 	time(&itime);
44 	itime -= localtime(&itime)->tm_sec;
45 	fclose(stdin);
46 
47 	for (;; itime+=60, slp()) {
48 		struct stat cstat;
49 
50 		if (stat(crontab, &cstat) == -1)
51 			continue;
52 		if (cstat.st_mtime > filetime) {
53 			filetime = cstat.st_mtime;
54 			init();
55 		}
56 		loct = localtime(&itime);
57 		loct->tm_mon++;		 /* 1-12 for month */
58 		if (loct->tm_wday == 0)
59 			loct->tm_wday == 7;	/* sunday is 7, not 0 */
60 		for(cp = list; *cp != EOS;) {
61 			flag = 0;
62 			cp = cmp(cp, loct->tm_min);
63 			cp = cmp(cp, loct->tm_hour);
64 			cp = cmp(cp, loct->tm_mday);
65 			cp = cmp(cp, loct->tm_mon);
66 			cp = cmp(cp, loct->tm_wday);
67 			if(flag == 0)
68 				ex(cp);
69 			while(*cp++ != 0)
70 				;
71 		}
72 	}
73 }
74 
75 char *
76 cmp(p, v)
77 char *p;
78 {
79 	register char *cp;
80 
81 	cp = p;
82 	switch(*cp++) {
83 
84 	case EXACT:
85 		if (*cp++ != v)
86 			flag++;
87 		return(cp);
88 
89 	case ANY:
90 		return(cp);
91 
92 	case LIST:
93 		while(*cp != LIST)
94 			if(*cp++ == v) {
95 				while(*cp++ != LIST)
96 					;
97 				return(cp);
98 			}
99 		flag++;
100 		return(cp+1);
101 
102 	case RANGE:
103 		if(*cp > v || cp[1] < v)
104 			flag++;
105 		return(cp+2);
106 	}
107 	if(cp[-1] != v)
108 		flag++;
109 	return(cp);
110 }
111 
112 slp()
113 {
114 	register i;
115 	time_t t;
116 
117 	time(&t);
118 	i = itime - t;
119 	if(i < -60 * 60 || i > 60 * 60) {
120 		itime = t;
121 		i = 60 - localtime(&itime)->tm_sec;
122 		itime += i;
123 	}
124 	if(i > 0)
125 		sleep(i);
126 }
127 
128 ex(s)
129 char *s;
130 {
131 	int st;
132 
133 	if(fork()) {
134 		wait(&st);
135 		return;
136 	}
137 	if(fork())
138 		exit(0);
139 	freopen("/", "r", stdin);
140 	execl("/bin/sh", "sh", "-c", s, 0);
141 	exit(0);
142 }
143 
144 init()
145 {
146 	register i, c;
147 	register char *cp;
148 	register char *ocp;
149 	register int n;
150 
151 	freopen(crontab, "r", stdin);
152 	if (list) {
153 		free(list);
154 		list = realloc(list, LISTS);
155 	} else
156 		list = malloc(LISTS);
157 	listsize = LISTS;
158 	cp = list;
159 
160 loop:
161 	if(cp > list+listsize-MAXLIN) {
162 		char *olist;
163 		listsize += LISTS;
164 		olist = list;
165 		free(list);
166 		list = realloc(list, listsize);
167 		cp = list + (cp - olist);
168 	}
169 	ocp = cp;
170 	for(i=0;; i++) {
171 		do
172 			c = getchar();
173 		while(c == ' ' || c == '\t')
174 			;
175 		if(c == EOF || c == '\n')
176 			goto ignore;
177 		if(i == 5)
178 			break;
179 		if(c == '*') {
180 			*cp++ = ANY;
181 			continue;
182 		}
183 		if ((n = number(c)) < 0)
184 			goto ignore;
185 		c = getchar();
186 		if(c == ',')
187 			goto mlist;
188 		if(c == '-')
189 			goto mrange;
190 		if(c != '\t' && c != ' ')
191 			goto ignore;
192 		*cp++ = EXACT;
193 		*cp++ = n;
194 		continue;
195 
196 	mlist:
197 		*cp++ = LIST;
198 		*cp++ = n;
199 		do {
200 			if ((n = number(getchar())) < 0)
201 				goto ignore;
202 			*cp++ = n;
203 			c = getchar();
204 		} while (c==',');
205 		if(c != '\t' && c != ' ')
206 			goto ignore;
207 		*cp++ = LIST;
208 		continue;
209 
210 	mrange:
211 		*cp++ = RANGE;
212 		*cp++ = n;
213 		if ((n = number(getchar())) < 0)
214 			goto ignore;
215 		c = getchar();
216 		if(c != '\t' && c != ' ')
217 			goto ignore;
218 		*cp++ = n;
219 	}
220 	while(c != '\n') {
221 		if(c == EOF)
222 			goto ignore;
223 		if(c == '%')
224 			c = '\n';
225 		*cp++ = c;
226 		c = getchar();
227 	}
228 	*cp++ = '\n';
229 	*cp++ = 0;
230 	goto loop;
231 
232 ignore:
233 	cp = ocp;
234 	while(c != '\n') {
235 		if(c == EOF) {
236 			*cp++ = EOS;
237 			*cp++ = EOS;
238 			fclose(stdin);
239 			return;
240 		}
241 		c = getchar();
242 	}
243 	goto loop;
244 }
245 
246 number(c)
247 register c;
248 {
249 	register n = 0;
250 
251 	while (isdigit(c)) {
252 		n = n*10 + c - '0';
253 		c = getchar();
254 	}
255 	ungetc(c, stdin);
256 	if (n>100)
257 		return(-1);
258 	return(n);
259 }
260