|
|
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.