remove vacation.ignore stuff; first cut at checking To: and Cc: lines
authorKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Sun, 27 Dec 1987 07:27:46 +0000 (23:27 -0800)
committerKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Sun, 27 Dec 1987 07:27:46 +0000 (23:27 -0800)
for mention of user's login or aliases; remove messages to stderr.

SCCS-vsn: usr.bin/vacation/vacation.c 5.7

usr/src/usr.bin/vacation/vacation.c

index c766a03..4103420 100644 (file)
@@ -1,17 +1,31 @@
+/*
+ * Copyright (c) 1983, 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of California at Berkeley. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1983, 1987 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)vacation.c 5.7 (Berkeley) %G%";
+#endif /* not lint */
+
 /*
 **  Vacation
 **  Copyright (c) 1983  Eric P. Allman
 **  Berkeley, California
 /*
 **  Vacation
 **  Copyright (c) 1983  Eric P. Allman
 **  Berkeley, California
-**
-**  Copyright (c) 1983, 1987 Regents of the University of California.
-**  All rights reserved.  The Berkeley software License Agreement
-**  specifies the terms and conditions for redistribution.
 */
 
 */
 
-#ifndef lint
-static char    SccsId[] = "@(#)vacation.c      5.6 (Berkeley) %G%";
-#endif not lint
-
 #include <sys/param.h>
 #include <sys/file.h>
 #include <pwd.h>
 #include <sys/param.h>
 #include <sys/file.h>
 #include <pwd.h>
@@ -29,181 +43,161 @@ static char       SccsId[] = "@(#)vacation.c      5.6 (Berkeley) %G%";
 **     prevent "I am on vacation" loops.
 */
 
 **     prevent "I am on vacation" loops.
 */
 
-#define        NO      0                       /* no/false */
-#define        YES     1                       /* yes/true */
-#define        EOS     '\0'                    /* end of string */
 #define        MAXLINE 500                     /* max line from mail header */
 #define        PERIOD  (60L*60L*24L*7L)        /* week between notifications */
 #define        MAXLINE 500                     /* max line from mail header */
 #define        PERIOD  (60L*60L*24L*7L)        /* week between notifications */
+#define        VMSG    ".vacation.msg"         /* vacation message */
 #define        VACAT   ".vacation"             /* dbm's database prefix */
 #define        VDIR    ".vacation.dir"         /* dbm's DB prefix, part 1 */
 #define        VACAT   ".vacation"             /* dbm's database prefix */
 #define        VDIR    ".vacation.dir"         /* dbm's DB prefix, part 1 */
-#define        VIGN    ".vacation.ignore"      /* addresses never replied to */
-#define        VLOG    ".vacation.log"         /* log action and errors */
-#define        VMSG    ".vacation.msg"         /* vacation message */
 #define        VPAG    ".vacation.pag"         /* dbm's DB prefix, part 2 */
 
 #define        VPAG    ".vacation.pag"         /* dbm's DB prefix, part 2 */
 
-typedef struct {
-       char    *dptr;
-       int     dsize;
-} DATUM;
-
-typedef struct {
-       time_t  sentdate;
-} DBREC;
+typedef struct alias {
+       struct alias *next;
+       char    *name;
+} ALIAS;
+ALIAS  *names;
 
 
-static int     debug;                  /* debugging flag */
+static char from[MAXLINE];             /* sender's address */
 
 main(argc, argv)
 
 main(argc, argv)
-       int     argc;
-       char    **argv;
+       int argc;
+       char **argv;
 {
 {
-       extern int      optind;
-       struct passwd   *pw;
-       int     ch, iflag = NO;
-       char    *from,
-               *getfrom();
-       uid_t   getuid();
-
-       while ((ch = getopt(argc, argv, "Idi")) != EOF)
+       extern int optind;
+       extern char *optarg;
+       struct passwd *pw;
+       ALIAS *cur;
+       int ch, iflag;
+       char *malloc();
+       uid_t getuid();
+
+       iflag = 0;
+       while ((ch = getopt(argc, argv, "a:Ii")) != EOF)
                switch((char)ch) {
                switch((char)ch) {
+               case 'a':                       /* alias */
+                       if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))))
+                               break;
+                       cur->name = optarg;
+                       cur->next = names;
+                       names = cur;
+                       break;
                case 'i':                       /* init the database */
                case 'I':                       /* backward compatible */
                case 'i':                       /* init the database */
                case 'I':                       /* backward compatible */
-                       iflag = YES;
-                       break;
-               case 'd':                       /* debugging */
-                       debug = YES;
+                       iflag = 1;
                        break;
                case '?':
                default:
                        break;
                case '?':
                default:
-                       usage();
+                       goto usage;
                }
                }
-       argv += optind;
        argc -= optind;
        argc -= optind;
+       argv += optind;
 
 
-       /* find and move to user's home directory */
        if (argc != 1) {
        if (argc != 1) {
-               if (!iflag)
-                       usage();
-               if (!(pw = getpwuid(getuid())) || chdir(pw->pw_dir)) {
-                       fprintf(stderr, "vacation: no such user uid %u.\n", getuid());
+               if (!iflag) {
+usage:                 syslog(LOG_ERR, "uid %u: usage: vacation [-i] [-a alias] login\n", getuid());
+                       exit(EX_USAGE);
+               }
+               if (!(pw = getpwuid(getuid()))) {
                        syslog(LOG_ERR, "vacation: no such user uid %u.\n", getuid());
                        exit(EX_USAGE);
                }
                        syslog(LOG_ERR, "vacation: no such user uid %u.\n", getuid());
                        exit(EX_USAGE);
                }
-               *argv = pw->pw_name;
        }
        }
-       else if (!(pw = getpwnam(*argv)) || chdir(pw->pw_dir)) {
-               fprintf(stderr, "vacation: no such user %s.\n", *argv);
+       else if (!(pw = getpwnam(*argv))) {
                syslog(LOG_ERR, "vacation: no such user %s.\n", *argv);
                exit(EX_USAGE);
        }
                syslog(LOG_ERR, "vacation: no such user %s.\n", *argv);
                exit(EX_USAGE);
        }
+       if (chdir(pw->pw_dir)) {
+               syslog(LOG_ERR, "vacation: no such directory %s.\n", pw->pw_dir);
+               exit(EX_USAGE);
+       }
 
 
-       /* iflag cleans out the database */
        if (iflag) {
                initialize();
                exit(EX_OK);
        }
 
        if (iflag) {
                initialize();
                exit(EX_OK);
        }
 
-       if (debug) {
-               time_t  now,
-                       time();
-               char    *ctime();
+       if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))))
+               exit(EX_SOFTWARE);
+       cur->name = pw->pw_name;
+       cur->next = names;
+       names = cur;
 
 
-               if (!freopen(VLOG, "a", stderr)) {
-                       fprintf(stderr, "vacation: can't append ~%s/%s\n", *argv, VLOG);
-                       syslog(LOG_ERR, "vacation: can't append ~%s/%s\n", *argv, VLOG);
-                       exit(EX_CANTCREAT);
-               }
-               (void)time(&now);
-               fprintf(stderr, "===== %s", ctime(&now));
-       }
+       readheaders();
 
 
-       /*
-        * if database missing, we create it and do a dbminit;
-        * otherwise, just do the dbminit.
-        */
        if (access(VDIR, F_OK))
                initialize();
        else
                dbminit(VACAT);
 
        if (access(VDIR, F_OK))
                initialize();
        else
                dbminit(VACAT);
 
-       /* find out who sent us mail */
-       from = getfrom(&shortfrom);
-#ifdef VDEBUG
-       printf("from='%s'\nshortfrom='%s'\n", from, shortfrom);
-       exit(0);
-#endif
-
-               setknows(shortfrom);
-
-       /*
-        * ignore if recently replied to this address,
-        * else note the time and send a reply
-        */
-       if (!knows(from)) {
-               setknows(from, NO);
-               sendmessage(from, *argv);
+       if (!recent()) {
+               setreply();
+               sendmessage(pw->pw_name);
        }
        exit(EX_OK);
 }
 
 /*
        }
        exit(EX_OK);
 }
 
 /*
- * getfrom --
- *     read mail "From" line and return sender's address
+ * readheaders --
+ *     read mail headers
  */
  */
-static char *
 getfrom(shortp)
 char **shortp;
 {
 getfrom(shortp)
 char **shortp;
 {
-       register char   *p;
-       char    buf[MAXLINE],
-               *malloc(), *strcpy();
-
-       /* read the from line */
-       if (!gets(buf) || strncmp(buf, "From ", 5)) {
-               fputs("vacation: no initial From line.\n", stderr);
-               exit(EX_DATAERR);
-       }
-
-       /* find the end of the sender address and terminate it */
-       for (p = &buf[5]; *p && *p != ' '; ++p);
-       if (!*p) {
-               fprintf(stderr, "vacation: address terminated From line '%s'\n", buf);
+       register ALIAS *cur;
+       register char *p;
+       int tome, cont;
+       char buf[MAXLINE], *strcpy(), *index();
+
+       cont = tome = 0;
+       while (fgets(buf, sizeof(buf), stdin) && *buf != '\n')
+               switch(*buf) {
+               case 'F':               /* "From " */
+                       cont = 0;
+                       if (!strncmp(buf, "From ", 5)) {
+                               for (p = buf + 5; *p && *p != ' '; ++p);
+                               *p = '\0';
+                               (void)strcpy(from, buf + 5);
+                               if (junkmail())
+                                       exit(EX_OK);
+                       }
+                       break;
+               case 'P':               /* "Precedence:" */
+                       cont = 0;
+                       if (strncasecmp(buf, "Precedence", 10) || buf[10] != ':' && buf[10] != ' ' && buf[10] != '\t')
+                               break;
+                       if (!(p = index(buf, ':')))
+                               break;
+                       while (*++p && isspace(*p));
+                       if (!*p)
+                               break;
+                       if (!strncasecmp(p, "junk", 4) || !strncasecmp(p, "bulk", 4))
+                               exit(EX_OK);
+                       break;
+               case 'C':               /* "Cc:" */
+                       if (!strncmp(buf, "Cc:", 3))
+                               break;
+                       cont = 1;
+                       goto findme;
+               case 'T':               /* "To:" */
+                       if (strncmp(buf, "To:", 3))
+                               break;
+                       cont = 1;
+                       goto findme;
+               default:
+                       if (!isspace(*buf) || !cont || tome) {
+                               cont = 0;
+                               break;
+                       }
+findme:                        for (cur = names; !tome && cur; cur = cur->next)
+                               tome += nsearch(cur->name, buf);
+               }
+       if (!tome)
+               exit(EX_OK);
+       if (!*from) {
+               syslog(LOG_ERR, "vacation: no initial \"From\" line.\n");
                exit(EX_DATAERR);
        }
                exit(EX_DATAERR);
        }
-       *p = EOS;
-       if (!(p = malloc((u_int)(strlen(&buf[5]) + 1)))) {
-               fputs("vacation: out of space.\n", stderr);
-               exit(EX_OSERR);
-       }
-       /*
-        * Strip all but the rightmost UUCP host
-        * to prevent loops due to forwarding.
-        * Start searching leftward from the leftmost '@'.
-        *      a!b!c!d yields a short name of c!d
-        *      a!b!c!d@e yields a short name of c!d@e
-        *      e@a!b!c yields the same short name
-        */
-#ifdef VDEBUG
-printf("start='%s'\n", start);
-#endif
-       *shortp = start;                        /* assume whole addr */
-       if ((at = index(start, '@')) == NULL)   /* leftmost '@' */
-               at = p;                         /* if none, use end of addr */
-       saveat = *at;
-       *at = '\0';
-       if ((bang = rindex(start, '!')) != NULL) {      /* rightmost '!' */
-               char *bang2;
-
-               *bang = '\0';
-               if ((bang2 = rindex(start, '!')) != NULL) /* 2nd rightmost '!' */
-                       *shortp = bang2 + 1;            /* move past ! */
-               *bang = '!';
-       }
-       *at = saveat;
-#ifdef VDEBUG
-printf("place='%s'\n", *shortp);
-#endif
+}
 
 
-       /* return the sender address */
        return start;
 }
 
        return start;
 }
 
@@ -212,87 +206,64 @@ printf("place='%s'\n", *shortp);
  *     read the header and return if automagic/junk/bulk mail
  */
 static
  *     read the header and return if automagic/junk/bulk mail
  */
 static
-junkmail(from)
-       char    *from;
+junkmail()
 {
        static struct ignore {
                char    *name;
                int     len;
        } ignore[] = {
 {
        static struct ignore {
                char    *name;
                int     len;
        } ignore[] = {
-               "-REQUEST", 8,          "Postmaster", 10,
-               "uucp", 4,              "MAILER-DAEMON", 13,
-               "MAILER", 6,            NULL, NULL,
+               "-REQUEST", 8,  "Postmaster", 10,
+               "uucp", 4,      "MAILER-DAEMON", 13,
+               "MAILER", 6,    NULL, NULL,
        };
        };
-       register struct ignore  *I;
-       register int    len;
-       register char   *p;
-       char    buf[MAXLINE],
-               *index(), *rindex();
+       register struct ignore *cur;
+       register int len;
+       register char *p;
+       char *index(), *rindex();
 
        /*
 
        /*
-        * This is mildly amusing, and I'm not positive it's right; what
-        * we're trying to do is find the "real" name of the sender.  I'm
-        * assuming that addresses will be some variant of:
-        *
-        * From SENDER
-        * From SENDER@seismo.css.gov
-        * From SENDER%site.BITNET@seismo.css.gov
-        * From site1!site2!SENDER@seismo.css.gov
+        * This is mildly amusing, and I'm not positive it's right; trying
+        * to find the "real" name of the sender, assuming that addresses
+        * will be some variant of:
         *
         *
-        * Therefore, the following search order:
+        * From site!site!SENDER%site.domain%site.domain@site.domain
         */
        if (!(p = index(from, '%')))
                if (!(p = index(from, '@'))) {
                        if (p = rindex(from, '!'))
                                ++p;
         */
        if (!(p = index(from, '%')))
                if (!(p = index(from, '@'))) {
                        if (p = rindex(from, '!'))
                                ++p;
-                       for (p = from; *p; ++p);
+                       else
+                               p = from;
+                       for (; *p; ++p);
                }
        len = p - from;
                }
        len = p - from;
-       for (I = ignore; I->name; ++I)
-               if (len >= I->len && !strncasecmp(I->name, p - I->len, I->len)) {
-                       if (debug)
-                               fprintf(stderr, "not sending to %s {%s}\n", from, I->name);
-                       return(YES);
-               }
-
-       /* read the header looking for a "Precedence:" line */
-       while (gets(buf) && *buf) {
-               if (strncasecmp(buf, "Precedence", 10) ||
-                  buf[10] != ':' && buf[10] != ' ' && buf[10] != '\t')
-                       continue;
+       for (cur = ignore; cur->name; ++cur)
+               if (len >= cur->len && !strncasecmp(cur->name, p - cur->len, cur->len))
+                       return(1);
+       return(0);
+}
 
 
-               /* find the value of this field */
-               if (!(p = index(buf, ':')))
-                       continue;
-               while (*++p && isspace(*p));
-               if (!*p)
-                       continue;
+typedef struct {
+       char    *dptr;
+       int     dsize;
+} DATUM;
 
 
-               /* see if it is "junk" or "bulk" */
-               if (!strncasecmp(p, "junk", 4) || !strncasecmp(p, "bulk", 4)) {
-                       if (debug)
-                               fprintf(stderr, "not sending to %s {junk/bulk}\n", from);
-                       return(YES);
-               }
-       }
-       return(NO);
-}
+typedef struct {
+       time_t  sentdate;
+} DBREC;
 
 /*
 
 /*
- * knows --
+ * recent --
  *     find out if user has gotten a vacation message recently.
  */
 static
  *     find out if user has gotten a vacation message recently.
  */
 static
-knows(user)
 char *user;
 {
 char *user;
 {
-       DATUM   k, d,
-               fetch();
-       time_t  now, then,
-               time();
+       DATUM k, d, fetch();
+       time_t now, then, time();
 
 
-       k.dptr = user;
-       k.dsize = strlen(user) + 1;
+       k.dptr = from;
+       k.dsize = strlen(from) + 1;
        d = fetch(k);
        if (d.dptr == NULL)
                return FALSE;
        d = fetch(k);
        if (d.dptr == NULL)
                return FALSE;
@@ -311,25 +282,19 @@ register unsigned size;
 #endif
 
 /*
 #endif
 
 /*
- * setknows --
+ * setreply --
  *     store that this user knows about the vacation.
  */
 static
  *     store that this user knows about the vacation.
  */
 static
-setknows(user, forever)
-       char    *user;
-       int     forever;
+setreply()
 {
 {
-       DBREC   xrec;
-       DATUM   k, d;
-       time_t  time();
+       DBREC xrec;
+       DATUM k, d;
+       time_t time();
 
 
-       k.dptr = user;
-       k.dsize = strlen(user) + 1;
-       if (forever)
-               /* zero is the flag value meaning *never* reply */
-               xrec.sentdate = 0;
-       else
-               (void)time(&xrec.sentdate);
+       k.dptr = from;
+       k.dsize = strlen(from) + 1;
+       (void)time(&xrec.sentdate);
        d.dptr = (char *)&xrec;
        d.dsize = sizeof(xrec);
        store(k, d);
        d.dptr = (char *)&xrec;
        d.dsize = sizeof(xrec);
        store(k, d);
@@ -337,76 +302,41 @@ setknows(user, forever)
 
 /*
  * sendmessage --
 
 /*
  * sendmessage --
- *     exec sendmail to send the vacation file to "user".
+ *     exec sendmail to send the vacation file to sender
  */
 static
  */
 static
-sendmessage(user, myname)
-       char    *user, *myname;
+sendmessage(myname)
+       char *myname;
 {
 {
-       if (debug) {
-               fprintf(stderr, "sending {%s} to {%s}\n", VMSG, user);
-               return;
-       }
        if (!freopen(VMSG, "r", stdin)) {
        if (!freopen(VMSG, "r", stdin)) {
-               fprintf(stderr, "vacation: no ~%s/%s file.\n", myname, VMSG);
                syslog(LOG_ERR, "vacation: no ~%s/%s file.\n", myname, VMSG);
                exit(EX_NOINPUT);
        }
                syslog(LOG_ERR, "vacation: no ~%s/%s file.\n", myname, VMSG);
                exit(EX_NOINPUT);
        }
-       execl("/usr/lib/sendmail", "sendmail", "-f", myname, user, NULL);
-       fprintf(stderr, "vacation: can't exec /usr/lib/sendmail.\n");
+       execl("/usr/lib/sendmail", "sendmail", "-f", myname, from, NULL);
        syslog(LOG_ERR, "vacation: can't exec /usr/lib/sendmail.\n");
        exit(EX_OSERR);
 }
 
 /*
  * initialize --
        syslog(LOG_ERR, "vacation: can't exec /usr/lib/sendmail.\n");
        exit(EX_OSERR);
 }
 
 /*
  * initialize --
- *     initialize the database
+ *     initialize the dbm database
  */
 static
 initialize()
 {
  */
 static
 initialize()
 {
-       extern int      errno;
-       extern char     *sys_errlist[];
-       FILE    *fp;
-       int     fd;
+       extern int errno;
+       extern char *sys_errlist[];
+       int fd;
 
        if ((fd = open(VDIR, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
 
        if ((fd = open(VDIR, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
-               fprintf(stderr, "vacation: %s: %s\n", VDIR, sys_errlist[errno]);
                syslog(LOG_ERR, "vacation: %s: %s\n", VDIR, sys_errlist[errno]);
                exit(EX_OSERR);
        }
        (void)close(fd);
        if ((fd = open(VPAG, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
                syslog(LOG_ERR, "vacation: %s: %s\n", VDIR, sys_errlist[errno]);
                exit(EX_OSERR);
        }
        (void)close(fd);
        if ((fd = open(VPAG, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
-               fprintf(stderr, "vacation: %s: %s\n", VPAG, sys_errlist[errno]);
                syslog(LOG_ERR, "vacation: %s: %s\n", VPAG, sys_errlist[errno]);
                exit(EX_OSERR);
        }
        (void)close(fd);
        dbminit(VACAT);
                syslog(LOG_ERR, "vacation: %s: %s\n", VPAG, sys_errlist[errno]);
                exit(EX_OSERR);
        }
        (void)close(fd);
        dbminit(VACAT);
-       if (fp = fopen(VIGN, "r")) {
-               char    buf[MAXLINE],
-                       *index();
-
-/* VARARGS 1 */
-               while (fgets(buf, sizeof(buf), fp)) {
-                       *(index(buf, '\n')) = EOS;
-                       setknows(buf, YES);
-               }
-               (void)fclose(fp);
-       }
-       return p;
-}
-
-/*
- * usage --
- *     print out a usage message and die
- */
-static
-usage()
-{
-       uid_t   getuid();
-
-       fputs("usage: vacation [-i] login\n", stderr);
-       syslog(LOG_ERR, "uid %u: usage: vacation [-i] login\n", getuid());
-       exit(EX_USAGE);
 }
 }