static char sccsid[] = "@(#)cron.c 1.3"; #include <sys/types.h> #include <stdio.h> #include <ctype.h> #include <signal.h> #include <time.h> #include <sys/stat.h> #define LISTS 512 #define HOUR 3600 #define EXACT 123 #define ANY 124 #define LIST 125 #define RANGE 126 #define EOS 127 char crontab[] = "/usr/lib/crontab"; char cronlog[] = "/usr/adm/cronlog"; time_t itime; struct tm *loct; struct tm *localtime(); char *malloc(); char *realloc(); char *ctime(); int flag; char *list; unsigned listsize; int rfork; char lorange[] = { 0,0,1,1,0 }, hirange[] = { 59,23,31,12,6 }; main() { register char *cp; char *cmp(); time_t filetime = 0; setuid(0); if (rfork = fork()) if(rfork == -1) { write(2, "cron: cannot fork\n",18); exit(2); } else exit(0); chdir("/"); signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); time(&itime); itime -= localtime(&itime)->tm_sec; for (;; itime+=60, slp()) { struct stat cstat; if(access(cronlog,2)==0) { freopen(crontab, "r", stdin); freopen(cronlog, "a", stdout); setbuf(stdout, NULL); close(fileno(stderr)); dup(1); fflush(stdin); } else { freopen("/dev/null", "r", stdout); freopen("/dev/null", "r", stderr); } if (itime%HOUR == 0) puts(""),puts(ctime(&itime)); if (stat(crontab, &cstat) == -1) continue; if (cstat.st_mtime > filetime) { filetime = cstat.st_mtime; puts(""),fputs(ctime(&itime), stdout),puts("crontab read"); init(); } loct = localtime(&itime); loct->tm_mon++; /* 1-12 for month */ for(cp = list; *cp != EOS;) { flag = 0; cp = cmp(cp, loct->tm_min); cp = cmp(cp, loct->tm_hour); cp = cmp(cp, loct->tm_mday); cp = cmp(cp, loct->tm_mon); cp = cmp(cp, loct->tm_wday); if(flag == 0) { slp(); ex(cp); } while(*cp++ != 0) ; } } } char * cmp(p, v) char *p; { register char *cp; cp = p; switch(*cp++) { case EXACT: if (*cp++ != v) flag++; return(cp); case ANY: return(cp); case LIST: while(*cp != LIST) if(*cp++ == v) { while(*cp++ != LIST) ; return(cp); } flag++; return(cp+1); case RANGE: if(cp[0] < cp[1]) { if(!(cp[0]<=v && cp[1]>=v)) ++flag; } else if(!(v>=cp[0] || v<=cp[1])) ++flag; return(cp+2); } if(cp[-1] != v) flag++; return(cp); } slp() { register i; time_t t; time(&t); i = itime - t; if(i > 0) sleep(i); } ex(s) char *s; { int st; fputs(s, stdout); again: if(rfork = fork()) { if(rfork == -1) { sleep(20); goto again; } wait(&st); return; } if(rfork = fork()) exit(0); if(rfork == -1) exit(2); freopen("/dev/null", "r", stdin); execl("/bin/sh", "sh", "-c", s, 0); exit(0); } init() { register i, c; register char *cp; register char *ocp, *cp2; register int n; freopen(crontab, "r", stdin); if (list) { free(list); list = realloc(list, LISTS); } else list = malloc(LISTS); listsize = LISTS; cp = list; loop: if(cp > list+listsize-256) { char *olist; listsize += LISTS; olist = list; free(list); list = realloc(list, listsize); cp = list + (cp - olist); } ocp = cp; for(i=0;; i++) { do c = getchar(); while(c == ' ' || c == '\t') ; if(c == EOF || c == '\n') goto ignore; if(i == 5) break; if(c == '*') { *cp++ = ANY; continue; } if ((n = number(c, lorange[i], hirange[i])) < 0) goto ignore; c = getchar(); if(c == ',') goto mlist; if(c == '-') goto mrange; if(c != '\t' && c != ' ') goto ignore; *cp++ = EXACT; *cp++ = n; continue; mlist: *cp++ = LIST; *cp++ = n; do { if ((n = number(getchar(), lorange[i], hirange[i])) < 0) goto ignore; *cp++ = n; c = getchar(); } while (c==','); if(c != '\t' && c != ' ') goto ignore; *cp++ = LIST; continue; mrange: *cp++ = RANGE; *cp++ = n; if ((n = number(getchar(), lorange[i], hirange[i])) < 0) goto ignore; c = getchar(); if(c != '\t' && c != ' ') goto ignore; *cp++ = n; } i = 0; while(c != '\n') { if(c == EOF) goto ignore; if(c == '%') { if (i == 0) { i++; for (cp2 = "<< __GNOME__"; *cp++ = *cp2++;) ; cp--; } c = '\n'; } *cp++ = c; c = getchar(); } *cp++ = '\n'; if (i) for (cp2 = "__GNOME__\n"; *cp++ = *cp2++;) ; else *cp++ = 0; goto loop; ignore: cp = ocp; while(c != '\n') { if(c == EOF) { *cp++ = EOS; *cp++ = EOS; fflush(stdin); return; } c = getchar(); } goto loop; } number(c, lowv, highv) register c; { register n = 0; while (isdigit(c)) { n = n*10 + c - '0'; c = getchar(); } ungetc(c, stdin); if (n<lowv || n>highv) { puts("value range error"); return -1; } return(n); }