add -r flag for user settable reply intervals; replace dbm with ndbm;
authorKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Wed, 8 Feb 1989 12:45:05 +0000 (04:45 -0800)
committerKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Wed, 8 Feb 1989 12:45:05 +0000 (04:45 -0800)
remove DATUM, DBREC -- should simply be able to bcopy buffer onto the time_t,
shouldn't need all that struct stuff

SCCS-vsn: usr.bin/vacation/vacation.1 6.7
SCCS-vsn: usr.bin/vacation/vacation.c 5.12

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

index b593b5d..0fb6247 100644 (file)
@@ -13,7 +13,7 @@
 .\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 .\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
 .\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 .\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.\"    @(#)vacation.1  6.6 (Berkeley) %G%
+.\"    @(#)vacation.1  6.7 (Berkeley) %G%
 .\"
 .TH VACATION 1 ""
 .UC 6
 .\"
 .TH VACATION 1 ""
 .UC 6
@@ -22,16 +22,22 @@ vacation \- return ``I am not here'' indication
 .SH SYNOPSIS
 .B vacation
 .B -i
 .SH SYNOPSIS
 .B vacation
 .B -i
+[
+.B -r
+interval ]
 .br
 .B vacation
 [
 .B -a
 alias ] login
 .SH DESCRIPTION
 .br
 .B vacation
 [
 .B -a
 alias ] login
 .SH DESCRIPTION
-\fIVacation\fP returns a message to the sender of a message telling
-them that you are currently not reading your mail.  The intended use
-is in a \fI.forward\fP file.  For example, your \fI.forward\fP file
-might have:
+.I Vacation
+returns a message to the sender of a message telling them that you
+are currently not reading your mail.  The intended use is in a
+.I .forward
+file.  For example, your
+.I .forward
+file might have:
 .PP
 .ti +5
 \eeric, "|/usr/ucb/vacation -a allman eric"
 .PP
 .ti +5
 \eeric, "|/usr/ucb/vacation -a allman eric"
@@ -39,22 +45,49 @@ might have:
 which would send messages to you (assuming your login name was eric) and
 reply to any messages for ``eric'' or ``allman''.
 .PP
 which would send messages to you (assuming your login name was eric) and
 reply to any messages for ``eric'' or ``allman''.
 .PP
-No message will be sent unless \fIlogin\fP or an \fIalias\fP supplied
-using the \fB-a\fP option is a substring of either the ``To:'' or ``Cc:''
-headers of the mail.  No messages from ``???-REQUEST'', ``Postmaster'',
-``UUCP'', ``MAILER'', or ``MAILER-DAEMON'' will be replied to, nor is a
-notification sent if a ``Precedence: bulk'' or ``Precedence: junk'' line
-is included in the mail headers.  Only one message per week will be sent
-to each unique sender.  The people who have sent you messages are
-maintained as an \fIndbm\fP(3) database in the files \fI.vacation.pag\fP
-and \fI.vacation.dir\fP in your home directory.
+No message will be sent unless
+.I login
+(or an
+.I alias
+supplied using the
+.B -a
+option) is part of either the ``To:'' or ``Cc:'' headers of the mail.
+No messages from ``???-REQUEST'', ``Postmaster'', ``UUCP'', ``MAILER'',
+or ``MAILER-DAEMON'' will be replied to (where these strings are
+case insensitive) nor is a notification sent if a ``Precedence: bulk''
+or ``Precedence: junk'' line is included in the mail headers.
+The people who have sent you messages are maintained as an
+.IR ndbm (3)
+database in the files
+.I .vacation.pag
+and
+.I .vacation.dir
+in your home directory.
+.PP
+The
+.B -i
+flag initializes the vacation database files.  It should be used
+before you modify your
+.I .forward
+file.
 .PP
 .PP
-The \fB-i\fP flag initializes the vacation database files.  It should be
-used before you modify your \fI.forward\fP file.
+The
+.B -r
+flag sets the reply interval to
+.I interval
+days.  The default is one week.  An interval of ``0'' means that
+a reply is sent to each message, and an interval of ``infinite''
+(actually, any non-numeric character) will never send more than
+one reply.  It should be noted that intervals of ``0'' are quite
+dangerous, as it allows mailers to get into ``I am on vacation''
+loops.
 .PP
 .PP
-\fIVacation\fP expects a file \fI.vacation.msg\fP, in your home directory,
-containing a message to be sent back to each sender.  It should be an entire
-message (including headers).  For example, it might say:
+.I Vacation
+expects a file
+.IR .vacation.msg ,
+in your home directory, containing a message to be sent back to each
+sender.  It should be an entire message (including headers).  For
+example, it might contain:
 .PP
 .in +5
 .nf
 .PP
 .in +5
 .nf
@@ -69,13 +102,18 @@ please contact Joe Kalash <kalash@ucbingres.Berkeley.EDU>.
 .fi
 .in -5
 .PP
 .fi
 .in -5
 .PP
-\fIVacation\fP reads the first line from the standard input for
-a \s-1UNIX\s0-style ``From'' line to determine the sender.
-\fISendmail\fP(8) includes this ``From'' line automatically.
+.I Vacation
+reads the first line from the standard input for a \s-1UNIX\s0-style
+``From'' line to determine the sender.
+.IR Sendmail (8)
+includes this ``From'' line automatically.
 .PP
 .PP
-Fatal errors, such as calling \fIvacation\fP with incorrect arguments,
-or with non-existent \fIlogin\fPs, are logged in the system log file,
-using \fIsyslog\fP(8).
+Fatal errors, such as calling
+.I vacation
+with incorrect arguments, or with non-existent
+.IR login s,
+are logged in the system log file, using
+.IR syslog (8).
 .SH FILES
 .nf
 .ta \w'~/.vacation.msg    'u
 .SH FILES
 .nf
 .ta \w'~/.vacation.msg    'u
index 169a4ce..110de98 100644 (file)
@@ -22,7 +22,7 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)vacation.c 5.11 (Berkeley) %G%";
+static char sccsid[] = "@(#)vacation.c 5.12 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -34,21 +34,22 @@ static char sccsid[] = "@(#)vacation.c      5.11 (Berkeley) %G%";
 #include <sys/param.h>
 #include <sys/file.h>
 #include <pwd.h>
 #include <sys/param.h>
 #include <sys/file.h>
 #include <pwd.h>
+#include <ndbm.h>
+#include <syslog.h>
+#include <tzfile.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <stdio.h>
 #include <ctype.h>
-#include <syslog.h>
 
 /*
 
 /*
-**  VACATION -- return a message to the sender when on vacation.
-**
-**     This program could be invoked as a message receiver when someone is
-**     on vacation.  It returns a message specified by the user to whoever
-**     sent the mail, taking care not to return a message too often to
-**     prevent "I am on vacation" loops.
-*/
+ *  VACATION -- return a message to the sender when on vacation.
+ *
+ *     This program is invoked as a message receiver.  It returns a
+ *     message specified by the user to whomever sent the mail, taking
+ *     care not to return a message too often to prevent "I am on
+ *     vacation" loops.
+ */
 
 #define        MAXLINE 500                     /* max line from mail header */
 
 #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        VMSG    ".vacation.msg"         /* vacation message */
 #define        VACAT   ".vacation"             /* dbm's database prefix */
 #define        VDIR    ".vacation.dir"         /* dbm's DB prefix, part 1 */
@@ -56,26 +57,34 @@ static char sccsid[] = "@(#)vacation.c      5.11 (Berkeley) %G%";
 
 typedef struct alias {
        struct alias *next;
 
 typedef struct alias {
        struct alias *next;
-       char    *name;
+       char *name;
 } ALIAS;
 } ALIAS;
-ALIAS  *names;
+ALIAS *names;
 
 
-static char from[MAXLINE];             /* sender's address */
+static DBM *db;
+
+extern int errno;
+
+#define        VIT     "__VACATION__INTERVAL__TIMER__"
+static char from[MAXLINE];
 
 main(argc, argv)
        int argc;
        char **argv;
 {
 
 main(argc, argv)
        int argc;
        char **argv;
 {
-       extern int optind;
+       extern int optind, opterr;
        extern char *optarg;
        struct passwd *pw;
        ALIAS *cur;
        extern char *optarg;
        struct passwd *pw;
        ALIAS *cur;
+       time_t interval;
        int ch, iflag;
        char *malloc();
        uid_t getuid();
        int ch, iflag;
        char *malloc();
        uid_t getuid();
+       long atol();
 
 
-       iflag = 0;
-       while ((ch = getopt(argc, argv, "a:Ii")) != EOF)
+       opterr = iflag = 0;
+       interval = -1;
+       while ((ch = getopt(argc, argv, "a:Iir:")) != EOF)
                switch((char)ch) {
                case 'a':                       /* alias */
                        if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))))
                switch((char)ch) {
                case 'a':                       /* alias */
                        if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))))
@@ -84,10 +93,19 @@ main(argc, argv)
                        cur->next = names;
                        names = cur;
                        break;
                        cur->next = names;
                        names = cur;
                        break;
-               case 'i':                       /* init the database */
                case 'I':                       /* backward compatible */
                case 'I':                       /* backward compatible */
+               case 'i':                       /* init the database */
                        iflag = 1;
                        break;
                        iflag = 1;
                        break;
+               case 'r':
+                       if (isdigit(*optarg)) {
+                               interval = atol(optarg) * SECS_PER_DAY;
+                               if (interval < 0)
+                                       goto usage;
+                       }
+                       else
+                               interval = LONG_MAX;
+                       break;
                case '?':
                default:
                        goto usage;
                case '?':
                default:
                        goto usage;
@@ -97,46 +115,50 @@ main(argc, argv)
 
        if (argc != 1) {
                if (!iflag) {
 
        if (argc != 1) {
                if (!iflag) {
-usage:                 syslog(LOG_ERR, "uid %u: usage: vacation [-i] [-a alias] login\n", getuid());
-                       exit(1);
+usage:                 syslog(LOG_NOTICE, "uid %u: usage: vacation [-i] [-a alias] login\n", getuid());
+                       myexit(1);
                }
                if (!(pw = getpwuid(getuid()))) {
                        syslog(LOG_ERR, "vacation: no such user uid %u.\n", getuid());
                }
                if (!(pw = getpwuid(getuid()))) {
                        syslog(LOG_ERR, "vacation: no such user uid %u.\n", getuid());
-                       exit(1);
+                       myexit(1);
                }
        }
        else if (!(pw = getpwnam(*argv))) {
                syslog(LOG_ERR, "vacation: no such user %s.\n", *argv);
                }
        }
        else if (!(pw = getpwnam(*argv))) {
                syslog(LOG_ERR, "vacation: no such user %s.\n", *argv);
-               exit(1);
+               myexit(1);
        }
        if (chdir(pw->pw_dir)) {
        }
        if (chdir(pw->pw_dir)) {
-               syslog(LOG_ERR, "vacation: no such directory %s.\n", pw->pw_dir);
-               exit(1);
+               syslog(LOG_NOTICE, "vacation: no such directory %s.\n", pw->pw_dir);
+               myexit(1);
        }
 
        }
 
-       if (iflag) {
+       if (iflag || access(VDIR, F_OK))
                initialize();
                initialize();
-               exit(0);
+       if (!(db = dbm_open(VACAT, O_RDWR, 0))) {
+               syslog(LOG_NOTICE, "vacation: %s: %s\n", VACAT,
+                   strerror(errno));
+               myexit(1);
        }
 
        }
 
+       if (interval != -1)
+               setinterval(interval);
+       if (iflag)
+               myexit(0);
+
        if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))))
        if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))))
-               exit(1);
+               myexit(1);
        cur->name = pw->pw_name;
        cur->next = names;
        names = cur;
 
        readheaders();
 
        cur->name = pw->pw_name;
        cur->next = names;
        names = cur;
 
        readheaders();
 
-       if (access(VDIR, F_OK))
-               initialize();
-       else
-               dbminit(VACAT);
-
        if (!recent()) {
                setreply();
                sendmessage(pw->pw_name);
        }
        if (!recent()) {
                setreply();
                sendmessage(pw->pw_name);
        }
-       exit(0);
+       myexit(0);
+       /* NOTREACHED */
 }
 
 /*
 }
 
 /*
@@ -160,8 +182,10 @@ char **shortp;
                                for (p = buf + 5; *p && *p != ' '; ++p);
                                *p = '\0';
                                (void)strcpy(from, buf + 5);
                                for (p = buf + 5; *p && *p != ' '; ++p);
                                *p = '\0';
                                (void)strcpy(from, buf + 5);
+                               if (p = index(from, '\n'))
+                                       *p = '\0';
                                if (junkmail())
                                if (junkmail())
-                                       exit(0);
+                                       myexit(0);
                        }
                        break;
                case 'P':               /* "Precedence:" */
                        }
                        break;
                case 'P':               /* "Precedence:" */
@@ -174,7 +198,7 @@ char **shortp;
                        if (!*p)
                                break;
                        if (!strncasecmp(p, "junk", 4) || !strncasecmp(p, "bulk", 4))
                        if (!*p)
                                break;
                        if (!strncasecmp(p, "junk", 4) || !strncasecmp(p, "bulk", 4))
-                               exit(0);
+                               myexit(0);
                        break;
                case 'C':               /* "Cc:" */
                        if (strncmp(buf, "Cc:", 3))
                        break;
                case 'C':               /* "Cc:" */
                        if (strncmp(buf, "Cc:", 3))
@@ -195,10 +219,10 @@ findme:                   for (cur = names; !tome && cur; cur = cur->next)
                                tome += nsearch(cur->name, buf);
                }
        if (!tome)
                                tome += nsearch(cur->name, buf);
                }
        if (!tome)
-               exit(0);
+               myexit(0);
        if (!*from) {
        if (!*from) {
-               syslog(LOG_ERR, "vacation: no initial \"From\" line.\n");
-               exit(1);
+               syslog(LOG_NOTICE, "vacation: no initial \"From\" line.\n");
+               myexit(1);
        }
 }
 
        }
 }
 
@@ -209,7 +233,6 @@ findme:                     for (cur = names; !tome && cur; cur = cur->next)
  * junkmail --
  *     read the header and return if automagic/junk/bulk mail
  */
  * junkmail --
  *     read the header and return if automagic/junk/bulk mail
  */
-static
 junkmail()
 {
        static struct ignore {
 junkmail()
 {
        static struct ignore {
@@ -247,28 +270,16 @@ junkmail()
        return(0);
 }
 
        return(0);
 }
 
-typedef struct {
-       char    *dptr;
-       int     dsize;
-} DATUM;
-
-typedef struct {
-       time_t  sentdate;
-} DBREC;
-
 /*
  * recent --
  *     find out if user has gotten a vacation message recently.
 /*
  * recent --
  *     find out if user has gotten a vacation message recently.
+ *     use bcopy for machines with alignment restrictions
  */
  */
-static
 char *user;
 {
 char *user;
 {
-       DATUM k, d, fetch();
-       time_t now, then, time();
+       datum key, data;
+       time_t then, next, time();
 
 
-       k.dptr = from;
-       k.dsize = strlen(from) + 1;
-       d = fetch(k);
        if (d.dptr == NULL)
                return FALSE;
        bcopy(d.dptr, (char *)&ldbrec, sizeof ldbrec);  /* realign data */
        if (d.dptr == NULL)
                return FALSE;
        bcopy(d.dptr, (char *)&ldbrec, sizeof ldbrec);  /* realign data */
@@ -285,62 +296,83 @@ register unsigned size;
 }
 #endif
 
 }
 #endif
 
+/*
+ * setinterval --
+ *     store the reply interval
+ */
+setinterval(interval)
+       time_t interval;
+{
+       datum key, data;
+
+       key.dptr = VIT;
+       key.dsize = sizeof(VIT) - 1;
+       data.dptr = (char *)&interval;
+       data.dsize = sizeof(interval);
+       dbm_store(db, key, data, DBM_REPLACE);
+}
+
 /*
  * setreply --
  *     store that this user knows about the vacation.
  */
 /*
  * setreply --
  *     store that this user knows about the vacation.
  */
-static
 setreply()
 {
 setreply()
 {
-       DBREC xrec;
-       DATUM k, d;
-       time_t time();
-
-       k.dptr = from;
-       k.dsize = strlen(from) + 1;
-       (void)time(&xrec.sentdate);
-       d.dptr = (char *)&xrec;
-       d.dsize = sizeof(xrec);
-       store(k, d);
+       datum key, data;
+       time_t now, time();
+
+       key.dptr = from;
+       key.dsize = strlen(from);
+       (void)time(&now);
+       data.dptr = (char *)&now;
+       data.dsize = sizeof(now);
+       dbm_store(db, key, data, DBM_REPLACE);
 }
 
 /*
  * sendmessage --
  *     exec sendmail to send the vacation file to sender
  */
 }
 
 /*
  * sendmessage --
  *     exec sendmail to send the vacation file to sender
  */
-static
 sendmessage(myname)
        char *myname;
 {
        if (!freopen(VMSG, "r", stdin)) {
 sendmessage(myname)
        char *myname;
 {
        if (!freopen(VMSG, "r", stdin)) {
-               syslog(LOG_ERR, "vacation: no ~%s/%s file.\n", myname, VMSG);
-               exit(1);
+               syslog(LOG_NOTICE, "vacation: no ~%s/%s file.\n", myname, VMSG);
+               myexit(1);
        }
        execl("/usr/lib/sendmail", "sendmail", "-f", myname, from, NULL);
        syslog(LOG_ERR, "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(1);
+       myexit(1);
 }
 
 /*
  * initialize --
  *     initialize the dbm database
  */
 }
 
 /*
  * initialize --
  *     initialize the dbm database
  */
-static
 initialize()
 {
 initialize()
 {
-       extern int errno;
-       extern char *sys_errlist[];
        int fd;
 
        if ((fd = open(VDIR, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
        int fd;
 
        if ((fd = open(VDIR, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
-               syslog(LOG_ERR, "vacation: %s: %s\n", VDIR, sys_errlist[errno]);
+               syslog(LOG_NOTICE, "vacation: %s: %s\n", VDIR, strerror(errno));
                exit(1);
        }
        (void)close(fd);
        if ((fd = open(VPAG, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
                exit(1);
        }
        (void)close(fd);
        if ((fd = open(VPAG, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
-               syslog(LOG_ERR, "vacation: %s: %s\n", VPAG, sys_errlist[errno]);
+               syslog(LOG_NOTICE, "vacation: %s: %s\n", VPAG, strerror(errno));
                exit(1);
        }
        (void)close(fd);
                exit(1);
        }
        (void)close(fd);
-       dbminit(VACAT);
+}
+
+/*
+ * myexit --
+ *     we're outta here...
+ */
+myexit(eval)
+       int eval;
+{
+       if (db)
+               dbm_close(db);
+       exit(eval);
 }
 }