Annotation of 43BSD/ucb/vacation.c, revision 1.1.1.1

1.1       root        1: /*
                      2: **  Vacation
                      3: **  Copyright (c) 1983  Eric P. Allman
                      4: **  Berkeley, California
                      5: **
                      6: **  Copyright (c) 1983 Regents of the University of California.
                      7: **  All rights reserved.  The Berkeley software License Agreement
                      8: **  specifies the terms and conditions for redistribution.
                      9: */
                     10: 
                     11: #ifndef lint
                     12: static char    SccsId[] = "@(#)vacation.c      5.3 (Berkeley) 7/1/85";
                     13: #endif not lint
                     14: 
                     15: # include <sys/types.h>
                     16: # include <pwd.h>
                     17: # include <stdio.h>
                     18: # include <sysexits.h>
                     19: # include <ctype.h>
                     20: 
                     21: /*
                     22: **  VACATION -- return a message to the sender when on vacation.
                     23: **
                     24: **     This program could be invoked as a message receiver
                     25: **     when someone is on vacation.  It returns a message
                     26: **     specified by the user to whoever sent the mail, taking
                     27: **     care not to return a message too often to prevent
                     28: **     "I am on vacation" loops.
                     29: **
                     30: **     Positional Parameters:
                     31: **             the user to collect the vacation message from.
                     32: **
                     33: **     Flag Parameters:
                     34: **             -I      initialize the database.
                     35: **             -d      turn on debugging.
                     36: **
                     37: **     Side Effects:
                     38: **             A message is sent back to the sender.
                     39: **
                     40: **     Author:
                     41: **             Eric Allman
                     42: **             UCB/INGRES
                     43: */
                     44: 
                     45: typedef int    bool;
                     46: 
                     47: # define TRUE          1
                     48: # define FALSE         0
                     49: 
                     50: # define MAXLINE       256     /* max size of a line */
                     51: # define MAXNAME       128     /* max size of one name */
                     52: 
                     53: # define ONEWEEK       (60L*60L*24L*7L)
                     54: 
                     55: time_t Timeout = ONEWEEK;      /* timeout between notices per user */
                     56: 
                     57: struct dbrec
                     58: {
                     59:        long    sentdate;
                     60: };
                     61: 
                     62: typedef struct
                     63: {
                     64:        char    *dptr;
                     65:        int     dsize;
                     66: } DATUM;
                     67: 
                     68: extern DATUM fetch();
                     69: 
                     70: 
                     71: 
                     72: bool   Debug = FALSE;
                     73: 
                     74: main(argc, argv)
                     75:        char **argv;
                     76: {
                     77:        char *from;
                     78:        register char *p;
                     79:        struct passwd *pw;
                     80:        char *homedir;
                     81:        char *myname;
                     82:        char buf[MAXLINE];
                     83:        extern struct passwd *getpwnam();
                     84:        extern char *newstr();
                     85:        extern char *getfrom();
                     86:        extern bool knows();
                     87:        extern bool junkmail();
                     88:        extern time_t convtime();
                     89: 
                     90:        /* process arguments */
                     91:        while (--argc > 0 && (p = *++argv) != NULL && *p == '-')
                     92:        {
                     93:                switch (*++p)
                     94:                {
                     95:                  case 'I':     /* initialize */
                     96:                        initialize();
                     97:                        exit(EX_OK);
                     98: 
                     99:                  case 'd':     /* debug */
                    100:                        Debug = TRUE;
                    101:                        break;
                    102: 
                    103:                  default:
                    104:                        usrerr("Unknown flag -%s", p);
                    105:                        exit(EX_USAGE);
                    106:                }
                    107:        }
                    108: 
                    109:        /* verify recipient argument */
                    110:        if (argc != 1)
                    111:        {
                    112:                usrerr("Usage: vacation username (or) vacation -I");
                    113:                exit(EX_USAGE);
                    114:        }
                    115: 
                    116:        myname = p;
                    117: 
                    118:        /* find user's home directory */
                    119:        pw = getpwnam(myname);
                    120:        if (pw == NULL)
                    121:        {
                    122:                usrerr("Unknown user %s", myname);
                    123:                exit(EX_NOUSER);
                    124:        }
                    125:        homedir = newstr(pw->pw_dir);
                    126:        (void) strcpy(buf, homedir);
                    127:        (void) strcat(buf, "/.vacation");
                    128:        dbminit(buf);
                    129: 
                    130:        /* read message from standard input (just from line) */
                    131:        from = getfrom();
                    132: 
                    133:        /* check if junk mail or this person is already informed */
                    134:        if (!junkmail(from) && !knows(from))
                    135:        {
                    136:                /* mark this person as knowing */
                    137:                setknows(from);
                    138: 
                    139:                /* send the message back */
                    140:                (void) strcpy(buf, homedir);
                    141:                (void) strcat(buf, "/.vacation.msg");
                    142:                if (Debug)
                    143:                        printf("Sending %s to %s\n", buf, from);
                    144:                else
                    145:                {
                    146:                        sendmessage(buf, from, myname);
                    147:                        /*NOTREACHED*/
                    148:                }
                    149:        }
                    150:        exit (EX_OK);
                    151: }
                    152: /*
                    153: **  GETFROM -- read message from standard input and return sender
                    154: **
                    155: **     Parameters:
                    156: **             none.
                    157: **
                    158: **     Returns:
                    159: **             pointer to the sender address.
                    160: **
                    161: **     Side Effects:
                    162: **             Reads first line from standard input.
                    163: */
                    164: 
                    165: char *
                    166: getfrom()
                    167: {
                    168:        static char line[MAXLINE];
                    169:        register char *p;
                    170:        extern char *index();
                    171: 
                    172:        /* read the from line */
                    173:        if (fgets(line, sizeof line, stdin) == NULL ||
                    174:            strncmp(line, "From ", 5) != NULL)
                    175:        {
                    176:                usrerr("No initial From line");
                    177:                exit(EX_USAGE);
                    178:        }
                    179: 
                    180:        /* find the end of the sender address and terminate it */
                    181:        p = index(&line[5], ' ');
                    182:        if (p == NULL)
                    183:        {
                    184:                usrerr("Funny From line '%s'", line);
                    185:                exit(EX_USAGE);
                    186:        }
                    187:        *p = '\0';
                    188: 
                    189:        /* return the sender address */
                    190:        return (&line[5]);
                    191: }
                    192: /*
                    193: **  JUNKMAIL -- read the header and tell us if this is junk/bulk mail.
                    194: **
                    195: **     Parameters:
                    196: **             from -- the Return-Path of the sender.  We assume that
                    197: **                     anything from "*-REQUEST@*" is bulk mail.
                    198: **
                    199: **     Returns:
                    200: **             TRUE -- if this is junk or bulk mail (that is, if the
                    201: **                     sender shouldn't receive a response).
                    202: **             FALSE -- if the sender deserves a response.
                    203: **
                    204: **     Side Effects:
                    205: **             May read the header from standard input.  When this
                    206: **             returns the position on stdin is undefined.
                    207: */
                    208: 
                    209: bool
                    210: junkmail(from)
                    211:        char *from;
                    212: {
                    213:        register char *p;
                    214:        char buf[MAXLINE+1];
                    215:        extern char *index();
                    216:        extern char *rindex();
                    217:        extern bool sameword();
                    218: 
                    219:        /* test for inhuman sender */
                    220:        p = rindex(from, '@');
                    221:        if (p != NULL)
                    222:        {
                    223:                *p = '\0';
                    224:                if (sameword(&p[-8],  "-REQUEST") ||
                    225:                    sameword(&p[-10], "Postmaster") ||
                    226:                    sameword(&p[-13], "MAILER-DAEMON"))
                    227:                {
                    228:                        *p = '@';
                    229:                        return (TRUE);
                    230:                }
                    231:                *p = '@';
                    232:        }
                    233: 
                    234:        /* read the header looking for a "Precedence:" line */
                    235:        while (fgets(buf, MAXLINE, stdin) != NULL && buf[0] != '\n')
                    236:        {
                    237:                /* should ignore case, but this is reasonably safe */
                    238:                if (strncmp(buf, "Precedence", 10) != 0 ||
                    239:                    !(buf[10] == ':' || buf[10] == ' ' || buf[10] == '\t'))
                    240:                {
                    241:                        continue;
                    242:                }
                    243: 
                    244:                /* find the value of this field */
                    245:                p = index(buf, ':');
                    246:                if (p == NULL)
                    247:                        continue;
                    248:                while (*++p != '\0' && isspace(*p))
                    249:                        continue;
                    250:                if (*p == '\0')
                    251:                        continue;
                    252: 
                    253:                /* see if it is "junk" or "bulk" */
                    254:                p[4] = '\0';
                    255:                if (sameword(p, "junk") || sameword(p, "bulk"))
                    256:                        return (TRUE);
                    257:        }
                    258:        return (FALSE);
                    259: }
                    260: /*
                    261: **  KNOWS -- predicate telling if user has already been informed.
                    262: **
                    263: **     Parameters:
                    264: **             user -- the user who sent this message.
                    265: **
                    266: **     Returns:
                    267: **             TRUE if 'user' has already been informed that the
                    268: **                     recipient is on vacation.
                    269: **             FALSE otherwise.
                    270: **
                    271: **     Side Effects:
                    272: **             none.
                    273: */
                    274: 
                    275: bool
                    276: knows(user)
                    277:        char *user;
                    278: {
                    279:        DATUM k, d;
                    280:        long now;
                    281:        auto long then;
                    282: 
                    283:        time(&now);
                    284:        k.dptr = user;
                    285:        k.dsize = strlen(user) + 1;
                    286:        d = fetch(k);
                    287:        if (d.dptr == NULL)
                    288:                return (FALSE);
                    289:        
                    290:        /* be careful on 68k's and others with alignment restrictions */
                    291:        bcopy((char *) &((struct dbrec *) d.dptr)->sentdate, (char *) &then, sizeof then);
                    292:        if (then + Timeout < now)
                    293:                return (FALSE);
                    294:        return (TRUE);
                    295: }
                    296: /*
                    297: **  SETKNOWS -- set that this user knows about the vacation.
                    298: **
                    299: **     Parameters:
                    300: **             user -- the user who should be marked.
                    301: **
                    302: **     Returns:
                    303: **             none.
                    304: **
                    305: **     Side Effects:
                    306: **             The dbm file is updated as appropriate.
                    307: */
                    308: 
                    309: setknows(user)
                    310:        char *user;
                    311: {
                    312:        DATUM k, d;
                    313:        struct dbrec xrec;
                    314: 
                    315:        k.dptr = user;
                    316:        k.dsize = strlen(user) + 1;
                    317:        time(&xrec.sentdate);
                    318:        d.dptr = (char *) &xrec;
                    319:        d.dsize = sizeof xrec;
                    320:        store(k, d);
                    321: }
                    322: /*
                    323: **  SENDMESSAGE -- send a message to a particular user.
                    324: **
                    325: **     Parameters:
                    326: **             msgf -- filename containing the message.
                    327: **             user -- user who should receive it.
                    328: **
                    329: **     Returns:
                    330: **             none.
                    331: **
                    332: **     Side Effects:
                    333: **             sends mail to 'user' using /usr/lib/sendmail.
                    334: */
                    335: 
                    336: sendmessage(msgf, user, myname)
                    337:        char *msgf;
                    338:        char *user;
                    339:        char *myname;
                    340: {
                    341:        FILE *f;
                    342: 
                    343:        /* find the message to send */
                    344:        f = freopen(msgf, "r", stdin);
                    345:        if (f == NULL)
                    346:        {
                    347:                f = freopen("/usr/lib/vacation.def", "r", stdin);
                    348:                if (f == NULL)
                    349:                        syserr("No message to send");
                    350:        }
                    351: 
                    352:        execl("/usr/lib/sendmail", "sendmail", "-f", myname, user, NULL);
                    353:        syserr("Cannot exec /usr/lib/sendmail");
                    354: }
                    355: /*
                    356: **  INITIALIZE -- initialize the database before leaving for vacation
                    357: **
                    358: **     Parameters:
                    359: **             none.
                    360: **
                    361: **     Returns:
                    362: **             none.
                    363: **
                    364: **     Side Effects:
                    365: **             Initializes the files .vacation.{pag,dir} in the
                    366: **             caller's home directory.
                    367: */
                    368: 
                    369: initialize()
                    370: {
                    371:        char *homedir;
                    372:        char buf[MAXLINE];
                    373:        extern char *getenv();
                    374: 
                    375:        setgid(getgid());
                    376:        setuid(getuid());
                    377:        homedir = getenv("HOME");
                    378:        if (homedir == NULL)
                    379:                syserr("No home!");
                    380:        (void) strcpy(buf, homedir);
                    381:        (void) strcat(buf, "/.vacation.dir");
                    382:        if (close(creat(buf, 0644)) < 0)
                    383:                syserr("Cannot create %s", buf);
                    384:        (void) strcpy(buf, homedir);
                    385:        (void) strcat(buf, "/.vacation.pag");
                    386:        if (close(creat(buf, 0644)) < 0)
                    387:                syserr("Cannot create %s", buf);
                    388: }
                    389: /*
                    390: **  USRERR -- print user error
                    391: **
                    392: **     Parameters:
                    393: **             f -- format.
                    394: **             p -- first parameter.
                    395: **
                    396: **     Returns:
                    397: **             none.
                    398: **
                    399: **     Side Effects:
                    400: **             none.
                    401: */
                    402: 
                    403: usrerr(f, p)
                    404:        char *f;
                    405:        char *p;
                    406: {
                    407:        fprintf(stderr, "vacation: ");
                    408:        _doprnt(f, &p, stderr);
                    409:        fprintf(stderr, "\n");
                    410: }
                    411: /*
                    412: **  SYSERR -- print system error
                    413: **
                    414: **     Parameters:
                    415: **             f -- format.
                    416: **             p -- first parameter.
                    417: **
                    418: **     Returns:
                    419: **             none.
                    420: **
                    421: **     Side Effects:
                    422: **             none.
                    423: */
                    424: 
                    425: syserr(f, p)
                    426:        char *f;
                    427:        char *p;
                    428: {
                    429:        fprintf(stderr, "vacation: ");
                    430:        _doprnt(f, &p, stderr);
                    431:        fprintf(stderr, "\n");
                    432:        exit(EX_USAGE);
                    433: }
                    434: /*
                    435: **  NEWSTR -- copy a string
                    436: **
                    437: **     Parameters:
                    438: **             s -- the string to copy.
                    439: **
                    440: **     Returns:
                    441: **             A copy of the string.
                    442: **
                    443: **     Side Effects:
                    444: **             none.
                    445: */
                    446: 
                    447: char *
                    448: newstr(s)
                    449:        char *s;
                    450: {
                    451:        char *p;
                    452:        extern char *malloc();
                    453: 
                    454:        p = malloc(strlen(s) + 1);
                    455:        if (p == NULL)
                    456:        {
                    457:                syserr("newstr: cannot alloc memory");
                    458:                exit(EX_OSERR);
                    459:        }
                    460:        strcpy(p, s);
                    461:        return (p);
                    462: }
                    463: /*
                    464: **  SAMEWORD -- return TRUE if the words are the same
                    465: **
                    466: **     Ignores case.
                    467: **
                    468: **     Parameters:
                    469: **             a, b -- the words to compare.
                    470: **
                    471: **     Returns:
                    472: **             TRUE if a & b match exactly (modulo case)
                    473: **             FALSE otherwise.
                    474: **
                    475: **     Side Effects:
                    476: **             none.
                    477: */
                    478: 
                    479: bool
                    480: sameword(a, b)
                    481:        register char *a, *b;
                    482: {
                    483:        char ca, cb;
                    484: 
                    485:        do
                    486:        {
                    487:                ca = *a++;
                    488:                cb = *b++;
                    489:                if (isascii(ca) && isupper(ca))
                    490:                        ca = ca - 'A' + 'a';
                    491:                if (isascii(cb) && isupper(cb))
                    492:                        cb = cb - 'A' + 'a';
                    493:        } while (ca != '\0' && ca == cb);
                    494:        return (ca == cb);
                    495: }

unix.superglobalmegacorp.com

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