|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)cron.c 4.12 (Berkeley) 5/27/86";
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: #include <sys/wait.h>
12: #include <sys/ioctl.h>
13: #include <sys/file.h>
14: #include <pwd.h>
15: #include <fcntl.h>
16:
17: #define LISTS (2*BUFSIZ)
18: #define MAXLIN BUFSIZ
19:
20: #ifndef CRONTAB
21: #define CRONTAB "/usr/lib/crontab"
22: #endif
23:
24: #ifndef CRONTABLOC
25: #define CRONTABLOC "/usr/lib/crontab.local"
26: #endif
27:
28: #define EXACT 100
29: #define ANY 101
30: #define LIST 102
31: #define RANGE 103
32: #define EOS 104
33:
34: char crontab[] = CRONTAB;
35: char loc_crontab[] = CRONTABLOC;
36: time_t itime;
37: struct tm *loct;
38: struct tm *localtime();
39: char *malloc();
40: char *realloc();
41: int reapchild();
42: int flag;
43: char *list;
44: char *listend;
45: unsigned listsize;
46:
47: FILE *debug;
48: #define dprintf if (debug) fprintf
49:
50: main(argc, argv)
51: int argc;
52: char **argv;
53: {
54: register char *cp;
55: char *cmp();
56: time_t filetime = 0;
57: time_t lfiletime = 0;
58: char c;
59: extern char *optarg;
60:
61: if (fork())
62: exit(0);
63: c = getopt(argc, argv, "d:");
64: if (c == 'd') {
65: debug = fopen(optarg, "w");
66: if (debug == NULL)
67: exit(1);
68: fcntl(fileno(debug), F_SETFL, FAPPEND);
69: }
70: chdir("/");
71: freopen("/", "r", stdout);
72: freopen("/", "r", stderr);
73: untty();
74: signal(SIGHUP, SIG_IGN);
75: signal(SIGINT, SIG_IGN);
76: signal(SIGQUIT, SIG_IGN);
77: signal(SIGCHLD, reapchild);
78: time(&itime);
79: itime -= localtime(&itime)->tm_sec;
80:
81: for (;; itime+=60, slp()) {
82: struct stat cstat, lcstat;
83: int newcron, newloc;
84:
85: newcron = 0;
86: if (stat(crontab, &cstat) < 0)
87: cstat.st_mtime = 1;
88: if (cstat.st_mtime != filetime) {
89: filetime = cstat.st_mtime;
90: newcron++;
91: }
92:
93: newloc = 0;
94: if (stat(loc_crontab, &lcstat) < 0)
95: lcstat.st_mtime = 1;
96: if (lcstat.st_mtime != lfiletime) {
97: lfiletime = lcstat.st_mtime;
98: newloc++;
99: }
100:
101: if (newcron || newloc) {
102: init();
103: append(crontab);
104: append(loc_crontab);
105: *listend++ = EOS;
106: *listend++ = EOS;
107: }
108:
109: loct = localtime(&itime);
110: loct->tm_mon++; /* 1-12 for month */
111: if (loct->tm_wday == 0)
112: loct->tm_wday = 7; /* sunday is 7, not 0 */
113: for(cp = list; *cp != EOS;) {
114: flag = 0;
115: cp = cmp(cp, loct->tm_min);
116: cp = cmp(cp, loct->tm_hour);
117: cp = cmp(cp, loct->tm_mday);
118: cp = cmp(cp, loct->tm_mon);
119: cp = cmp(cp, loct->tm_wday);
120: if(flag == 0)
121: ex(cp);
122: while(*cp++ != 0)
123: ;
124: }
125: }
126: }
127:
128: char *
129: cmp(p, v)
130: char *p;
131: {
132: register char *cp;
133:
134: cp = p;
135: switch(*cp++) {
136:
137: case EXACT:
138: if (*cp++ != v)
139: flag++;
140: return(cp);
141:
142: case ANY:
143: return(cp);
144:
145: case LIST:
146: while(*cp != LIST)
147: if(*cp++ == v) {
148: while(*cp++ != LIST)
149: ;
150: return(cp);
151: }
152: flag++;
153: return(cp+1);
154:
155: case RANGE:
156: if(*cp > v || cp[1] < v)
157: flag++;
158: return(cp+2);
159: }
160: if(cp[-1] != v)
161: flag++;
162: return(cp);
163: }
164:
165: slp()
166: {
167: register i;
168: time_t t;
169:
170: time(&t);
171: i = itime - t;
172: if(i < -60 * 60 || i > 60 * 60) {
173: itime = t;
174: i = 60 - localtime(&itime)->tm_sec;
175: itime += i;
176: }
177: if(i > 0)
178: sleep(i);
179: }
180:
181: ex(s)
182: char *s;
183: {
184: int st;
185: register struct passwd *pwd;
186: char user[BUFSIZ];
187: char *c = user;
188: int pid;
189:
190: if (fork()) {
191: return;
192: }
193:
194: pid = getpid();
195: while(*s != ' ' && *s != '\t')
196: *c++ = *s++;
197: *c = '\0';
198: s++;
199: if ((pwd = getpwnam(user)) == NULL) {
200: dprintf(debug, "%d: cannot find %s\n", pid, user),
201: fflush(debug);
202: exit(1);
203: }
204: (void) setgid(pwd->pw_gid);
205: initgroups(pwd->pw_name, pwd->pw_gid);
206: (void) setuid(pwd->pw_uid);
207: freopen("/", "r", stdin);
208: dprintf(debug, "%d: executing %s", pid, s), fflush (debug);
209: execl("/bin/sh", "sh", "-c", s, 0);
210: dprintf(debug, "%d: cannot execute sh\n", pid), fflush (debug);
211: exit(0);
212: }
213:
214: init()
215: {
216: /*
217: * Don't free in case was longer than LISTS. Trades off
218: * the rare case of crontab shrinking vs. the common case of
219: * extra realloc's needed in append() for a large crontab.
220: */
221: if (list == 0) {
222: list = malloc(LISTS);
223: listsize = LISTS;
224: }
225: listend = list;
226: }
227:
228: append(fn)
229: char *fn;
230: {
231: register i, c;
232: register char *cp;
233: register char *ocp;
234: register int n;
235:
236: if (freopen(fn, "r", stdin) == NULL)
237: return;
238: cp = listend;
239: loop:
240: if(cp > list+listsize-MAXLIN) {
241: int length = cp - list;
242:
243: listsize += LISTS;
244: list = realloc(list, listsize);
245: cp = list + length;
246: }
247: ocp = cp;
248: for(i=0;; i++) {
249: do
250: c = getchar();
251: while(c == ' ' || c == '\t')
252: ;
253: if(c == EOF || c == '\n')
254: goto ignore;
255: if(i == 5)
256: break;
257: if(c == '*') {
258: *cp++ = ANY;
259: continue;
260: }
261: if ((n = number(c)) < 0)
262: goto ignore;
263: c = getchar();
264: if(c == ',')
265: goto mlist;
266: if(c == '-')
267: goto mrange;
268: if(c != '\t' && c != ' ')
269: goto ignore;
270: *cp++ = EXACT;
271: *cp++ = n;
272: continue;
273:
274: mlist:
275: *cp++ = LIST;
276: *cp++ = n;
277: do {
278: if ((n = number(getchar())) < 0)
279: goto ignore;
280: *cp++ = n;
281: c = getchar();
282: } while (c==',');
283: if(c != '\t' && c != ' ')
284: goto ignore;
285: *cp++ = LIST;
286: continue;
287:
288: mrange:
289: *cp++ = RANGE;
290: *cp++ = n;
291: if ((n = number(getchar())) < 0)
292: goto ignore;
293: c = getchar();
294: if(c != '\t' && c != ' ')
295: goto ignore;
296: *cp++ = n;
297: }
298: while(c != '\n') {
299: if(c == EOF)
300: goto ignore;
301: if(c == '%')
302: c = '\n';
303: *cp++ = c;
304: c = getchar();
305: }
306: *cp++ = '\n';
307: *cp++ = 0;
308: goto loop;
309:
310: ignore:
311: cp = ocp;
312: while(c != '\n') {
313: if(c == EOF) {
314: fclose(stdin);
315: listend = cp;
316: return;
317: }
318: c = getchar();
319: }
320: goto loop;
321: }
322:
323: number(c)
324: register c;
325: {
326: register n = 0;
327:
328: while (isdigit(c)) {
329: n = n*10 + c - '0';
330: c = getchar();
331: }
332: ungetc(c, stdin);
333: if (n>=100)
334: return(-1);
335: return(n);
336: }
337:
338: reapchild()
339: {
340: union wait status;
341: int pid;
342:
343: while ((pid = wait3(&status, WNOHANG, 0)) > 0)
344: dprintf(debug, "%d: child exits with signal %d status %d\n",
345: pid, status.w_termsig, status.w_retcode),
346: fflush (debug);
347: }
348:
349: untty()
350: {
351: int i;
352:
353: i = open("/dev/tty", O_RDWR);
354: if (i >= 0) {
355: ioctl(i, TIOCNOTTY, (char *)0);
356: (void) close(i);
357: }
358: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.