Annotation of 43BSDTahoe/ucb/vacation.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1983, 1987 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 the above copyright notice and this paragraph are
        !             7:  * duplicated in all such forms and that any documentation,
        !             8:  * advertising materials, and other materials related to such
        !             9:  * distribution and use acknowledge that the software was developed
        !            10:  * by the University of California, Berkeley.  The name of the
        !            11:  * University may not be used to endorse or promote products derived
        !            12:  * from this software without specific prior written permission.
        !            13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            15:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            16:  */
        !            17: 
        !            18: #ifndef lint
        !            19: char copyright[] =
        !            20: "@(#) Copyright (c) 1983, 1987 Regents of the University of California.\n\
        !            21:  All rights reserved.\n";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #ifndef lint
        !            25: static char sccsid[] = "@(#)vacation.c 5.10 (Berkeley) 6/29/88";
        !            26: #endif /* not lint */
        !            27: 
        !            28: /*
        !            29: **  Vacation
        !            30: **  Copyright (c) 1983  Eric P. Allman
        !            31: **  Berkeley, California
        !            32: */
        !            33: 
        !            34: #include <sys/param.h>
        !            35: #include <sys/file.h>
        !            36: #include <pwd.h>
        !            37: #include <stdio.h>
        !            38: #include <ctype.h>
        !            39: #include <syslog.h>
        !            40: 
        !            41: /*
        !            42: **  VACATION -- return a message to the sender when on vacation.
        !            43: **
        !            44: **     This program could be invoked as a message receiver when someone is
        !            45: **     on vacation.  It returns a message specified by the user to whoever
        !            46: **     sent the mail, taking care not to return a message too often to
        !            47: **     prevent "I am on vacation" loops.
        !            48: */
        !            49: 
        !            50: #define        MAXLINE 500                     /* max line from mail header */
        !            51: #define        PERIOD  (60L*60L*24L*7L)        /* week between notifications */
        !            52: #define        VMSG    ".vacation.msg"         /* vacation message */
        !            53: #define        VACAT   ".vacation"             /* dbm's database prefix */
        !            54: #define        VDIR    ".vacation.dir"         /* dbm's DB prefix, part 1 */
        !            55: #define        VPAG    ".vacation.pag"         /* dbm's DB prefix, part 2 */
        !            56: 
        !            57: typedef struct alias {
        !            58:        struct alias *next;
        !            59:        char    *name;
        !            60: } ALIAS;
        !            61: ALIAS  *names;
        !            62: 
        !            63: static char from[MAXLINE];             /* sender's address */
        !            64: 
        !            65: main(argc, argv)
        !            66:        int argc;
        !            67:        char **argv;
        !            68: {
        !            69:        extern int optind;
        !            70:        extern char *optarg;
        !            71:        struct passwd *pw;
        !            72:        ALIAS *cur;
        !            73:        int ch, iflag;
        !            74:        char *malloc();
        !            75:        uid_t getuid();
        !            76: 
        !            77:        iflag = 0;
        !            78:        while ((ch = getopt(argc, argv, "a:Ii")) != EOF)
        !            79:                switch((char)ch) {
        !            80:                case 'a':                       /* alias */
        !            81:                        if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))))
        !            82:                                break;
        !            83:                        cur->name = optarg;
        !            84:                        cur->next = names;
        !            85:                        names = cur;
        !            86:                        break;
        !            87:                case 'i':                       /* init the database */
        !            88:                case 'I':                       /* backward compatible */
        !            89:                        iflag = 1;
        !            90:                        break;
        !            91:                case '?':
        !            92:                default:
        !            93:                        goto usage;
        !            94:                }
        !            95:        argc -= optind;
        !            96:        argv += optind;
        !            97: 
        !            98:        if (argc != 1) {
        !            99:                if (!iflag) {
        !           100: usage:                 syslog(LOG_ERR, "uid %u: usage: vacation [-i] [-a alias] login\n", getuid());
        !           101:                        exit(1);
        !           102:                }
        !           103:                if (!(pw = getpwuid(getuid()))) {
        !           104:                        syslog(LOG_ERR, "vacation: no such user uid %u.\n", getuid());
        !           105:                        exit(1);
        !           106:                }
        !           107:        }
        !           108:        else if (!(pw = getpwnam(*argv))) {
        !           109:                syslog(LOG_ERR, "vacation: no such user %s.\n", *argv);
        !           110:                exit(1);
        !           111:        }
        !           112:        if (chdir(pw->pw_dir)) {
        !           113:                syslog(LOG_ERR, "vacation: no such directory %s.\n", pw->pw_dir);
        !           114:                exit(1);
        !           115:        }
        !           116: 
        !           117:        if (iflag) {
        !           118:                initialize();
        !           119:                exit(0);
        !           120:        }
        !           121: 
        !           122:        if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))))
        !           123:                exit(1);
        !           124:        cur->name = pw->pw_name;
        !           125:        cur->next = names;
        !           126:        names = cur;
        !           127: 
        !           128:        readheaders();
        !           129: 
        !           130:        if (access(VDIR, F_OK))
        !           131:                initialize();
        !           132:        else
        !           133:                dbminit(VACAT);
        !           134: 
        !           135:        if (!recent()) {
        !           136:                setreply();
        !           137:                sendmessage(pw->pw_name);
        !           138:        }
        !           139:        exit(0);
        !           140: }
        !           141: 
        !           142: /*
        !           143:  * readheaders --
        !           144:  *     read mail headers
        !           145:  */
        !           146: static
        !           147: readheaders()
        !           148: {
        !           149:        register ALIAS *cur;
        !           150:        register char *p;
        !           151:        int tome, cont;
        !           152:        char buf[MAXLINE], *strcpy(), *index();
        !           153: 
        !           154:        cont = tome = 0;
        !           155:        while (fgets(buf, sizeof(buf), stdin) && *buf != '\n')
        !           156:                switch(*buf) {
        !           157:                case 'F':               /* "From " */
        !           158:                        cont = 0;
        !           159:                        if (!strncmp(buf, "From ", 5)) {
        !           160:                                for (p = buf + 5; *p && *p != ' '; ++p);
        !           161:                                *p = '\0';
        !           162:                                (void)strcpy(from, buf + 5);
        !           163:                                if (junkmail())
        !           164:                                        exit(0);
        !           165:                        }
        !           166:                        break;
        !           167:                case 'P':               /* "Precedence:" */
        !           168:                        cont = 0;
        !           169:                        if (strncasecmp(buf, "Precedence", 10) || buf[10] != ':' && buf[10] != ' ' && buf[10] != '\t')
        !           170:                                break;
        !           171:                        if (!(p = index(buf, ':')))
        !           172:                                break;
        !           173:                        while (*++p && isspace(*p));
        !           174:                        if (!*p)
        !           175:                                break;
        !           176:                        if (!strncasecmp(p, "junk", 4) || !strncasecmp(p, "bulk", 4))
        !           177:                                exit(0);
        !           178:                        break;
        !           179:                case 'C':               /* "Cc:" */
        !           180:                        if (strncmp(buf, "Cc:", 3))
        !           181:                                break;
        !           182:                        cont = 1;
        !           183:                        goto findme;
        !           184:                case 'T':               /* "To:" */
        !           185:                        if (strncmp(buf, "To:", 3))
        !           186:                                break;
        !           187:                        cont = 1;
        !           188:                        goto findme;
        !           189:                default:
        !           190:                        if (!isspace(*buf) || !cont || tome) {
        !           191:                                cont = 0;
        !           192:                                break;
        !           193:                        }
        !           194: findme:                        for (cur = names; !tome && cur; cur = cur->next)
        !           195:                                tome += nsearch(cur->name, buf);
        !           196:                }
        !           197:        if (!tome)
        !           198:                exit(0);
        !           199:        if (!*from) {
        !           200:                syslog(LOG_ERR, "vacation: no initial \"From\" line.\n");
        !           201:                exit(1);
        !           202:        }
        !           203: }
        !           204: 
        !           205: /*
        !           206:  * nsearch --
        !           207:  *     do a nice, slow, search of a string for a substring.
        !           208:  */
        !           209: static
        !           210: nsearch(name, str)
        !           211:        register char *name, *str;
        !           212: {
        !           213:        register int len;
        !           214: 
        !           215:        for (len = strlen(name); *str; ++str)
        !           216:                if (*str == *name && !strncasecmp(name, str, len))
        !           217:                        return(1);
        !           218:        return(0);
        !           219: }
        !           220: 
        !           221: /*
        !           222:  * junkmail --
        !           223:  *     read the header and return if automagic/junk/bulk mail
        !           224:  */
        !           225: static
        !           226: junkmail()
        !           227: {
        !           228:        static struct ignore {
        !           229:                char    *name;
        !           230:                int     len;
        !           231:        } ignore[] = {
        !           232:                "-REQUEST", 8,  "Postmaster", 10,
        !           233:                "uucp", 4,      "MAILER-DAEMON", 13,
        !           234:                "MAILER", 6,    NULL, NULL,
        !           235:        };
        !           236:        register struct ignore *cur;
        !           237:        register int len;
        !           238:        register char *p;
        !           239:        char *index(), *rindex();
        !           240: 
        !           241:        /*
        !           242:         * This is mildly amusing, and I'm not positive it's right; trying
        !           243:         * to find the "real" name of the sender, assuming that addresses
        !           244:         * will be some variant of:
        !           245:         *
        !           246:         * From site!site!SENDER%site.domain%[email protected]
        !           247:         */
        !           248:        if (!(p = index(from, '%')))
        !           249:                if (!(p = index(from, '@'))) {
        !           250:                        if (p = rindex(from, '!'))
        !           251:                                ++p;
        !           252:                        else
        !           253:                                p = from;
        !           254:                        for (; *p; ++p);
        !           255:                }
        !           256:        len = p - from;
        !           257:        for (cur = ignore; cur->name; ++cur)
        !           258:                if (len >= cur->len && !strncasecmp(cur->name, p - cur->len, cur->len))
        !           259:                        return(1);
        !           260:        return(0);
        !           261: }
        !           262: 
        !           263: typedef struct {
        !           264:        char    *dptr;
        !           265:        int     dsize;
        !           266: } DATUM;
        !           267: 
        !           268: typedef struct {
        !           269:        time_t  sentdate;
        !           270: } DBREC;
        !           271: 
        !           272: /*
        !           273:  * recent --
        !           274:  *     find out if user has gotten a vacation message recently.
        !           275:  */
        !           276: static
        !           277: recent()
        !           278: {
        !           279:        DATUM k, d, fetch();
        !           280:        time_t now, then, time();
        !           281: 
        !           282:        k.dptr = from;
        !           283:        k.dsize = strlen(from) + 1;
        !           284:        d = fetch(k);
        !           285:        if (d.dptr) {
        !           286:                /* be careful on machines with alignment restrictions */
        !           287:                bcopy((char *)&((DBREC *)d.dptr)->sentdate, (char *)&then, sizeof(then));
        !           288:                (void)time(&now);
        !           289:                if (!then || then + PERIOD > now)
        !           290:                        return(1);
        !           291:        }
        !           292:        return(0);
        !           293: }
        !           294: 
        !           295: /*
        !           296:  * setreply --
        !           297:  *     store that this user knows about the vacation.
        !           298:  */
        !           299: static
        !           300: setreply()
        !           301: {
        !           302:        DBREC xrec;
        !           303:        DATUM k, d;
        !           304:        time_t time();
        !           305: 
        !           306:        k.dptr = from;
        !           307:        k.dsize = strlen(from) + 1;
        !           308:        (void)time(&xrec.sentdate);
        !           309:        d.dptr = (char *)&xrec;
        !           310:        d.dsize = sizeof(xrec);
        !           311:        store(k, d);
        !           312: }
        !           313: 
        !           314: /*
        !           315:  * sendmessage --
        !           316:  *     exec sendmail to send the vacation file to sender
        !           317:  */
        !           318: static
        !           319: sendmessage(myname)
        !           320:        char *myname;
        !           321: {
        !           322:        if (!freopen(VMSG, "r", stdin)) {
        !           323:                syslog(LOG_ERR, "vacation: no ~%s/%s file.\n", myname, VMSG);
        !           324:                exit(1);
        !           325:        }
        !           326:        execl("/usr/lib/sendmail", "sendmail", "-f", myname, from, NULL);
        !           327:        syslog(LOG_ERR, "vacation: can't exec /usr/lib/sendmail.\n");
        !           328:        exit(1);
        !           329: }
        !           330: 
        !           331: /*
        !           332:  * initialize --
        !           333:  *     initialize the dbm database
        !           334:  */
        !           335: static
        !           336: initialize()
        !           337: {
        !           338:        extern int errno;
        !           339:        extern char *sys_errlist[];
        !           340:        int fd;
        !           341: 
        !           342:        if ((fd = open(VDIR, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
        !           343:                syslog(LOG_ERR, "vacation: %s: %s\n", VDIR, sys_errlist[errno]);
        !           344:                exit(1);
        !           345:        }
        !           346:        (void)close(fd);
        !           347:        if ((fd = open(VPAG, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
        !           348:                syslog(LOG_ERR, "vacation: %s: %s\n", VPAG, sys_errlist[errno]);
        !           349:                exit(1);
        !           350:        }
        !           351:        (void)close(fd);
        !           352:        dbminit(VACAT);
        !           353: }

unix.superglobalmegacorp.com

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