Annotation of coherent/d/etc/cron.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Cron. Execute commands stored in /usr/lib/crontab at preset times.
                      3:  * It sets its uid and gid to those of daemon, if possible.
                      4:  */
                      5: 
                      6: #include <stdio.h>
                      7: #include <time.h>
                      8: #include <signal.h>
                      9: #include <errno.h>
                     10: #include <ctype.h>
                     11: #include <pwd.h>
                     12: 
                     13: #define        TRUE    (0 == 0)
                     14: #define FALSE  (0 != 0)
                     15: 
                     16: /*
                     17:  * Time field types.
                     18:  */
                     19: #define        MIN     0
                     20: #define HOUR   1
                     21: #define        MDAY    2
                     22: #define        MON     3
                     23: #define WDAY   4
                     24: 
                     25: /*
                     26:  * (Finite) States in valid().
                     27:  */
                     28: #define START  0
                     29: #define INT    1
                     30: #define INTDASH        2
                     31: #define RANGE  3
                     32: #define STR    4
                     33: #define STRPLUS        5
                     34: #define ERR    6
                     35: #define END    7
                     36: #define GLOB   ('*')
                     37: 
                     38: /*
                     39:  * Tokens returned by gettoken(). Tokens are integers. EOF is also a token.
                     40:  * INT, STR and GLOB above are also tokens.
                     41:  */
                     42: #define DASH   ('-')
                     43: #define COMMA  (',')
                     44: #define WS     (' ')
                     45: #define PERCENT        (-2)
                     46: #define NEWLINE (-3)
                     47: 
                     48: struct tm *tm;
                     49: long   clock;
                     50: int    tmfield[5];
                     51: FILE   *f;
                     52: extern int     errno;
                     53: 
                     54: int    ugtokflag = FALSE;
                     55: int    ugtoken;
                     56: int    ufetflag = FALSE;
                     57: int    ufetval;
                     58: 
                     59: char   *tokbuf;
                     60: int    buflen = 512;
                     61: char   crontab[] = "/usr/lib/crontab";
                     62: 
                     63: 
                     64: main()
                     65: {
                     66:        int n;
                     67:        sigsetup();
                     68: 
                     69:        todaemon();
                     70:        tokbuf = malloc(buflen);
                     71:        chdir("/bin");
                     72:        time(&clock);
                     73:        tm = localtime(&clock);
                     74:        alarm(61 - tm->tm_sec);
                     75: 
                     76:        for (;;) {
                     77:                /* Put the time values into tmfield[] for easy reference.
                     78:                 * localtime() gives tm_mon in the range 0-11, tm_wday, 0-6
                     79:                 * (0=sunday). These are adjusted for cron's syntax.
                     80:                 */
                     81:                tmfield[MIN]    = tm->tm_min;
                     82:                tmfield[HOUR]   = tm->tm_hour;
                     83:                tmfield[MDAY]   = tm->tm_mday;
                     84:                tmfield[MON]    = tm->tm_mon + 1;
                     85:                tmfield[WDAY]   = tm->tm_wday;
                     86: 
                     87:                if ((f = fopen(crontab, "r")) != NULL) {
                     88:                        while (tex() != EOF)
                     89:                                ;
                     90:                        fclose(f);
                     91:                }
                     92:                while (wait(&n) != -1)
                     93:                        ;
                     94:                if (errno == ECHILD)
                     95:                        pause();
                     96:        }
                     97: }
                     98: 
                     99: /*
                    100:  * Test and Execute: tests a crontab entry against the time fields in `tm' to
                    101:  * see if it should be executed, if so it executes. f is left pointing to the
                    102:  * next entry (line). Returns EOF when encountered, something else otherwise.
                    103:  */
                    104: tex()
                    105: {
                    106:        register int fieldnum;
                    107: 
                    108:        for (fieldnum = MIN; fieldnum <= WDAY; ++fieldnum)
                    109:                if (!valid(fieldnum))
                    110:                        return (skip_it());
                    111:        return (do_it());
                    112: }
                    113: 
                    114: /*
                    115:  * Valid(fieldnum) parses the next time field from the current line in crontab
                    116:  * and checks whether tmfield[fieldnum] satisfies the constraints of that time
                    117:  * field. Returns TRUE if so, FALSE if not. Leaves f at the next field.
                    118:  * Detects syntax errors in the time fields.
                    119:  */
                    120: valid(fieldnum)
                    121: int fieldnum;
                    122: {
                    123:        register int t;
                    124:        register int ival;
                    125:        register int state = START;
                    126:        int ival2;
                    127:        int tm_val = tmfield[fieldnum];
                    128: 
                    129:        if (fieldnum == MIN) {
                    130:                while ((t = gettoken()) == WS  ||  t == NEWLINE)
                    131:                        ;
                    132:                ungettoken(t);
                    133:        }
                    134: 
                    135:        for (;;) {
                    136:                t = gettoken();
                    137:                switch (state) {
                    138:                case START:
                    139:                        switch (t) {
                    140:                        case INT:
                    141:                                if (strlen(tokbuf) <= 2) {
                    142:                                        ival = atoi(tokbuf);
                    143:                                        state = INT;
                    144:                                }
                    145:                                else
                    146:                                        state = ERR;
                    147:                                break;
                    148:                        case GLOB:
                    149:                                state = GLOB;
                    150:                                break;
                    151:                        case WS:
                    152:                                state = END;
                    153:                                break;
                    154:                        default:
                    155:                                state = ERR;
                    156:                                break;
                    157:                        }
                    158:                        break;
                    159:                case INT:
                    160:                        if (t == COMMA  ||  t == WS) {
                    161:                                if (ival == tm_val) {
                    162:                                        while (t != WS)
                    163:                                                t = gettoken();
                    164:                                        return (TRUE);
                    165:                                }
                    166:                                state = (t == WS) ? END : START;
                    167:                        }
                    168:                        else if (t == DASH)
                    169:                                state = INTDASH;
                    170:                        else
                    171:                                state = ERR;
                    172:                        break;
                    173:                case INTDASH:
                    174:                        if (t == INT  &&  strlen(tokbuf) <= 2) {
                    175:                                ival2 = atoi(tokbuf);
                    176:                                state = RANGE;
                    177:                        }
                    178:                        else
                    179:                                state = ERR;
                    180:                        break;
                    181:                case RANGE:
                    182:                        if (t == COMMA  ||  t == WS) {
                    183:                                if (ival <= tm_val  &&  tm_val <= ival2) {
                    184:                                        while (t != WS)
                    185:                                                t = gettoken();
                    186:                                        return (TRUE);
                    187:                                }
                    188:                                state = (t == WS) ? END : START;
                    189:                        }
                    190:                        else
                    191:                                state = ERR;
                    192:                        break;
                    193:                case GLOB:
                    194:                        if (t == COMMA  ||  t == WS) {
                    195:                                while (t != WS)
                    196:                                        t = gettoken();
                    197:                                return (TRUE);
                    198:                        }
                    199:                        else
                    200:                                state = ERR;
                    201:                        break;
                    202:                }               /* End switch on state */
                    203: 
                    204:                if (state == END)
                    205:                        return (FALSE);
                    206:                if (state == ERR) {
                    207:                        ungettoken(t);
                    208:                        ungettoken(skip_it());
                    209:                        return (FALSE);
                    210:                }
                    211:        }
                    212: }
                    213: 
                    214: 
                    215: ungettoken(t)
                    216: int t;
                    217: {
                    218:        ugtokflag = TRUE;
                    219:        ugtoken = t;
                    220: }
                    221: 
                    222: gettoken()
                    223: {
                    224:        register int c;
                    225:        register char *sp = tokbuf;
                    226:        register char *mark;
                    227:        int posn;
                    228: 
                    229:        if (ugtokflag) {
                    230:                ugtokflag = FALSE;
                    231:                return (ugtoken);
                    232:        }
                    233: 
                    234:        switch (c = fetch()) {
                    235:        case NEWLINE:
                    236:        case EOF:
                    237:        case PERCENT:
                    238:                return (c);
                    239:        case ' ':
                    240:        case '\t':
                    241:                while ((c = fetch()) == ' '  ||  c == '\t')
                    242:                        ;
                    243:                unfetch(c);
                    244:                return (WS);
                    245:        case '-':
                    246:                return (DASH);
                    247:        case ',':
                    248:                return (COMMA);
                    249:        case '*':
                    250:                return (GLOB);
                    251:        }
                    252: 
                    253: 
                    254:        /*
                    255:         * Case of INT. Place ascii digit string into tokbuf.
                    256:         */
                    257:        if (isdigit(c)) {
                    258:                *sp++ = c;
                    259:                while (isdigit(c = fetch()))
                    260:                        *sp++ = c;
                    261:                unfetch(c);
                    262:                *sp = '\0';
                    263:                return (INT);
                    264:        }
                    265: 
                    266:        /*
                    267:         * The only remaining possibility is the token STR or STRPLUS.
                    268:         */
                    269:        *sp++ = c;
                    270:        mark = tokbuf + buflen - 2;
                    271:        while ((c = fetch()) != EOF  &&  c != NEWLINE  &&  c != PERCENT) {
                    272:                if (sp == mark) {
                    273:                        posn = sp - tokbuf;
                    274:                        tokbuf = realloc(tokbuf, (buflen += 128));
                    275:                        sp = tokbuf + posn;
                    276:                        mark = sp + buflen;
                    277:                }
                    278:                *sp++ = c;
                    279:        }
                    280:        *sp = '\0';
                    281:        if (c == PERCENT)
                    282:                return (STRPLUS);
                    283:        unfetch(c);
                    284:        return (STR);
                    285: }
                    286: 
                    287: 
                    288: unfetch(c)
                    289: int c;
                    290: {
                    291:        ufetval = c;
                    292:        ufetflag = TRUE;
                    293: }
                    294: 
                    295: fetch()
                    296: {
                    297:        register int c;
                    298:        register int c2;
                    299: 
                    300:        if (ufetflag) {
                    301:                ufetflag = FALSE;
                    302:                return (ufetval);
                    303:        }
                    304: 
                    305:        for (;;)
                    306:                switch (c = getc(f)) {
                    307:                case '%':
                    308:                        return (PERCENT);
                    309:                case '\n':
                    310:                        return (NEWLINE);
                    311:                case '\\':
                    312:                        if ((c2 = getc(f)) == '%')
                    313:                                return ('%');
                    314:                        else if (c2 == '\n')
                    315:                                continue;
                    316:                        else {
                    317:                                ungetc(c2, f);
                    318:                                return ('\\');
                    319:                        }
                    320:                default:
                    321:                        return (c);
                    322:                }
                    323: }
                    324: 
                    325: 
                    326: skip_it()
                    327: {
                    328:        register int t;
                    329: 
                    330:        while ((t = gettoken()) != EOF  &&  t != NEWLINE)
                    331:                ;
                    332:        return (t);
                    333: }
                    334: 
                    335: do_it()
                    336: {
                    337:        register int c;
                    338:        register FILE *fp;
                    339: 
                    340:        if ((c = gettoken()) != STR  &&  c != STRPLUS) {
                    341:                ungettoken(c);
                    342:                return (skip_it());
                    343:        }
                    344:        if ((fp = popen(tokbuf, "w")) == NULL) {
                    345:                fprintf(stderr, "Cron:\tCould not popen: %s\n\t\
                    346:                                errno = %d: %s.\n", tokbuf, errno, perror());
                    347:                return (skip_it());
                    348:        }
                    349:        if (c == STR) {
                    350:                fclose(fp);
                    351:                return (gettoken());
                    352:        }
                    353:        while ((c = fetch()) != NEWLINE  &&  c != EOF)
                    354:                if (c == PERCENT)
                    355:                        putc('\n', fp);
                    356:                else
                    357:                        putc(c, fp);
                    358:        putc('\n', fp);
                    359:        fclose(fp);
                    360:        return(c);
                    361: }
                    362: 
                    363: sigsetup()
                    364: {
                    365:        int catchalarm();
                    366: 
                    367:        signal(SIGHUP, SIG_IGN);
                    368:        signal(SIGINT, SIG_IGN);
                    369:        signal(SIGPIPE, SIG_IGN);
                    370:        signal(SIGALRM, catchalarm);
                    371: }
                    372: 
                    373: catchalarm()
                    374: {
                    375:        signal(SIGALRM, catchalarm);
                    376:        time(&clock);
                    377:        tm = localtime(&clock);
                    378:        alarm(61 - tm->tm_sec);
                    379: }
                    380: 
                    381: todaemon()
                    382: {
                    383:        register struct passwd  *pwp;
                    384:        struct passwd   *getpwnam();
                    385: 
                    386:        pwp = getpwnam("daemon");
                    387:        endpwent();
                    388:        if (pwp == NULL)
                    389:                return;
                    390:        setgid(pwp->pw_gid);
                    391:        setuid(pwp->pw_uid);
                    392: }

unix.superglobalmegacorp.com

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