Annotation of 43BSDReno/usr.bin/calendar/calendar.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1989 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted
        !             6:  * provided that: (1) source distributions retain this entire copyright
        !             7:  * notice and comment, and (2) distributions including binaries display
        !             8:  * the following acknowledgement:  ``This product includes software
        !             9:  * developed by the University of California, Berkeley and its contributors''
        !            10:  * in the documentation or other materials provided with the distribution
        !            11:  * and in all advertising materials mentioning features or use of this
        !            12:  * software. Neither the name of the University nor the names of its
        !            13:  * contributors may be used to endorse or promote products derived
        !            14:  * from this software without specific prior written permission.
        !            15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            18:  */
        !            19: 
        !            20: #ifndef lint
        !            21: char copyright[] =
        !            22: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
        !            23:  All rights reserved.\n";
        !            24: #endif /* not lint */
        !            25: 
        !            26: #ifndef lint
        !            27: static char sccsid[] = "@(#)calendar.c 4.10 (Berkeley) 6/1/90";
        !            28: #endif /* not lint */
        !            29: 
        !            30: #include <sys/param.h>
        !            31: #include <sys/time.h>
        !            32: #include <sys/stat.h>
        !            33: #include <sys/file.h>
        !            34: #include <sys/uio.h>
        !            35: #include <pwd.h>
        !            36: #include <errno.h>
        !            37: #include <tzfile.h>
        !            38: #include <stdio.h>
        !            39: #include <ctype.h>
        !            40: #include <unistd.h>
        !            41: #include <string.h>
        !            42: #include "pathnames.h"
        !            43: 
        !            44: extern int errno;
        !            45: struct passwd *pw;
        !            46: int doall;
        !            47: 
        !            48: main(argc, argv)
        !            49:        int argc;
        !            50:        char **argv;
        !            51: {
        !            52:        extern int optind;
        !            53:        int ch;
        !            54: 
        !            55:        while ((ch = getopt(argc, argv, "-a")) != EOF)
        !            56:                switch(ch) {
        !            57:                case '-':               /* backward contemptible */
        !            58:                case 'a':
        !            59:                        if (getuid()) {
        !            60:                                (void)fprintf(stderr,
        !            61:                                    "calendar: %s\n", strerror(EPERM));
        !            62:                                exit(1);
        !            63:                        }
        !            64:                        doall = 1;
        !            65:                        break;
        !            66:                case '?':
        !            67:                default:
        !            68:                        usage();
        !            69:                }
        !            70:        argc -= optind;
        !            71:        argv += optind;
        !            72: 
        !            73:        if (argc)
        !            74:                usage();
        !            75: 
        !            76:        settime();
        !            77:        if (doall)
        !            78:                while (pw = getpwent()) {
        !            79:                        (void)setegid(pw->pw_gid);
        !            80:                        (void)seteuid(pw->pw_uid);
        !            81:                        if (!chdir(pw->pw_dir))
        !            82:                                cal();
        !            83:                        (void)seteuid(0);
        !            84:                }
        !            85:        else
        !            86:                cal();
        !            87:        exit(0);
        !            88: }
        !            89: 
        !            90: cal()
        !            91: {
        !            92:        register int printing;
        !            93:        register char *p;
        !            94:        FILE *fp, *opencal();
        !            95:        int ch;
        !            96:        char buf[2048 + 1];
        !            97: 
        !            98:        if (!(fp = opencal()))
        !            99:                return;
        !           100:        for (printing = 0; fgets(buf, sizeof(buf), stdin);) {
        !           101:                if (p = index(buf, '\n'))
        !           102:                        *p = '\0';
        !           103:                else
        !           104:                        while ((ch = getchar()) != '\n' && ch != EOF);
        !           105:                if (buf[0] == '\0')
        !           106:                        continue;
        !           107:                if (buf[0] != '\t')
        !           108:                        printing = isnow(buf) ? 1 : 0;
        !           109:                if (printing)
        !           110:                        (void)fprintf(fp, "%s\n", buf);
        !           111:        }
        !           112:        closecal(fp);
        !           113: }
        !           114: 
        !           115: struct iovec header[] = {
        !           116:        "From: ", 6,
        !           117:        NULL, 0,
        !           118:        " (Reminder Service)\nTo: ", 24,
        !           119:        NULL, 0,
        !           120:        "\nSubject: ", 10,
        !           121:        NULL, 0,
        !           122:        "'s Calendar\nPrecedence: bulk\n\n",  30,
        !           123: };
        !           124: 
        !           125: /* 1-based month, 0-based days, cumulative */
        !           126: int daytab[][14] = {
        !           127:        0, 0, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364,
        !           128:        0, 0, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365,
        !           129: };
        !           130: struct tm *tp;
        !           131: int *cumdays, offset, yrdays;
        !           132: char dayname[10];
        !           133: 
        !           134: settime()
        !           135: {
        !           136:        time_t now, time();
        !           137: 
        !           138:        (void)time(&now);
        !           139:        tp = localtime(&now);
        !           140:        if (isleap(tp->tm_year + 1900)) {
        !           141:                yrdays = DAYSPERLYEAR;
        !           142:                cumdays = daytab[1];
        !           143:        } else {
        !           144:                yrdays = DAYSPERNYEAR;
        !           145:                cumdays = daytab[0];
        !           146:        }
        !           147:        /* Friday displays Monday's events */
        !           148:        offset = tp->tm_wday == 6 ? 3 : 1;
        !           149:        header[5].iov_base = dayname;
        !           150:        header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", tp);
        !           151: }
        !           152: 
        !           153: /*
        !           154:  * Possible date formats include any combination of:
        !           155:  *     3-charmonth                     (January, Jan, Jan)
        !           156:  *     3-charweekday                   (Friday, Monday, mon.)
        !           157:  *     numeric month or day            (1, 2, 04)
        !           158:  *
        !           159:  * Any character may separate them, or they may not be separated.  Any line,
        !           160:  * following a line that is matched, that starts with "whitespace", is shown
        !           161:  * along with the matched line.
        !           162:  */
        !           163: isnow(endp)
        !           164:        char *endp;
        !           165: {
        !           166:        int day, flags, month, v1, v2;
        !           167: 
        !           168: #define        F_ISMONTH       0x01
        !           169: #define        F_ISDAY         0x02
        !           170:        flags = 0;
        !           171:        /* didn't recognize anything, skip it */
        !           172:        if (!(v1 = getfield(endp, &endp, &flags)))
        !           173:                return(0);
        !           174:        if (flags&F_ISDAY || v1 > 12) {
        !           175:                /* found a day */
        !           176:                day = v1;
        !           177:                /* if no recognizable month, assume just a day alone */
        !           178:                if (!(month = getfield(endp, &endp, &flags)))
        !           179:                        month = tp->tm_mon;
        !           180:        } else if (flags&F_ISMONTH) {
        !           181:                month = v1;
        !           182:                /* if no recognizable day, assume the first */
        !           183:                if (!(day = getfield(endp, &endp, &flags)))
        !           184:                        day = 1;
        !           185:        } else {
        !           186:                v2 = getfield(endp, &endp, &flags);
        !           187:                if (flags&F_ISMONTH) {
        !           188:                        day = v1;
        !           189:                        month = v2;
        !           190:                } else {
        !           191:                        /* F_ISDAY set, v2 > 12, or no way to tell */
        !           192:                        month = v1;
        !           193:                        /* if no recognizable day, assume the first */
        !           194:                        day = v2 ? v2 : 1;
        !           195:                }
        !           196:        }
        !           197:        day = cumdays[month] + day;
        !           198: 
        !           199:        /* if today or today + offset days */
        !           200:        if (day >= tp->tm_yday && day <= tp->tm_yday + offset)
        !           201:                return(1);
        !           202:        /* if number of days left in this year + days to event in next year */
        !           203:        if (yrdays - tp->tm_yday + day <= offset)
        !           204:                return(1);
        !           205:        return(0);
        !           206: }
        !           207: 
        !           208: getfield(p, endp, flags)
        !           209:        char *p, **endp;
        !           210:        int *flags;
        !           211: {
        !           212:        int val;
        !           213:        char *start, savech;
        !           214: 
        !           215:        if (*p == '*') {                        /* `*' is current month */
        !           216:                *flags |= F_ISMONTH;
        !           217:                return(tp->tm_mon);
        !           218:        }
        !           219:        if (isdigit(*p)) {
        !           220:                val = strtol(p, &p, 10);        /* if 0, it's failure */
        !           221:                for (; !isdigit(*p) && !isalpha(*p); ++p);
        !           222:                *endp = p;
        !           223:                return(val);
        !           224:        }
        !           225:        for (start = p; isalpha(*++p););
        !           226:        savech = *p;
        !           227:        *p = '\0';
        !           228:        if (val = getmonth(start))
        !           229:                *flags |= F_ISMONTH;
        !           230:        else if (val = getday(start))
        !           231:                *flags |= F_ISDAY;
        !           232:        else
        !           233:                return(0);
        !           234:        for (*p = savech; !isdigit(*p) && !isalpha(*p); ++p);
        !           235:        *endp = p;
        !           236:        return(val);
        !           237: }
        !           238: 
        !           239: char path[MAXPATHLEN + 1];
        !           240: 
        !           241: FILE *
        !           242: opencal()
        !           243: {
        !           244:        int fd, pdes[2];
        !           245:        char *mktemp();
        !           246: 
        !           247:        /* open up calendar file as stdin */
        !           248:        if (!freopen("calendar", "r", stdin)) {
        !           249:                if (doall)
        !           250:                        return((FILE *)NULL);
        !           251:                (void)fprintf(stderr, "calendar: no calendar file.\n");
        !           252:                exit(1);
        !           253:        }
        !           254:        if (pipe(pdes) < 0) 
        !           255:                return(NULL);
        !           256:        switch (vfork()) {
        !           257:        case -1:                        /* error */
        !           258:                (void)close(pdes[0]);
        !           259:                (void)close(pdes[1]);
        !           260:                return(NULL);
        !           261:        case 0:
        !           262:                /* child -- stdin already setup, set stdout to pipe input */
        !           263:                if (pdes[1] != STDOUT_FILENO) {
        !           264:                        (void)dup2(pdes[1], STDOUT_FILENO);
        !           265:                        (void)close(pdes[1]);
        !           266:                }
        !           267:                (void)close(pdes[0]);
        !           268:                execl(_PATH_CPP, "cpp", "-I.", _PATH_INCLUDE, NULL);
        !           269:                _exit(1);
        !           270:        }
        !           271:        /* parent -- set stdin to pipe output */
        !           272:        (void)dup2(pdes[0], STDIN_FILENO);
        !           273:        (void)close(pdes[0]);
        !           274:        (void)close(pdes[1]);
        !           275: 
        !           276:        /* not reading all calendar files, just set output to stdout */
        !           277:        if (!doall)
        !           278:                return(stdout);
        !           279: 
        !           280:        /* set output to a temporary file, so if no output don't send mail */
        !           281:        (void)sprintf(path, "%s/_calXXXXXX", _PATH_TMP);
        !           282:        if ((fd = mkstemp(path)) < 0)
        !           283:                return(NULL);
        !           284:        return(fdopen(fd, "w+"));
        !           285: }
        !           286: 
        !           287: closecal(fp)
        !           288:        FILE *fp;
        !           289: {
        !           290:        struct stat sbuf;
        !           291:        int nread, pdes[2], status;
        !           292:        char buf[1024], *mktemp();
        !           293: 
        !           294:        if (!doall)
        !           295:                return;
        !           296: 
        !           297:        (void)rewind(fp);
        !           298:        if (fstat(fileno(fp), &sbuf) || !sbuf.st_size)
        !           299:                goto done;
        !           300:        if (pipe(pdes) < 0) 
        !           301:                goto done;
        !           302:        switch (vfork()) {
        !           303:        case -1:                        /* error */
        !           304:                (void)close(pdes[0]);
        !           305:                (void)close(pdes[1]);
        !           306:                goto done;
        !           307:        case 0:         
        !           308:                /* child -- set stdin to pipe output */
        !           309:                if (pdes[0] != STDIN_FILENO) {
        !           310:                        (void)dup2(pdes[0], STDIN_FILENO);
        !           311:                        (void)close(pdes[0]);
        !           312:                }
        !           313:                (void)close(pdes[1]);
        !           314:                execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F",
        !           315:                    "\"Reminder Service\"", "-f", "root", NULL);
        !           316:                (void)fprintf(stderr, "calendar: %s: %s.\n", 
        !           317:                    _PATH_SENDMAIL, strerror(errno));
        !           318:                _exit(1);
        !           319:        }
        !           320:        /* parent -- write to pipe input */
        !           321:        (void)close(pdes[0]);
        !           322: 
        !           323:        header[1].iov_base = header[3].iov_base = pw->pw_name;
        !           324:        header[1].iov_len = header[3].iov_len = strlen(pw->pw_name);
        !           325:        writev(pdes[1], header, 7);
        !           326:        while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0)
        !           327:                (void)write(pdes[1], buf, nread);
        !           328:        (void)close(pdes[1]);
        !           329: done:  (void)fclose(fp);
        !           330:        (void)unlink(path);
        !           331:        while (wait(&status) >= 0);
        !           332: }
        !           333: 
        !           334: static char *months[] = {
        !           335:        "jan", "feb", "mar", "apr", "may", "jun",
        !           336:        "jul", "aug", "sep", "oct", "nov", "dec", NULL,
        !           337: };
        !           338: getmonth(s)
        !           339:        register char *s;
        !           340: {
        !           341:        register char **p;
        !           342: 
        !           343:        for (p = months; *p; ++p)
        !           344:                if (!strncasecmp(s, *p, 3))
        !           345:                        return((p - months) + 1);
        !           346:        return(0);
        !           347: }
        !           348: 
        !           349: static char *days[] = {
        !           350:        "sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL,
        !           351: };
        !           352: getday(s)
        !           353:        register char *s;
        !           354: {
        !           355:        register char **p;
        !           356: 
        !           357:        for (p = days; *p; ++p)
        !           358:                if (!strncasecmp(s, *p, 3))
        !           359:                        return((p - days) + 1);
        !           360:        return(0);
        !           361: }
        !           362: 
        !           363: usage()
        !           364: {
        !           365:        (void)fprintf(stderr, "usage: calendar [-a]\n");
        !           366:        exit(1);
        !           367: }

unix.superglobalmegacorp.com

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