Annotation of 43BSDReno/usr.bin/calendar/calendar.c, revision 1.1.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.