Annotation of 43BSDTahoe/etc/cron.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.