xref: /original-bsd/usr.sbin/cron/cron.c (revision 1f3a482a)
1 static char *sccsid = "@(#)cron.c	4.3 (Berkeley) 07/05/81";
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	100
12 #define	ANY	101
13 #define	LIST	102
14 #define	RANGE	103
15 #define	EOS	104
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 				ex(cp);
66 			while(*cp++ != 0)
67 				;
68 		}
69 	}
70 }
71 
72 char *
73 cmp(p, v)
74 char *p;
75 {
76 	register char *cp;
77 
78 	cp = p;
79 	switch(*cp++) {
80 
81 	case EXACT:
82 		if (*cp++ != v)
83 			flag++;
84 		return(cp);
85 
86 	case ANY:
87 		return(cp);
88 
89 	case LIST:
90 		while(*cp != LIST)
91 			if(*cp++ == v) {
92 				while(*cp++ != LIST)
93 					;
94 				return(cp);
95 			}
96 		flag++;
97 		return(cp+1);
98 
99 	case RANGE:
100 		if(*cp > v || cp[1] < v)
101 			flag++;
102 		return(cp+2);
103 	}
104 	if(cp[-1] != v)
105 		flag++;
106 	return(cp);
107 }
108 
109 slp()
110 {
111 	register i;
112 	time_t t;
113 
114 	time(&t);
115 	i = itime - t;
116 	if(i < -60 * 60 || i > 60 * 60) {
117 		itime = t;
118 		i = 60 - localtime(&itime)->tm_sec;
119 		itime += i;
120 	}
121 	if(i > 0)
122 		sleep(i);
123 }
124 
125 ex(s)
126 char *s;
127 {
128 	int st;
129 
130 	if(fork()) {
131 		wait(&st);
132 		return;
133 	}
134 	if(fork())
135 		exit(0);
136 	freopen("/", "r", stdin);
137 	execl("/bin/sh", "sh", "-c", s, 0);
138 	exit(0);
139 }
140 
141 init()
142 {
143 	register i, c;
144 	register char *cp;
145 	register char *ocp;
146 	register int n;
147 
148 	freopen(crontab, "r", stdin);
149 	if (list) {
150 		free(list);
151 		list = realloc(list, LISTS);
152 	} else
153 		list = malloc(LISTS);
154 	listsize = LISTS;
155 	cp = list;
156 
157 loop:
158 	if(cp > list+listsize-100) {
159 		char *olist;
160 		listsize += LISTS;
161 		olist = list;
162 		free(list);
163 		list = realloc(list, listsize);
164 		cp = list + (cp - olist);
165 	}
166 	ocp = cp;
167 	for(i=0;; i++) {
168 		do
169 			c = getchar();
170 		while(c == ' ' || c == '\t')
171 			;
172 		if(c == EOF || c == '\n')
173 			goto ignore;
174 		if(i == 5)
175 			break;
176 		if(c == '*') {
177 			*cp++ = ANY;
178 			continue;
179 		}
180 		if ((n = number(c)) < 0)
181 			goto ignore;
182 		c = getchar();
183 		if(c == ',')
184 			goto mlist;
185 		if(c == '-')
186 			goto mrange;
187 		if(c != '\t' && c != ' ')
188 			goto ignore;
189 		*cp++ = EXACT;
190 		*cp++ = n;
191 		continue;
192 
193 	mlist:
194 		*cp++ = LIST;
195 		*cp++ = n;
196 		do {
197 			if ((n = number(getchar())) < 0)
198 				goto ignore;
199 			*cp++ = n;
200 			c = getchar();
201 		} while (c==',');
202 		if(c != '\t' && c != ' ')
203 			goto ignore;
204 		*cp++ = LIST;
205 		continue;
206 
207 	mrange:
208 		*cp++ = RANGE;
209 		*cp++ = n;
210 		if ((n = number(getchar())) < 0)
211 			goto ignore;
212 		c = getchar();
213 		if(c != '\t' && c != ' ')
214 			goto ignore;
215 		*cp++ = n;
216 	}
217 	while(c != '\n') {
218 		if(c == EOF)
219 			goto ignore;
220 		if(c == '%')
221 			c = '\n';
222 		*cp++ = c;
223 		c = getchar();
224 	}
225 	*cp++ = '\n';
226 	*cp++ = 0;
227 	goto loop;
228 
229 ignore:
230 	cp = ocp;
231 	while(c != '\n') {
232 		if(c == EOF) {
233 			*cp++ = EOS;
234 			*cp++ = EOS;
235 			fclose(stdin);
236 			return;
237 		}
238 		c = getchar();
239 	}
240 	goto loop;
241 }
242 
243 number(c)
244 register c;
245 {
246 	register n = 0;
247 
248 	while (isdigit(c)) {
249 		n = n*10 + c - '0';
250 		c = getchar();
251 	}
252 	ungetc(c, stdin);
253 	if (n>100)
254 		return(-1);
255 	return(n);
256 }
257