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