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