[BACK]Return to calendar.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / calendar

Annotation of src/usr.bin/calendar/calendar.c, Revision 1.1

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