minor rearrangements
[unix-history] / usr / src / usr.bin / vacation / vacation.c
index 87012b5..c766a03 100644 (file)
 **  Copyright (c) 1983  Eric P. Allman
 **  Berkeley, California
 **
 **  Copyright (c) 1983  Eric P. Allman
 **  Berkeley, California
 **
-**  Copyright (c) 1983 Regents of the University of 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
 **  All rights reserved.  The Berkeley software License Agreement
 **  specifies the terms and conditions for redistribution.
 */
 
 #ifndef lint
-static char    SccsId[] = "@(#)vacation.c      5.3 (Berkeley) %G%";
+static char    SccsId[] = "@(#)vacation.c      5.6 (Berkeley) %G%";
 #endif not lint
 
 #endif not lint
 
-# include <sys/types.h>
-# include <pwd.h>
-# include <stdio.h>
-# include <sysexits.h>
-# include <ctype.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <sysexits.h>
+#include <syslog.h>
 
 /*
 **  VACATION -- return a message to the sender when on vacation.
 **
 
 /*
 **  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.
-**
-**     Positional Parameters:
-**             the user to collect the vacation message from.
-**
-**     Flag Parameters:
-**             -I      initialize the database.
-**             -d      turn on debugging.
-**
-**     Side Effects:
-**             A message is sent back to the sender.
-**
-**     Author:
-**             Eric Allman
-**             UCB/INGRES
+**     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.
 */
 
 */
 
-typedef int    bool;
-
-# define TRUE          1
-# define FALSE         0
-
-# define MAXLINE       256     /* max size of a line */
-# define MAXNAME       128     /* max size of one name */
-
-# define ONEWEEK       (60L*60L*24L*7L)
-
-time_t Timeout = ONEWEEK;      /* timeout between notices per user */
-
-struct dbrec
-{
-       long    sentdate;
-};
-
-typedef struct
-{
+#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        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 */
+
+typedef struct {
        char    *dptr;
        int     dsize;
 } DATUM;
 
        char    *dptr;
        int     dsize;
 } DATUM;
 
-extern DATUM fetch();
-
+typedef struct {
+       time_t  sentdate;
+} DBREC;
 
 
-
-bool   Debug = FALSE;
+static int     debug;                  /* debugging flag */
 
 main(argc, argv)
 
 main(argc, argv)
-       char **argv;
+       int     argc;
+       char    **argv;
 {
 {
-       char *from;
-       register char *p;
-       struct passwd *pw;
-       char *homedir;
-       char *myname;
-       char buf[MAXLINE];
-       extern struct passwd *getpwnam();
-       extern char *newstr();
-       extern char *getfrom();
-       extern bool knows();
-       extern bool junkmail();
-       extern time_t convtime();
-
-       /* process arguments */
-       while (--argc > 0 && (p = *++argv) != NULL && *p == '-')
-       {
-               switch (*++p)
-               {
-                 case 'I':     /* initialize */
-                       initialize();
-                       exit(EX_OK);
-
-                 case 'd':     /* debug */
-                       Debug = TRUE;
+       extern int      optind;
+       struct passwd   *pw;
+       int     ch, iflag = NO;
+       char    *from,
+               *getfrom();
+       uid_t   getuid();
+
+       while ((ch = getopt(argc, argv, "Idi")) != EOF)
+               switch((char)ch) {
+               case 'i':                       /* init the database */
+               case 'I':                       /* backward compatible */
+                       iflag = YES;
                        break;
                        break;
-
-                 default:
-                       usrerr("Unknown flag -%s", p);
+               case 'd':                       /* debugging */
+                       debug = YES;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argv += optind;
+       argc -= optind;
+
+       /* find and move to user's home directory */
+       if (argc != 1) {
+               if (!iflag)
+                       usage();
+               if (!(pw = getpwuid(getuid())) || chdir(pw->pw_dir)) {
+                       fprintf(stderr, "vacation: no such user uid %u.\n", getuid());
+                       syslog(LOG_ERR, "vacation: no such user uid %u.\n", getuid());
                        exit(EX_USAGE);
                }
                        exit(EX_USAGE);
                }
+               *argv = pw->pw_name;
        }
        }
-
-       /* verify recipient argument */
-       if (argc != 1)
-       {
-               usrerr("Usage: vacation username (or) vacation -I");
+       else if (!(pw = getpwnam(*argv)) || chdir(pw->pw_dir)) {
+               fprintf(stderr, "vacation: no such user %s.\n", *argv);
+               syslog(LOG_ERR, "vacation: no such user %s.\n", *argv);
                exit(EX_USAGE);
        }
 
                exit(EX_USAGE);
        }
 
-       myname = p;
-
-       /* find user's home directory */
-       pw = getpwnam(myname);
-       if (pw == NULL)
-       {
-               usrerr("Unknown user %s", myname);
-               exit(EX_NOUSER);
+       /* iflag cleans out the database */
+       if (iflag) {
+               initialize();
+               exit(EX_OK);
        }
        }
-       homedir = newstr(pw->pw_dir);
-       (void) strcpy(buf, homedir);
-       (void) strcat(buf, "/.vacation");
-       dbminit(buf);
-
-       /* read message from standard input (just from line) */
-       from = getfrom();
-
-       /* check if junk mail or this person is already informed */
-       if (!junkmail(from) && !knows(from))
-       {
-               /* mark this person as knowing */
-               setknows(from);
-
-               /* send the message back */
-               (void) strcpy(buf, homedir);
-               (void) strcat(buf, "/.vacation.msg");
-               if (Debug)
-                       printf("Sending %s to %s\n", buf, from);
-               else
-               {
-                       sendmessage(buf, from, myname);
-                       /*NOTREACHED*/
+
+       if (debug) {
+               time_t  now,
+                       time();
+               char    *ctime();
+
+               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));
+       }
+
+       /*
+        * if database missing, we create it and do a dbminit;
+        * otherwise, just do the dbminit.
+        */
+       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);
        }
        }
-       exit (EX_OK);
+       exit(EX_OK);
 }
 }
-\f/*
-**  GETFROM -- read message from standard input and return sender
-**
-**     Parameters:
-**             none.
-**
-**     Returns:
-**             pointer to the sender address.
-**
-**     Side Effects:
-**             Reads first line from standard input.
-*/
 
 
-char *
-getfrom()
+/*
+ * getfrom --
+ *     read mail "From" line and return sender's address
+ */
+static char *
+getfrom(shortp)
+char **shortp;
 {
 {
-       static char line[MAXLINE];
-       register char *p;
-       extern char *index();
+       register char   *p;
+       char    buf[MAXLINE],
+               *malloc(), *strcpy();
 
        /* read the from line */
 
        /* read the from line */
-       if (fgets(line, sizeof line, stdin) == NULL ||
-           strncmp(line, "From ", 5) != NULL)
-       {
-               usrerr("No initial From line");
-               exit(EX_USAGE);
+       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 */
        }
 
        /* find the end of the sender address and terminate it */
-       p = index(&line[5], ' ');
-       if (p == NULL)
-       {
-               usrerr("Funny From line '%s'", line);
-               exit(EX_USAGE);
+       for (p = &buf[5]; *p && *p != ' '; ++p);
+       if (!*p) {
+               fprintf(stderr, "vacation: address terminated From line '%s'\n", buf);
+               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 = '!';
        }
        }
-       *p = '\0';
+       *at = saveat;
+#ifdef VDEBUG
+printf("place='%s'\n", *shortp);
+#endif
 
        /* return the sender address */
 
        /* return the sender address */
-       return (&line[5]);
+       return start;
 }
 }
-\f/*
-**  JUNKMAIL -- read the header and tell us if this is junk/bulk mail.
-**
-**     Parameters:
-**             from -- the Return-Path of the sender.  We assume that
-**                     anything from "*-REQUEST@*" is bulk mail.
-**
-**     Returns:
-**             TRUE -- if this is junk or bulk mail (that is, if the
-**                     sender shouldn't receive a response).
-**             FALSE -- if the sender deserves a response.
-**
-**     Side Effects:
-**             May read the header from standard input.  When this
-**             returns the position on stdin is undefined.
-*/
 
 
-bool
+/*
+ * junkmail --
+ *     read the header and return if automagic/junk/bulk mail
+ */
+static
 junkmail(from)
 junkmail(from)
-       char *from;
+       char    *from;
 {
 {
-       register char *p;
-       char buf[MAXLINE+1];
-       extern char *index();
-       extern char *rindex();
-       extern bool sameword();
-
-       /* test for inhuman sender */
-       p = rindex(from, '@');
-       if (p != NULL)
-       {
-               *p = '\0';
-               if (sameword(&p[-8],  "-REQUEST") ||
-                   sameword(&p[-10], "Postmaster") ||
-                   sameword(&p[-13], "MAILER-DAEMON"))
-               {
-                       *p = '@';
-                       return (TRUE);
+       static struct ignore {
+               char    *name;
+               int     len;
+       } ignore[] = {
+               "-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();
+
+       /*
+        * 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
+        *
+        * Therefore, the following search order:
+        */
+       if (!(p = index(from, '%')))
+               if (!(p = index(from, '@'))) {
+                       if (p = rindex(from, '!'))
+                               ++p;
+                       for (p = from; *p; ++p);
+               }
+       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);
                }
                }
-               *p = '@';
-       }
 
        /* read the header looking for a "Precedence:" line */
 
        /* read the header looking for a "Precedence:" line */
-       while (fgets(buf, MAXLINE, stdin) != NULL && buf[0] != '\n')
-       {
-               /* should ignore case, but this is reasonably safe */
-               if (strncmp(buf, "Precedence", 10) != 0 ||
-                   !(buf[10] == ':' || buf[10] == ' ' || buf[10] == '\t'))
-               {
+       while (gets(buf) && *buf) {
+               if (strncasecmp(buf, "Precedence", 10) ||
+                  buf[10] != ':' && buf[10] != ' ' && buf[10] != '\t')
                        continue;
                        continue;
-               }
 
                /* find the value of this field */
 
                /* find the value of this field */
-               p = index(buf, ':');
-               if (p == NULL)
+               if (!(p = index(buf, ':')))
                        continue;
                        continue;
-               while (*++p != '\0' && isspace(*p))
-                       continue;
-               if (*p == '\0')
+               while (*++p && isspace(*p));
+               if (!*p)
                        continue;
 
                /* see if it is "junk" or "bulk" */
                        continue;
 
                /* see if it is "junk" or "bulk" */
-               p[4] = '\0';
-               if (sameword(p, "junk") || sameword(p, "bulk"))
-                       return (TRUE);
+               if (!strncasecmp(p, "junk", 4) || !strncasecmp(p, "bulk", 4)) {
+                       if (debug)
+                               fprintf(stderr, "not sending to %s {junk/bulk}\n", from);
+                       return(YES);
+               }
        }
        }
-       return (FALSE);
+       return(NO);
 }
 }
-\f/*
-**  KNOWS -- predicate telling if user has already been informed.
-**
-**     Parameters:
-**             user -- the user who sent this message.
-**
-**     Returns:
-**             TRUE if 'user' has already been informed that the
-**                     recipient is on vacation.
-**             FALSE otherwise.
-**
-**     Side Effects:
-**             none.
-*/
 
 
-bool
+/*
+ * knows --
+ *     find out if user has gotten a vacation message recently.
+ */
+static
 knows(user)
 knows(user)
-       char *user;
+char *user;
 {
 {
-       DATUM k, d;
-       long now;
-       auto long then;
+       DATUM   k, d,
+               fetch();
+       time_t  now, then,
+               time();
 
 
-       time(&now);
        k.dptr = user;
        k.dsize = strlen(user) + 1;
        d = fetch(k);
        if (d.dptr == NULL)
        k.dptr = user;
        k.dsize = strlen(user) + 1;
        d = fetch(k);
        if (d.dptr == NULL)
-               return (FALSE);
-       
-       /* be careful on 68k's and others with alignment restrictions */
-       bcopy((char *) &((struct dbrec *) d.dptr)->sentdate, (char *) &then, sizeof then);
-       if (then + Timeout < now)
-               return (FALSE);
-       return (TRUE);
+               return FALSE;
+       bcopy(d.dptr, (char *)&ldbrec, sizeof ldbrec);  /* realign data */
+       return ldbrec.sentdate + Timeout >= time((time_t *)0);
 }
 }
-\f/*
-**  SETKNOWS -- set that this user knows about the vacation.
-**
-**     Parameters:
-**             user -- the user who should be marked.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             The dbm file is updated as appropriate.
-*/
 
 
-setknows(user)
-       char *user;
+#ifndef VMUNIX
+bcopy(from, to, size)
+register char *to, *from;
+register unsigned size;
 {
 {
-       DATUM k, d;
-       struct dbrec xrec;
+       while (size-- > 0)
+               *to++ = *from++;
+}
+#endif
+
+/*
+ * setknows --
+ *     store that this user knows about the vacation.
+ */
+static
+setknows(user, forever)
+       char    *user;
+       int     forever;
+{
+       DBREC   xrec;
+       DATUM   k, d;
+       time_t  time();
 
        k.dptr = user;
        k.dsize = strlen(user) + 1;
 
        k.dptr = user;
        k.dsize = strlen(user) + 1;
-       time(&xrec.sentdate);
-       d.dptr = (char *) &xrec;
-       d.dsize = sizeof xrec;
+       if (forever)
+               /* zero is the flag value meaning *never* reply */
+               xrec.sentdate = 0;
+       else
+               (void)time(&xrec.sentdate);
+       d.dptr = (char *)&xrec;
+       d.dsize = sizeof(xrec);
        store(k, d);
 }
        store(k, d);
 }
-\f/*
-**  SENDMESSAGE -- send a message to a particular user.
-**
-**     Parameters:
-**             msgf -- filename containing the message.
-**             user -- user who should receive it.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             sends mail to 'user' using /usr/lib/sendmail.
-*/
 
 
-sendmessage(msgf, user, myname)
-       char *msgf;
-       char *user;
-       char *myname;
+/*
+ * sendmessage --
+ *     exec sendmail to send the vacation file to "user".
+ */
+static
+sendmessage(user, myname)
+       char    *user, *myname;
 {
 {
-       FILE *f;
-
-       /* find the message to send */
-       f = freopen(msgf, "r", stdin);
-       if (f == NULL)
-       {
-               f = freopen("/usr/lib/vacation.def", "r", stdin);
-               if (f == NULL)
-                       syserr("No message to send");
+       if (debug) {
+               fprintf(stderr, "sending {%s} to {%s}\n", VMSG, user);
+               return;
+       }
+       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);
        }
        }
-
        execl("/usr/lib/sendmail", "sendmail", "-f", myname, user, NULL);
        execl("/usr/lib/sendmail", "sendmail", "-f", myname, user, NULL);
-       syserr("Cannot exec /usr/lib/sendmail");
+       fprintf(stderr, "vacation: can't exec /usr/lib/sendmail.\n");
+       syslog(LOG_ERR, "vacation: can't exec /usr/lib/sendmail.\n");
+       exit(EX_OSERR);
 }
 }
-\f/*
-**  INITIALIZE -- initialize the database before leaving for vacation
-**
-**     Parameters:
-**             none.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             Initializes the files .vacation.{pag,dir} in the
-**             caller's home directory.
-*/
 
 
+/*
+ * initialize --
+ *     initialize the database
+ */
+static
 initialize()
 {
 initialize()
 {
-       char *homedir;
-       char buf[MAXLINE];
-       extern char *getenv();
-
-       setgid(getgid());
-       setuid(getuid());
-       homedir = getenv("HOME");
-       if (homedir == NULL)
-               syserr("No home!");
-       (void) strcpy(buf, homedir);
-       (void) strcat(buf, "/.vacation.dir");
-       if (close(creat(buf, 0644)) < 0)
-               syserr("Cannot create %s", buf);
-       (void) strcpy(buf, homedir);
-       (void) strcat(buf, "/.vacation.pag");
-       if (close(creat(buf, 0644)) < 0)
-               syserr("Cannot create %s", buf);
-}
-\f/*
-**  USRERR -- print user error
-**
-**     Parameters:
-**             f -- format.
-**             p -- first parameter.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             none.
-*/
-
-usrerr(f, p)
-       char *f;
-       char *p;
-{
-       fprintf(stderr, "vacation: ");
-       _doprnt(f, &p, stderr);
-       fprintf(stderr, "\n");
-}
-\f/*
-**  SYSERR -- print system error
-**
-**     Parameters:
-**             f -- format.
-**             p -- first parameter.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             none.
-*/
-
-syserr(f, p)
-       char *f;
-       char *p;
-{
-       fprintf(stderr, "vacation: ");
-       _doprnt(f, &p, stderr);
-       fprintf(stderr, "\n");
-       exit(EX_USAGE);
-}
-\f/*
-**  NEWSTR -- copy a string
-**
-**     Parameters:
-**             s -- the string to copy.
-**
-**     Returns:
-**             A copy of the string.
-**
-**     Side Effects:
-**             none.
-*/
-
-char *
-newstr(s)
-       char *s;
-{
-       char *p;
-       extern char *malloc();
-
-       p = malloc(strlen(s) + 1);
-       if (p == NULL)
-       {
-               syserr("newstr: cannot alloc memory");
+       extern int      errno;
+       extern char     *sys_errlist[];
+       FILE    *fp;
+       int     fd;
+
+       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);
        }
                exit(EX_OSERR);
        }
-       strcpy(p, s);
-       return (p);
+       (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);
+       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;
 }
 }
-\f/*
-**  SAMEWORD -- return TRUE if the words are the same
-**
-**     Ignores case.
-**
-**     Parameters:
-**             a, b -- the words to compare.
-**
-**     Returns:
-**             TRUE if a & b match exactly (modulo case)
-**             FALSE otherwise.
-**
-**     Side Effects:
-**             none.
-*/
 
 
-bool
-sameword(a, b)
-       register char *a, *b;
+/*
+ * usage --
+ *     print out a usage message and die
+ */
+static
+usage()
 {
 {
-       char ca, cb;
-
-       do
-       {
-               ca = *a++;
-               cb = *b++;
-               if (isascii(ca) && isupper(ca))
-                       ca = ca - 'A' + 'a';
-               if (isascii(cb) && isupper(cb))
-                       cb = cb - 'A' + 'a';
-       } while (ca != '\0' && ca == cb);
-       return (ca == cb);
+       uid_t   getuid();
+
+       fputs("usage: vacation [-i] login\n", stderr);
+       syslog(LOG_ERR, "uid %u: usage: vacation [-i] login\n", getuid());
+       exit(EX_USAGE);
 }
 }