Annotation of coherent/d/etc/SYSVcron/src/cron.new, revision 1.1.1.1

1.1       root        1: /* 
                      2:  *     The information contained herein is a trade secret of Mark Williams
                      3:  *     Company, and  is confidential information.  It is provided  under a
                      4:  *     license agreement,  and may be  copied or disclosed  only under the
                      5:  *     terms of  that agreement.  Any  reproduction or disclosure  of this
                      6:  *     material without the express written authorization of Mark Williams
                      7:  *     Company or persuant to the license agreement is unlawful.
                      8:  *
                      9:  *     An unpublished work by Mark Williams Company, Chicago.
                     10:  *     All rights reserved.
                     11:  */
                     12: 
                     13: /* cron.c
                     14:  *
                     15:  * Execute commands stored in /usr/lib/crontab if it exist (3.2.0 compatibility)
                     16:  * as daemon.
                     17:  * Otherwise execute crontabs from /usr/spool/cron/crontabs.
                     18:  * It sets uid and gid to user which crontab is going to be executed.
                     19:  *
                     20:  * $ 12-10-1991 vlad (Vladimir Smelyansky)
                     21:  *
                     22:  */
                     23: #include <stdio.h>
                     24: #include <time.h>
                     25: #include <signal.h>
                     26: #include <sys/msig.h>
                     27: #include <errno.h>
                     28: #include <ctype.h>
                     29: #include <pwd.h>
                     30: #include <sys/types.h>
                     31: #include <dirent.h>
                     32: #include "cron.h"
                     33: 
                     34: /*
                     35:  * Time field types.
                     36:  */
                     37: #define        MIN     0
                     38: #define HOUR   1
                     39: #define        MDAY    2
                     40: #define        MON     3
                     41: #define WDAY   4
                     42: 
                     43: /*
                     44:  * (Finite) States in valid().
                     45:  */
                     46: #define START  0
                     47: #define INT    1
                     48: #define INTDASH        2
                     49: #define RANGE  3
                     50: #define STR    4
                     51: #define STRPLUS        5
                     52: #define ERR    6
                     53: #define END    7
                     54: #define GLOB   ('*')
                     55: 
                     56: /*
                     57:  * Tokens returned by gettoken(). Tokens are integers. EOF is also a token.
                     58:  * INT, STR and GLOB above are also tokens.
                     59:  */
                     60: #define DASH   ('-')
                     61: #define COMMA  (',')
                     62: #define WS     (' ')
                     63: #define PERCENT        (-2)
                     64: #define NEWLINE (-3)
                     65: 
                     66: extern DIR             *opendir();
                     67: extern struct dirent   *readdir();
                     68: extern char            *realloc();
                     69: 
                     70: extern int     set_uid();      /* Set UID */
                     71: extern FILE    *fpOpenTable(); /* Open crintable */
                     72: extern int     lock();         /* Write a lock file */
                     73: extern FILE    *cronpipe();    /* Popen for cron */
                     74: 
                     75: extern void    mail_entry();   /* Send mail to user if command failed */
                     76: extern child_id        *add_entry(),   /* Add an new entry to a link list */
                     77:                *find_entry(),  /* Find an entry in the link list */
                     78:                *del_entry();   /* Remove an entry from the link list */
                     79: 
                     80: int ifmail();
                     81: 
                     82: child_id       *current;       /* Pointer to the current structure */
                     83: char   acRealUser[MAX_UNAME];  /* Real user name */
                     84: 
                     85: int    mailFlag = TRUE;
                     86: int    flag320 = FALSE;
                     87: 
                     88: struct tm *tm;
                     89: time_t clock;
                     90: int    tmfield[5];
                     91: FILE   *f;
                     92: extern int     errno;
                     93: 
                     94: int    ugtokflag = FALSE;
                     95: int    ugtoken;
                     96: int    ufetflag = FALSE;
                     97: int    ufetval;
                     98: int    set_uid_flag = FALSE;
                     99: 
                    100: char   *tokbuf;
                    101: int    buflen = MAX_STR_LEN;
                    102: char   crontab[] = "/usr/lib/crontab";
                    103: DIR    *dirp = NULL;
                    104: struct dirent  *dp;
                    105: 
                    106: main()
                    107: {
                    108:        int     n;
                    109:        int     child_pid;
                    110: 
                    111:        sigsetup();
                    112: 
                    113:        tokbuf = malloc(buflen);
                    114:        /* Check if crond chould be into cron 320 mode */
                    115:        if ((f = fopen(crontab, "r")) != NULL) {
                    116:                fclose(f);
                    117:                chdir("/bin");  /* Under 3.2.0 cron started from /bin. */
                    118:                flag320 = TRUE;
                    119:        }               
                    120: 
                    121:        if (flag320 == FALSE)   {
                    122:                /* Check if cron was fired. Do it only for SV cron. */
                    123:                if (lock(F_LOCK) == FALSE) {
                    124:                        fprintf(stderr, "crond: locked.\n");
                    125:                        exit(1);
                    126:                }
                    127:                /* Open dirp only once */
                    128:                /*if ((dirp = opendir(D_SPOOL)) == NULL) {
                    129:                        fprintf(stderr, 
                    130:                                 "crond: cannot open directory %s.\n", D_SPOOL);
                    131:                        exit(1);
                    132:                }*/
                    133:        }
                    134: 
                    135: #if !DEBUG
                    136:        /* Disassociate from controling terminal and process
                    137:         * group. Close all open files.
                    138:         */
                    139:        bedaemon();
                    140: #endif                 
                    141: 
                    142:        time(&clock);
                    143:        tm = localtime(&clock);
                    144:        alarm(61 - tm->tm_sec);
                    145: 
                    146:        Dprint("Time is %s\n", ctime(&clock));
                    147:        for (;;) {
                    148:                system("echo Debug1 >/dev/console");
                    149:                /* Put the time values into tmfield[] for easy reference.
                    150:                 * localtime() gives tm_mon in the range 0-11, tm_wday, 0-6
                    151:                 * (0=sunday). These are adjusted for cron's syntax.
                    152:                 */
                    153:                tmfield[MIN]    = tm->tm_min;
                    154:                tmfield[HOUR]   = tm->tm_hour;
                    155:                tmfield[MDAY]   = tm->tm_mday;
                    156:                tmfield[MON]    = tm->tm_mon + 1;
                    157:                tmfield[WDAY]   = tm->tm_wday;
                    158: 
                    159:                if (flag320 == TRUE) {          /* Run 320 mode */
                    160:                        system("echo Debug1 286>/dev/console");
                    161:                        if ((f = fopen(crontab, "r")) != NULL) {
                    162:                                Dprint("File pointer is 0x%x\n", f);
                    163:                                strcpy(acRealUser, DAEMON);
                    164:                                while (tex() != EOF)
                    165:                                        ;
                    166:                                fclose(f);
                    167:                                while (wait(&n) != -1) 
                    168:                                        ;
                    169:                                if (errno == ECHILD)
                    170:                                        pause();
                    171:                        } else
                    172:                                fprintf(stderr, "crond: cannot open %s\n", 
                    173:                                                crontab);
                    174:                } else {                        /* Run SV mode */
                    175:                        system("echo Debug1 386>/dev/console");
                    176:                        /* Open dirp only once */
                    177:                        if (dirp != NULL)
                    178:                                if ((dirp = opendir(D_SPOOL)) == NULL) {
                    179:                                        fprintf(stderr, 
                    180:                                 "crond: cannot open directory %s.\n", D_SPOOL);
                    181:                                        exit(1);
                    182:                                }
                    183: 
                    184:                        while ((dp = readdir(dirp)) != NULL) {
                    185:                                char    Dbuf[80];
                    186: 
                    187:                                /* Skip '.' and '..' */
                    188:                                if (!strcmp(dp->d_name, ".") ||
                    189:                                                !strcmp(dp->d_name, ".."))
                    190:                                        continue;
                    191:                
                    192:                                strcpy(acRealUser, dp->d_name);
                    193:                                Dprint("User name is %s\n", acRealUser);
                    194:                                set_uid_flag = FALSE; 
                    195: 
                    196:                                if ((f = fpOpenTable("r")) == NULL) {
                    197:                                        fprintf(stderr, 
                    198:                                           "crond: cannot open table '%s'\n", 
                    199:                                           acRealUser);
                    200:                                        sprintf(Dbuf,"crond: cannot open table"
                    201:                                           " '%s'\n", acRealUser);
                    202:                                           /*exit(1);*/
                    203:                                }
                    204:                                system("echo Debug >/dev/console");
                    205:                        sprintf(Dbuf, "echo %s > /dev/console", dp->d_name);
                    206:                                system(Dbuf);
                    207:                                while (tex() != EOF)
                    208:                                        ;
                    209:                                fclose(f);
                    210:                        } /* while readdir */
                    211:                        system("echo Debug after while >/dev/console");
                    212:                        rewinddir(dirp);
                    213:                        /* Wait for the children */
                    214:                        while ((child_pid = wait(&n)) != -1) {
                    215:                                static child_id *pstDone;
                    216: 
                    217:                                Dprint("\nmain: child id %d",child_pid);
                    218:                                Dprint("\treturn is %d\n", n);
                    219:                                pstDone = find_entry(child_pid);
                    220:                                if (n && ifmail(pstDone))
                    221:                                        mail_entry(pstDone);
                    222: 
                    223:                                current = del_entry(pstDone);
                    224:                        } /* while wait */
                    225:                        if (errno == ECHILD)
                    226:                                pause();
                    227:                        
                    228:                } /* if 320 */
                    229:        } /* for */
                    230: } /* main */
                    231: 
                    232: /*
                    233:  * Check do user want to have a mail messages. 
                    234:  */
                    235: int ifmail(entry)
                    236: child_id       *entry;
                    237: {
                    238:        char    *cBuf;
                    239:        int     fd;     /* Descriptor of lock file */
                    240: 
                    241:        if ((cBuf = malloc(sizeof(D_MAIN) + strlen(entry->name) + 1)) == NULL) {
                    242:                fprintf(stderr, "crond: out of memory\n");
                    243:                return(0);      
                    244:        }
                    245:        sprintf(cBuf, "%s/%s", D_MAIN, entry->name);
                    246:        if ((fd = open(cBuf, 0)) == -1) 
                    247:                return(1);
                    248:        close(fd);
                    249:        return(0);
                    250: }
                    251: 
                    252: /*
                    253:  * Test and Execute: tests a crontab entry against the time fields in `tm' to
                    254:  * see if it should be executed, if so it executes. f is left pointing to the
                    255:  * next entry (line). Returns EOF when encountered, something else otherwise.
                    256:  */
                    257: tex()
                    258: {
                    259:        register int fieldnum;
                    260: 
                    261:        for (fieldnum = MIN; fieldnum <= WDAY; ++fieldnum)
                    262:                if (!valid(fieldnum))
                    263:                        return (skip_it());
                    264:        return (do_it());
                    265: }
                    266: 
                    267: /*
                    268:  * Valid(fieldnum) parses the next time field from the current line in crontab
                    269:  * and checks whether tmfield[fieldnum] satisfies the constraints of that time
                    270:  * field. Returns TRUE if so, FALSE if not. Leaves f at the next field.
                    271:  * Detects syntax errors in the time fields.
                    272:  */
                    273: valid(fieldnum)
                    274: int fieldnum;
                    275: {
                    276:        register int t;
                    277:        register int ival;
                    278:        register int state = START;
                    279:        int ival2;
                    280:        int tm_val = tmfield[fieldnum];
                    281: 
                    282:        if (fieldnum == MIN) {
                    283:                while ((t = gettoken()) == WS  ||  t == NEWLINE)
                    284:                        ;
                    285:                ungettoken(t);
                    286:        }
                    287: 
                    288:        for (;;) {
                    289:                t = gettoken();
                    290:                switch (state) {
                    291:                case START:
                    292:                        switch (t) {
                    293:                        case INT:
                    294:                                if (strlen(tokbuf) <= 2) {
                    295:                                        ival = atoi(tokbuf);
                    296:                                        state = INT;
                    297:                                }
                    298:                                else
                    299:                                        state = ERR;
                    300:                                break;
                    301:                        case GLOB:
                    302:                                state = GLOB;
                    303:                                break;
                    304:                        case WS:
                    305:                                state = END;
                    306:                                break;
                    307:                        default:
                    308:                                state = ERR;
                    309:                                break;
                    310:                        }
                    311:                        break;
                    312:                case INT:
                    313:                        if (t == COMMA  ||  t == WS) {
                    314:                                if (ival == tm_val) {
                    315:                                        while (t != WS)
                    316:                                                t = gettoken();
                    317:                                        return (TRUE);
                    318:                                }
                    319:                                state = (t == WS) ? END : START;
                    320:                        }
                    321:                        else if (t == DASH)
                    322:                                state = INTDASH;
                    323:                        else
                    324:                                state = ERR;
                    325:                        break;
                    326:                case INTDASH:
                    327:                        if (t == INT  &&  strlen(tokbuf) <= 2) {
                    328:                                ival2 = atoi(tokbuf);
                    329:                                state = RANGE;
                    330:                        }
                    331:                        else
                    332:                                state = ERR;
                    333:                        break;
                    334:                case RANGE:
                    335:                        if (t == COMMA  ||  t == WS) {
                    336:                                if (ival <= tm_val  &&  tm_val <= ival2) {
                    337:                                        while (t != WS)
                    338:                                                t = gettoken();
                    339:                                        return (TRUE);
                    340:                                }
                    341:                                state = (t == WS) ? END : START;
                    342:                        }
                    343:                        else
                    344:                                state = ERR;
                    345:                        break;
                    346:                case GLOB:
                    347:                        if (t == COMMA  ||  t == WS) {
                    348:                                while (t != WS)
                    349:                                        t = gettoken();
                    350:                                return (TRUE);
                    351:                        }
                    352:                        else
                    353:                                state = ERR;
                    354:                        break;
                    355:                }               /* End switch on state */
                    356: 
                    357:                if (state == END)
                    358:                        return (FALSE);
                    359:                if (state == ERR) {
                    360:                        ungettoken(t);
                    361:                        ungettoken(skip_it());
                    362:                        return (FALSE);
                    363:                }
                    364:        }
                    365: }
                    366: 
                    367: 
                    368: ungettoken(t)
                    369: int t;
                    370: {
                    371:        ugtokflag = TRUE;
                    372:        ugtoken = t;
                    373: }
                    374: 
                    375: gettoken()
                    376: {
                    377:        register int c;
                    378:        register char *sp = tokbuf;
                    379:        register char *mark;
                    380:        int posn;
                    381: 
                    382:        if (ugtokflag) {
                    383:                ugtokflag = FALSE;
                    384:                return (ugtoken);
                    385:        }
                    386: 
                    387:        switch (c = fetch()) {
                    388:        case NEWLINE:
                    389:        case EOF:
                    390:        case PERCENT:
                    391:                return (c);
                    392:        case ' ':
                    393:        case '\t':
                    394:                while ((c = fetch()) == ' '  ||  c == '\t')
                    395:                        ;
                    396:                unfetch(c);
                    397:                return (WS);
                    398:        case '-':
                    399:                return (DASH);
                    400:        case ',':
                    401:                return (COMMA);
                    402:        case '*':
                    403:                return (GLOB);
                    404:        }
                    405: 
                    406: 
                    407:        /*
                    408:         * Case of INT. Place ascii digit string into tokbuf.
                    409:         */
                    410:        if (isdigit(c)) {
                    411:                *sp++ = c;
                    412:                while (isdigit(c = fetch()))
                    413:                        *sp++ = c;
                    414:                unfetch(c);
                    415:                *sp = '\0';
                    416:                return (INT);
                    417:        }
                    418: 
                    419:        /*
                    420:         * The only remaining possibility is the token STR or STRPLUS.
                    421:         */
                    422:        *sp++ = c;
                    423:        mark = tokbuf + buflen - 2;
                    424:        while ((c = fetch()) != EOF  &&  c != NEWLINE  &&  c != PERCENT) {
                    425:                if (sp == mark) {
                    426:                        posn = sp - tokbuf;
                    427:                        tokbuf = realloc(tokbuf, (buflen += 128));
                    428:                        sp = tokbuf + posn;
                    429:                        mark = sp + buflen;
                    430:                }
                    431:                *sp++ = c;
                    432:        }
                    433:        *sp = '\0';
                    434:        if (c == PERCENT)
                    435:                return (STRPLUS);
                    436:        unfetch(c);
                    437:        return (STR);
                    438: }
                    439: 
                    440: 
                    441: unfetch(c)
                    442: int c;
                    443: {
                    444:        ufetval = c;
                    445:        ufetflag = TRUE;
                    446: }
                    447: 
                    448: fetch()
                    449: {
                    450:        register int c;
                    451:        register int c2;
                    452: 
                    453:        if (ufetflag) {
                    454:                ufetflag = FALSE;
                    455:                return (ufetval);
                    456:        }
                    457: 
                    458:        for (;;)
                    459:                switch (c = getc(f)) {
                    460:                case '%':
                    461:                        return (PERCENT);
                    462:                case '\n':
                    463:                        return (NEWLINE);
                    464:                case '\\':
                    465:                        if ((c2 = getc(f)) == '%')
                    466:                                return ('%');
                    467:                        else if (c2 == '\n')
                    468:                                continue;
                    469:                        else {
                    470:                                ungetc(c2, f);
                    471:                                return ('\\');
                    472:                        }
                    473:                default:
                    474:                        return (c);
                    475:                }
                    476: }
                    477: 
                    478: 
                    479: skip_it()
                    480: {
                    481:        register int t;
                    482: 
                    483:        while ((t = gettoken()) != EOF  &&  t != NEWLINE)
                    484:                ;
                    485:        return (t);
                    486: }
                    487: 
                    488: do_it()
                    489: {
                    490:        register int c;
                    491:        register FILE *fp;
                    492: 
                    493:        if ((c = gettoken()) != STR  &&  c != STRPLUS) {
                    494:                ungettoken(c);
                    495:                return (skip_it());
                    496:        }
                    497:        
                    498:        Dprint("Tokken is %s\n", tokbuf);
                    499: 
                    500:        if ((fp = cronpipe(tokbuf, "w")) == NULL) {
                    501:                fprintf(stderr, "crond:\tCould not popen: %s\n\t\
                    502:                                errno = %d: %s.\n", tokbuf, errno, perror());
                    503:                return (skip_it());
                    504:        }
                    505: 
                    506:        if (c == STR) {
                    507:                fclose(fp);
                    508:                return (gettoken());
                    509:        }
                    510:        while ((c = fetch()) != NEWLINE  &&  c != EOF)
                    511:                if (c == PERCENT)
                    512:                        putc('\n', fp);
                    513:                else
                    514:                        putc(c, fp);
                    515:        putc('\n', fp);
                    516:        fclose(fp);
                    517:        return(c);
                    518: }
                    519: 
                    520: /*
                    521:  * We have to catch all signals.
                    522:  * Ignore signals INT, HUP, & PIPE.
                    523:  * Reset time on ALRM.
                    524:  * Remove lock file and take default action on the rest of them.
                    525:  */
                    526: sigsetup()
                    527: {
                    528:        register int    i;
                    529:        int             catchalarm();   /* Catch alarm signal */
                    530:        int             catchsignals(); /* Catch all signals */
                    531: 
                    532:        for (i = 1; i < NSIG; i++)
                    533:                signal(i, catchsignals);
                    534: 
                    535:        signal(SIGINT, SIG_IGN);
                    536:        signal(SIGHUP, SIG_IGN);
                    537:        signal(SIGPIPE, SIG_IGN);
                    538:        signal(SIGALRM, catchalarm);
                    539: }
                    540: 
                    541: /*
                    542:  * Remove lock file. Restore default action. Send the catched signal to itself.
                    543:  */
                    544: int catchsignals(sig)
                    545: int    sig;
                    546: {
                    547:        unlink(F_LOCK);         /* Remove lock FIFO. Do not care if unlink */
                    548:                                /* failed (case cron 3.2.0) */
                    549:        Dprint("Remove lock file %s\n", F_LOCK);
                    550:        signal(sig, SIG_DFL);   /* Reset to default */
                    551:        kill(getpid(), sig);    /* Send catched signal */
                    552:        wait(); 
                    553: }
                    554: 
                    555: /* 
                    556:  * Catch alarm.
                    557:  */
                    558: int catchalarm()
                    559: {
                    560:        signal(SIGALRM, catchalarm);
                    561:        time(&clock);
                    562:        tm = localtime(&clock);
                    563:        alarm(61 - tm->tm_sec);
                    564: }
                    565: 

unix.superglobalmegacorp.com

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