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