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