Annotation of 43BSDReno/usr.sbin/cron/cron.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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