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