Annotation of 43BSDTahoe/ucb/vacation.c, revision 1.1.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.