summaryrefslogtreecommitdiff
path: root/gnu/usr.sbin/sendmail/vacation
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2000-04-02 19:05:59 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2000-04-02 19:05:59 +0000
commit43225228859332051b0497d6732b906e2c753f85 (patch)
treee1545792a305da6620c54b122c51c207dd70accd /gnu/usr.sbin/sendmail/vacation
parent0b21c002091512c23501e805cd064cdc94f0a312 (diff)
stock sendmail 8.10.0 with $Id -> $Sendmail
Diffstat (limited to 'gnu/usr.sbin/sendmail/vacation')
-rw-r--r--gnu/usr.sbin/sendmail/vacation/Build13
-rw-r--r--gnu/usr.sbin/sendmail/vacation/Makefile17
-rw-r--r--gnu/usr.sbin/sendmail/vacation/Makefile.m419
-rw-r--r--gnu/usr.sbin/sendmail/vacation/vacation.0132
-rw-r--r--gnu/usr.sbin/sendmail/vacation/vacation.1194
-rw-r--r--gnu/usr.sbin/sendmail/vacation/vacation.c828
6 files changed, 1203 insertions, 0 deletions
diff --git a/gnu/usr.sbin/sendmail/vacation/Build b/gnu/usr.sbin/sendmail/vacation/Build
new file mode 100644
index 00000000000..aca2894e9ec
--- /dev/null
+++ b/gnu/usr.sbin/sendmail/vacation/Build
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Copyright (c) 1999 Sendmail, Inc. and its suppliers.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set
+# forth in the LICENSE file which can be found at the top level of
+# the sendmail distribution.
+#
+#
+# $Sendmail: Build,v 8.2 1999/03/02 02:35:21 peterh Exp $
+
+exec ../devtools/bin/Build $*
diff --git a/gnu/usr.sbin/sendmail/vacation/Makefile b/gnu/usr.sbin/sendmail/vacation/Makefile
new file mode 100644
index 00000000000..b57df04a6ef
--- /dev/null
+++ b/gnu/usr.sbin/sendmail/vacation/Makefile
@@ -0,0 +1,17 @@
+# $Sendmail: Makefile,v 8.5 1999/09/23 22:36:45 ca Exp $
+
+SHELL= /bin/sh
+BUILD= ./Build
+OPTIONS= $(CONFIG) $(FLAGS)
+
+all: FRC
+ $(SHELL) $(BUILD) $(OPTIONS) $@
+clean: FRC
+ $(SHELL) $(BUILD) $(OPTIONS) $@
+install: FRC
+ $(SHELL) $(BUILD) $(OPTIONS) $@
+
+fresh: FRC
+ $(SHELL) $(BUILD) $(OPTIONS) -c
+
+FRC:
diff --git a/gnu/usr.sbin/sendmail/vacation/Makefile.m4 b/gnu/usr.sbin/sendmail/vacation/Makefile.m4
new file mode 100644
index 00000000000..71430eb2c1b
--- /dev/null
+++ b/gnu/usr.sbin/sendmail/vacation/Makefile.m4
@@ -0,0 +1,19 @@
+include(confBUILDTOOLSDIR`/M4/switch.m4')
+
+# sendmail dir
+SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail')
+PREPENDDEF(`confENVDEF', `confMAPDEF')
+PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ')
+
+bldPRODUCT_START(`executable', `vacation')
+define(`bldSOURCES', `vacation.c ')
+bldPUSH_SMLIB(`smutil')
+bldPUSH_SMLIB(`smdb')
+APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL')
+bldPRODUCT_END
+
+bldPRODUCT_START(`manpage', `vacation')
+define(`bldSOURCES', `vacation.1')
+bldPRODUCT_END
+
+bldFINISH
diff --git a/gnu/usr.sbin/sendmail/vacation/vacation.0 b/gnu/usr.sbin/sendmail/vacation/vacation.0
new file mode 100644
index 00000000000..857d4b92e34
--- /dev/null
+++ b/gnu/usr.sbin/sendmail/vacation/vacation.0
@@ -0,0 +1,132 @@
+
+
+
+VACATION(1) VACATION(1)
+
+
+NNAAMMEE
+ vvaaccaattiioonn - return ``I am not here'' indication
+
+SSYYNNOOPPSSIISS
+ vvaaccaattiioonn --ii [--rr _i_n_t_e_r_v_a_l] [--xx] vvaaccaattiioonn [--aa _a_l_i_a_s] [--ff
+ _d_a_t_a_b_a_s_e] [--mm _m_e_s_s_a_g_e] [--ss _a_d_d_r_e_s_s] [--zz] _l_o_g_i_n
+
+DDEESSCCRRIIPPTTIIOONN
+ VVaaccaattiioonn 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 _._f_o_r_w_a_r_d file. For example, your
+ _._f_o_r_w_a_r_d file might have:
+
+ \eric, "|/usr/bin/vacation -a allman eric"
+
+ which would send messages to you (assuming your login name
+ was eric) and reply to any messages for ``eric'' or ``all-
+ man''.
+
+ Available options:
+
+ --aa _a_l_i_a_s
+ Handle messages for in the same manner as those
+ received for the user's login name.
+
+ --ff _f_i_l_e_n_a_m_e
+ Use _f_i_l_e_n_a_m_e as name of the database instead of
+ _~_/_._v_a_c_a_t_i_o_n_._d_b. Unless the _f_i_l_e_n_a_m_e starts with /
+ it is relative to ~.
+
+ --ii Initialize the vacation database files. It should
+ be used before you modify your _._f_o_r_w_a_r_d file.
+
+ --mm _f_i_l_e_n_a_m_e
+ Use _f_i_l_e_n_a_m_e as name of the file containing the
+ message to send instead of _~_/_._v_a_c_a_t_i_o_n_._m_s_g. Unless
+ the _f_i_l_e_n_a_m_e starts with / it is relative to ~.
+
+ --rr _i_n_t_e_r_v_a_l
+ Set the reply interval to _i_n_t_e_r_v_a_l days. The
+ default is one week. An interval of ``0'' or
+ ``infinite'' (actually, any non-numeric character)
+ will never send more than one reply.
+
+ --ss _a_d_d_r_e_s_s
+ Use _a_d_d_r_e_s_s instead of the sender address in the
+ _F_r_o_m line to determine the reply address.
+
+ --xx reads an exclusion list from stdin (one address per
+ line). Mails coming from an address in this exclu-
+ sion list won't get a reply by vvaaccaattiioonn. It is
+ possible to exclude complete domains by specifying
+ ``@domain'' as element of the exclusion list.
+
+
+
+
+ $Date: 2000/04/02 19:05:58 $ 1
+
+
+
+
+
+VACATION(1) VACATION(1)
+
+
+ --zz Set the sender of the vacation message to ``<>''
+ instead of the user. This probably violates the
+ RFCs since vacation messages are not required by a
+ standards-track RFC to have a null reverse-path.
+
+ No message will be sent unless _l_o_g_i_n (or an _a_l_i_a_s supplied
+ using the --aa 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 a db(3) database in the
+ file _._v_a_c_a_t_i_o_n_._d_b in your home directory.
+
+ VVaaccaattiioonn expects a file _._v_a_c_a_t_i_o_n_._m_s_g, in your home direc-
+ tory, containing a message to be sent back to each sender.
+ It should be an entire message (including headers). For
+ example, it might contain:
+
+ From: eric@CS.Berkeley.EDU (Eric Allman)
+ Subject: I am on vacation
+ Delivered-By-The-Graces-Of: The Vacation program
+ Precedence: bulk
+
+ I am on vacation until July 22. If you have something urgent,
+ please contact Keith Bostic <bostic@CS.Berkeley.EDU>.
+ --eric
+
+ VVaaccaattiioonn reads the first line from the standard input for
+ a UNIX ``From'' line to determine the sender. Sendmail(8)
+ includes this ``From'' line automatically.
+
+ Fatal errors, such as calling vvaaccaattiioonn with incorrect
+ arguments, or with non-existent _l_o_g_i_ns, are logged in the
+ system log file, using syslog(8).
+
+FFIILLEESS
+ ~/.vacation.db database file
+
+ ~/.vacation.msg message to send
+
+SSEEEE AALLSSOO
+ sendmail(8), syslog(8)
+
+HHIISSTTOORRYY
+ The vvaaccaattiioonn command appeared in 4.3BSD.
+
+
+
+
+
+
+
+
+
+ $Date: 2000/04/02 19:05:58 $ 2
+
+
diff --git a/gnu/usr.sbin/sendmail/vacation/vacation.1 b/gnu/usr.sbin/sendmail/vacation/vacation.1
new file mode 100644
index 00000000000..506765cd2d0
--- /dev/null
+++ b/gnu/usr.sbin/sendmail/vacation/vacation.1
@@ -0,0 +1,194 @@
+.\" Copyright (c) 1999 Sendmail, Inc. and its suppliers.
+.\" All rights reserved.
+.\" Copyright (c) 1985, 1987, 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\"
+.\" By using this file, you agree to the terms and conditions set
+.\" forth in the LICENSE file which can be found at the top level of
+.\" the sendmail distribution.
+.\"
+.\"
+.\" $Sendmail: vacation.1,v 8.9 1999/10/27 03:42:07 ca Exp $
+.\"
+.TH VACATION 1 "$Date: 2000/04/02 19:05:58 $"
+.SH NAME
+.B vacation
+\- return ``I am not here'' indication
+.SH SYNOPSIS
+.B vacation
+.B \-i
+.RB [ \-r
+.IR interval ]
+.RB [ \-x ]
+.B vacation
+.RB [ \-a
+.IR alias ]
+.RB [ \-f
+.IR database ]
+.RB [ \-m
+.IR message ]
+.RB [ \-s
+.IR address ]
+.RB [ \-z ]
+.I login
+.SH DESCRIPTION
+.B 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:
+.IP
+\eeric, "|/usr/bin/vacation -a allman eric"
+.PP
+which would send messages to you (assuming your login name was eric) and
+reply to any messages for
+``eric''
+or
+``allman''.
+.PP
+Available options:
+.TP
+.BI \-a " alias"
+Handle messages for
+.Ar alias
+in the same manner as those received for the user's
+login name.
+.TP
+.BI \-f " filename"
+Use
+.I filename
+as name of the database instead of
+.IR ~/.vacation.db .
+Unless the
+.I filename
+starts with / it is relative to ~.
+.TP
+.B \-i
+Initialize the vacation database files. It should be used
+before you modify your
+.I .forward
+file.
+.TP
+.BI \-m " filename"
+Use
+.I filename
+as name of the file containing the message to send instead of
+.IR ~/.vacation.msg .
+Unless the
+.I filename
+starts with / it is relative to ~.
+.TP
+.BI \-r " interval"
+Set the reply interval to
+.I interval
+days. The default is one week.
+An interval of ``0'' or
+``infinite''
+(actually, any non-numeric character) will never send more than
+one reply.
+.TP
+.BI \-s " address"
+Use
+.I address
+instead of the sender address in the
+.I From
+line to determine the reply address.
+.TP
+.B \-x
+reads an exclusion list from stdin (one address per line).
+Mails coming from an address
+in this exclusion list won't get a reply by
+.BR vacation .
+It is possible to exclude complete domains by specifying
+``@domain''
+as element of the exclusion list.
+.TP
+.B \-z
+Set the sender of the vacation message to
+``<>''
+instead of the user.
+This probably violates the RFCs since vacation messages are
+not required by a standards-track RFC to have a null reverse-path.
+.PP
+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 a
+db(3)
+database in the file
+.I .vacation.db
+in your home directory.
+.PP
+.B 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:
+.IP
+.nf
+From: eric@CS.Berkeley.EDU (Eric Allman)
+Subject: I am on vacation
+Delivered-By-The-Graces-Of: The Vacation program
+Precedence: bulk
+
+I am on vacation until July 22. If you have something urgent,
+please contact Keith Bostic <bostic@CS.Berkeley.EDU>.
+--eric
+.fi
+.PP
+.B Vacation
+reads the first line from the standard input for a
+UNIX
+``From''
+line to determine the sender.
+Sendmail(8)
+includes this
+``From''
+line automatically.
+.PP
+Fatal errors, such as calling
+.B vacation
+with incorrect arguments, or with non-existent
+.IR login s,
+are logged in the system log file, using
+syslog(8).
+.SH FILES
+.TP 1.8i
+~/.vacation.db
+database file
+.TP
+~/.vacation.msg
+message to send
+.SH SEE ALSO
+sendmail(8),
+syslog(8)
+.SH HISTORY
+The
+.B vacation
+command appeared in
+4.3BSD.
diff --git a/gnu/usr.sbin/sendmail/vacation/vacation.c b/gnu/usr.sbin/sendmail/vacation/vacation.c
new file mode 100644
index 00000000000..8602d801f08
--- /dev/null
+++ b/gnu/usr.sbin/sendmail/vacation/vacation.c
@@ -0,0 +1,828 @@
+/*
+ * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ * Copyright (c) 1983, 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1983 Eric P. Allman. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ *
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.\n\
+ All rights reserved.\n\
+ Copyright (c) 1983, 1987, 1993\n\
+ The Regents of the University of California. All rights reserved.\n\
+ Copyright (c) 1983 Eric P. Allman. All rights reserved.\n";
+#endif /* ! lint */
+
+#ifndef lint
+static char id[] = "@(#)$Sendmail: vacation.c,v 8.63 2000/02/01 05:50:00 gshapiro Exp $";
+#endif /* ! lint */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+#ifdef EX_OK
+# undef EX_OK /* unistd.h may have another use for this */
+#endif /* EX_OK */
+#include <sysexits.h>
+
+#if defined(sun) && !defined(BSD) && !defined(SOLARIS)
+# include <pathname.h>
+#endif /* sun && ! BSD && ! SOLARIS */
+
+#include "sendmail/sendmail.h"
+#include "libsmdb/smdb.h"
+
+#if defined(__hpux) && !defined(HPUX11)
+# undef syslog /* Undo hard_syslog conf.h change */
+#endif /* defined(__hpux) && !defined(HPUX11) */
+
+#ifndef _PATH_SENDMAIL
+# define _PATH_SENDMAIL "/usr/lib/sendmail"
+#endif /* ! _PATH_SENDMAIL */
+
+#define ONLY_ONCE ((time_t) 0) /* send at most one reply */
+#define INTERVAL_UNDEF ((time_t) (-1)) /* no value given */
+
+uid_t RealUid;
+gid_t RealGid;
+char *RealUserName;
+uid_t RunAsUid;
+uid_t RunAsGid;
+char *RunAsUserName;
+int Verbose = 2;
+bool DontInitGroups = FALSE;
+uid_t TrustedUid = 0;
+BITMAP256 DontBlameSendmail;
+
+/*
+** 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 VDB ".vacation" /* vacation database */
+#define VMSG ".vacation.msg" /* vacation message */
+#define SECSPERDAY (60 * 60 * 24)
+#define DAYSPERWEEK 7
+
+#ifndef TRUE
+# define TRUE 1
+# define FALSE 0
+#endif /* ! TRUE */
+
+#ifndef __P
+# ifdef __STDC__
+# define __P(protos) protos
+# else /* __STDC__ */
+# define __P(protos) ()
+# define const
+# endif /* __STDC__ */
+#endif /* ! __P */
+
+typedef struct alias
+{
+ char *name;
+ struct alias *next;
+} ALIAS;
+
+ALIAS *Names = NULL;
+
+SMDB_DATABASE *Db;
+
+char From[MAXLINE];
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ bool iflag, emptysender, exclude;
+ int ch;
+ int result;
+ time_t interval;
+ struct passwd *pw;
+ ALIAS *cur;
+ char *dbfilename = VDB;
+ char *msgfilename = VMSG;
+ SMDB_USER_INFO user_info;
+ static char rnamebuf[MAXNAME];
+ extern int optind, opterr;
+ extern char *optarg;
+ extern void usage __P((void));
+ extern void setinterval __P((time_t));
+ extern void readheaders __P((void));
+ extern bool recent __P((void));
+ extern void setreply __P((char *, time_t));
+ extern void sendmessage __P((char *, char *, bool));
+ extern void xclude __P((FILE *));
+
+ /* Vars needed to link with smutil */
+ clrbitmap(DontBlameSendmail);
+ RunAsUid = RealUid = getuid();
+ RunAsGid = RealGid = getgid();
+ pw = getpwuid(RealUid);
+ if (pw != NULL)
+ {
+ if (strlen(pw->pw_name) > MAXNAME - 1)
+ pw->pw_name[MAXNAME] = '\0';
+ snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name);
+ }
+ else
+ snprintf(rnamebuf, sizeof rnamebuf,
+ "Unknown UID %d", (int) RealUid);
+ RunAsUserName = RealUserName = rnamebuf;
+
+#ifdef LOG_MAIL
+ openlog("vacation", LOG_PID, LOG_MAIL);
+#else /* LOG_MAIL */
+ openlog("vacation", LOG_PID);
+#endif /* LOG_MAIL */
+
+ opterr = 0;
+ iflag = FALSE;
+ emptysender = FALSE;
+ exclude = FALSE;
+ interval = INTERVAL_UNDEF;
+ *From = '\0';
+ while ((ch = getopt(argc, argv, "a:f:Iim:r:s:xz")) != -1)
+ {
+ switch((char)ch)
+ {
+ case 'a': /* alias */
+ cur = (ALIAS *)malloc((u_int)sizeof(ALIAS));
+ if (cur == NULL)
+ {
+ syslog(LOG_NOTICE,
+ "vacation: can't allocate memory for alias %s.\n",
+ optarg);
+ break;
+ }
+ cur->name = optarg;
+ cur->next = Names;
+ Names = cur;
+ break;
+
+ case 'f': /* alternate database */
+ dbfilename = optarg;
+ break;
+
+ case 'I': /* backward compatible */
+ case 'i': /* init the database */
+ iflag = TRUE;
+ break;
+
+ case 'm': /* alternate message file */
+ msgfilename = optarg;
+ break;
+
+ case 'r':
+ if (isascii(*optarg) && isdigit(*optarg))
+ {
+ interval = atol(optarg) * SECSPERDAY;
+ if (interval < 0)
+ usage();
+ }
+ else
+ interval = ONLY_ONCE;
+ break;
+
+ case 's': /* alternate sender name */
+ (void) strlcpy(From, optarg, sizeof From);
+ break;
+
+ case 't': /* SunOS: -t1d (default expire) */
+ break;
+
+ case 'x':
+ exclude = TRUE;
+ break;
+
+ case 'z':
+ emptysender = TRUE;
+ break;
+
+ case '?':
+ default:
+ usage();
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ {
+ if (!iflag && !exclude)
+ usage();
+ if ((pw = getpwuid(getuid())) == NULL)
+ {
+ syslog(LOG_ERR,
+ "vacation: no such user uid %u.\n", getuid());
+ exit(EX_NOUSER);
+ }
+ }
+ else if ((pw = getpwnam(*argv)) == NULL)
+ {
+ syslog(LOG_ERR, "vacation: no such user %s.\n", *argv);
+ exit(EX_NOUSER);
+ }
+ if (chdir(pw->pw_dir) != 0)
+ {
+ syslog(LOG_NOTICE,
+ "vacation: no such directory %s.\n", pw->pw_dir);
+ exit(EX_NOINPUT);
+ }
+ user_info.smdbu_id = pw->pw_uid;
+ user_info.smdbu_group_id = pw->pw_gid;
+ (void) strlcpy(user_info.smdbu_name, pw->pw_name,
+ SMDB_MAX_USER_NAME_LEN);
+
+ result = smdb_open_database(&Db, dbfilename,
+ O_CREAT|O_RDWR | (iflag ? O_TRUNC : 0),
+ S_IRUSR|S_IWUSR, SFF_CREAT,
+ SMDB_TYPE_DEFAULT, &user_info, NULL);
+ if (result != SMDBE_OK)
+ {
+ syslog(LOG_NOTICE, "vacation: %s: %s\n", dbfilename,
+ errstring(result));
+ exit(EX_DATAERR);
+ }
+
+ if (interval != INTERVAL_UNDEF)
+ setinterval(interval);
+
+ if (iflag)
+ {
+ result = Db->smdb_close(Db);
+ if (!exclude)
+ exit(EX_OK);
+ }
+
+ if (exclude)
+ {
+ xclude(stdin);
+ result = Db->smdb_close(Db);
+ exit(EX_OK);
+ }
+
+ if ((cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))) == NULL)
+ {
+ syslog(LOG_NOTICE,
+ "vacation: can't allocate memory for username.\n");
+ exit(EX_OSERR);
+ }
+ cur->name = pw->pw_name;
+ cur->next = Names;
+ Names = cur;
+
+ readheaders();
+ if (!recent())
+ {
+ time_t now;
+
+ (void) time(&now);
+ setreply(From, now);
+ result = Db->smdb_close(Db);
+ sendmessage(pw->pw_name, msgfilename, emptysender);
+ }
+ else
+ result = Db->smdb_close(Db);
+ exit(EX_OK);
+ /* NOTREACHED */
+ return EX_OK;
+}
+
+/*
+** READHEADERS -- read mail headers
+**
+** Parameters:
+** none.
+**
+** Returns:
+** nothing.
+**
+*/
+void
+readheaders()
+{
+ bool tome, cont;
+ register char *p;
+ register ALIAS *cur;
+ char buf[MAXLINE];
+ extern bool junkmail __P((char *));
+ extern bool nsearch __P((char *, char *));
+
+ cont = tome = FALSE;
+ while (!tome && fgets(buf, sizeof(buf), stdin) && *buf != '\n')
+ {
+ switch(*buf)
+ {
+ case 'F': /* "From " */
+ cont = FALSE;
+ if (strncmp(buf, "From ", 5) == 0)
+ {
+ bool quoted = FALSE;
+
+ p = buf + 5;
+ while (*p != '\0')
+ {
+ /* escaped character */
+ if (*p == '\\')
+ {
+ p++;
+ if (*p == '\0')
+ {
+ syslog(LOG_NOTICE,
+ "vacation: badly formatted \"From \" line.\n");
+ exit(EX_DATAERR);
+ }
+ }
+ else if (*p == '"')
+ quoted = !quoted;
+ else if (*p == '\r' || *p == '\n')
+ break;
+ else if (*p == ' ' && !quoted)
+ break;
+ p++;
+ }
+ if (quoted)
+ {
+ syslog(LOG_NOTICE,
+ "vacation: badly formatted \"From \" line.\n");
+ exit(EX_DATAERR);
+ }
+ *p = '\0';
+
+ /* ok since both strings have MAXLINE length */
+ if (*From == '\0')
+ (void)strlcpy(From, buf + 5,
+ sizeof From);
+ if ((p = strchr(buf + 5, '\n')) != NULL)
+ *p = '\0';
+ if (junkmail(buf + 5))
+ exit(EX_OK);
+ }
+ break;
+
+ case 'P': /* "Precedence:" */
+ case 'p':
+ cont = FALSE;
+ if (strlen(buf) <= 10 ||
+ strncasecmp(buf, "Precedence", 10) != 0 ||
+ (buf[10] != ':' && buf[10] != ' ' &&
+ buf[10] != '\t'))
+ break;
+ if ((p = strchr(buf, ':')) == NULL)
+ break;
+ while (*++p != '\0' && isascii(*p) && isspace(*p));
+ if (*p == '\0')
+ break;
+ if (strncasecmp(p, "junk", 4) == 0 ||
+ strncasecmp(p, "bulk", 4) == 0 ||
+ strncasecmp(p, "list", 4) == 0)
+ exit(EX_OK);
+ break;
+
+ case 'C': /* "Cc:" */
+ case 'c':
+ if (strncasecmp(buf, "Cc:", 3) != 0)
+ break;
+ cont = TRUE;
+ goto findme;
+
+ case 'T': /* "To:" */
+ case 't':
+ if (strncasecmp(buf, "To:", 3) != 0)
+ break;
+ cont = TRUE;
+ goto findme;
+
+ default:
+ if (!isascii(*buf) || !isspace(*buf) || !cont || tome)
+ {
+ cont = FALSE;
+ break;
+ }
+findme:
+ for (cur = Names;
+ !tome && cur != NULL;
+ cur = cur->next)
+ tome = nsearch(cur->name, buf);
+ }
+ }
+ if (!tome)
+ exit(EX_OK);
+ if (*From == '\0')
+ {
+ syslog(LOG_NOTICE, "vacation: no initial \"From \" line.\n");
+ exit(EX_DATAERR);
+ }
+}
+
+/*
+** NSEARCH --
+** do a nice, slow, search of a string for a substring.
+**
+** Parameters:
+** name -- name to search.
+** str -- string in which to search.
+**
+** Returns:
+** is name a substring of str?
+**
+*/
+bool
+nsearch(name, str)
+ register char *name, *str;
+{
+ register size_t len;
+ register char *s;
+
+ len = strlen(name);
+
+ for (s = str; *s != '\0'; ++s)
+ {
+ /*
+ ** Check to make sure that the string matches and
+ ** the previous character is not an alphanumeric and
+ ** the next character after the match is not an alphanumeric.
+ **
+ ** This prevents matching "eric" to "derick" while still
+ ** matching "eric" to "<eric+detail>".
+ */
+
+ if (tolower(*s) == tolower(*name) &&
+ strncasecmp(name, s, len) == 0 &&
+ (s == str || !isascii(*(s - 1)) || !isalnum(*(s - 1))) &&
+ (!isascii(*(s + len)) || !isalnum(*(s + len))))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+** JUNKMAIL --
+** read the header and return if automagic/junk/bulk/list mail
+**
+** Parameters:
+** from -- sender address.
+**
+** Returns:
+** is this some automated/junk/bulk/list mail?
+**
+*/
+bool
+junkmail(from)
+ char *from;
+{
+ register size_t len;
+ register char *p;
+ register struct ignore *cur;
+ static struct ignore
+ {
+ char *name;
+ size_t len;
+ } ignore[] =
+ {
+ { "-request", 8 },
+ { "postmaster", 10 },
+ { "uucp", 4 },
+ { "mailer-daemon", 13 },
+ { "mailer", 6 },
+ { "-relay", 6 },
+ { NULL, 0 }
+ };
+
+ /*
+ * 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:
+ *
+ * From site!site!SENDER%site.domain%site.domain@site.domain
+ */
+ if ((p = strchr(from, '%')) == NULL &&
+ (p = strchr(from, '@')) == NULL)
+ {
+ if ((p = strrchr(from, '!')) != NULL)
+ ++p;
+ else
+ p = from;
+ for (; *p; ++p)
+ continue;
+ }
+ len = p - from;
+ for (cur = ignore; cur->name != NULL; ++cur)
+ {
+ if (len >= cur->len &&
+ strncasecmp(cur->name, p - cur->len, cur->len) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#define VIT "__VACATION__INTERVAL__TIMER__"
+
+/*
+** RECENT --
+** find out if user has gotten a vacation message recently.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** TRUE iff user has gotten a vacation message recently.
+**
+*/
+bool
+recent()
+{
+ SMDB_DBENT key, data;
+ time_t then, next;
+ bool trydomain = FALSE;
+ int st;
+ char *domain;
+
+ memset(&key, '\0', sizeof key);
+ memset(&data, '\0', sizeof data);
+
+ /* get interval time */
+ key.data.data = VIT;
+ key.data.size = sizeof(VIT);
+
+ st = Db->smdb_get(Db, &key, &data, 0);
+ if (st != SMDBE_OK)
+ next = SECSPERDAY * DAYSPERWEEK;
+ else
+ memmove(&next, data.data.data, sizeof(next));
+
+ memset(&data, '\0', sizeof data);
+
+ /* get record for this address */
+ key.data.data = From;
+ key.data.size = strlen(From);
+
+ do
+ {
+ st = Db->smdb_get(Db, &key, &data, 0);
+ if (st == SMDBE_OK)
+ {
+ memmove(&then, data.data.data, sizeof(then));
+ if (next == ONLY_ONCE || then == ONLY_ONCE ||
+ then + next > time(NULL))
+ return TRUE;
+ }
+ if ((trydomain = !trydomain) &&
+ (domain = strchr(From, '@')) != NULL)
+ {
+ key.data.data = domain;
+ key.data.size = strlen(domain);
+ }
+ } while (trydomain);
+ return FALSE;
+}
+
+/*
+** SETINTERVAL --
+** store the reply interval
+**
+** Parameters:
+** interval -- time interval for replies.
+**
+** Returns:
+** nothing.
+**
+** Side Effects:
+** stores the reply interval in database.
+*/
+void
+setinterval(interval)
+ time_t interval;
+{
+ SMDB_DBENT key, data;
+
+ memset(&key, '\0', sizeof key);
+ memset(&data, '\0', sizeof data);
+
+ key.data.data = VIT;
+ key.data.size = sizeof(VIT);
+ data.data.data = (char*) &interval;
+ data.data.size = sizeof(interval);
+ (void)(Db->smdb_put)(Db, &key, &data, 0);
+}
+
+/*
+** SETREPLY --
+** store that this user knows about the vacation.
+**
+** Parameters:
+** from -- sender address.
+** when -- last reply time.
+**
+** Returns:
+** nothing.
+**
+** Side Effects:
+** stores user/time in database.
+*/
+void
+setreply(from, when)
+ char *from;
+ time_t when;
+{
+ SMDB_DBENT key, data;
+
+ memset(&key, '\0', sizeof key);
+ memset(&data, '\0', sizeof data);
+
+ key.data.data = from;
+ key.data.size = strlen(from);
+ data.data.data = (char*) &when;
+ data.data.size = sizeof(when);
+ (void)(Db->smdb_put)(Db, &key, &data, 0);
+}
+
+/*
+** XCLUDE --
+** add users to vacation db so they don't get a reply.
+**
+** Parameters:
+** f -- file pointer with list of address to exclude
+**
+** Returns:
+** nothing.
+**
+** Side Effects:
+** stores users in database.
+*/
+void
+xclude(f)
+ FILE *f;
+{
+ char buf[MAXLINE], *p;
+
+ if (f == NULL)
+ return;
+ while (fgets(buf, sizeof buf, f))
+ {
+ if ((p = strchr(buf, '\n')) != NULL)
+ *p = '\0';
+ setreply(buf, ONLY_ONCE);
+ }
+}
+
+/*
+** SENDMESSAGE --
+** exec sendmail to send the vacation file to sender
+**
+** Parameters:
+** myname -- user name.
+** msgfn -- name of file with vacation message.
+** emptysender -- use <> as sender address?
+**
+** Returns:
+** nothing.
+**
+** Side Effects:
+** sends vacation reply.
+*/
+void
+sendmessage(myname, msgfn, emptysender)
+ char *myname;
+ char *msgfn;
+ bool emptysender;
+{
+ FILE *mfp, *sfp;
+ int i;
+ int pvect[2];
+ char buf[MAXLINE];
+
+ mfp = fopen(msgfn, "r");
+ if (mfp == NULL)
+ {
+ if (msgfn[0] == '/')
+ syslog(LOG_NOTICE, "vacation: no %s file.\n", msgfn);
+ else
+ syslog(LOG_NOTICE, "vacation: no ~%s/%s file.\n",
+ myname, msgfn);
+ exit(EX_NOINPUT);
+ }
+ if (pipe(pvect) < 0)
+ {
+ syslog(LOG_ERR, "vacation: pipe: %s", errstring(errno));
+ exit(EX_OSERR);
+ }
+ i = fork();
+ if (i < 0)
+ {
+ syslog(LOG_ERR, "vacation: fork: %s", errstring(errno));
+ exit(EX_OSERR);
+ }
+ if (i == 0)
+ {
+ (void) dup2(pvect[0], 0);
+ (void) close(pvect[0]);
+ (void) close(pvect[1]);
+ (void) fclose(mfp);
+ if (emptysender)
+ myname = "<>";
+ (void) execl(_PATH_SENDMAIL, "sendmail", "-f", myname, "--",
+ From, NULL);
+ syslog(LOG_ERR, "vacation: can't exec %s: %s",
+ _PATH_SENDMAIL, errstring(errno));
+ exit(EX_UNAVAILABLE);
+ }
+ /* check return status of the following calls? XXX */
+ (void) close(pvect[0]);
+ if ((sfp = fdopen(pvect[1], "w")) != NULL)
+ {
+ (void) fprintf(sfp, "To: %s\n", From);
+ (void) fprintf(sfp, "Auto-Submitted: auto-generated\n");
+ while (fgets(buf, sizeof buf, mfp))
+ (void) fputs(buf, sfp);
+ (void) fclose(mfp);
+ (void) fclose(sfp);
+ }
+ else
+ {
+ (void) fclose(mfp);
+ syslog(LOG_ERR, "vacation: can't open pipe to sendmail");
+ exit(EX_UNAVAILABLE);
+ }
+}
+
+void
+usage()
+{
+ syslog(LOG_NOTICE, "uid %u: usage: vacation [-i] [-a alias] [-f db] [-m msg] [-r interval] [-s sender] [-x] [-z] login\n",
+ getuid());
+ exit(EX_USAGE);
+}
+
+/*VARARGS1*/
+void
+#ifdef __STDC__
+message(const char *msg, ...)
+#else /* __STDC__ */
+message(msg, va_alist)
+ const char *msg;
+ va_dcl
+#endif /* __STDC__ */
+{
+ const char *m;
+ VA_LOCAL_DECL
+
+ m = msg;
+ if (isascii(m[0]) && isdigit(m[0]) &&
+ isascii(m[1]) && isdigit(m[1]) &&
+ isascii(m[2]) && isdigit(m[2]) && m[3] == ' ')
+ m += 4;
+ VA_START(msg);
+ (void) vfprintf(stderr, m, ap);
+ VA_END;
+ (void) fprintf(stderr, "\n");
+}
+
+/*VARARGS1*/
+void
+#ifdef __STDC__
+syserr(const char *msg, ...)
+#else /* __STDC__ */
+syserr(msg, va_alist)
+ const char *msg;
+ va_dcl
+#endif /* __STDC__ */
+{
+ const char *m;
+ VA_LOCAL_DECL
+
+ m = msg;
+ if (isascii(m[0]) && isdigit(m[0]) &&
+ isascii(m[1]) && isdigit(m[1]) &&
+ isascii(m[2]) && isdigit(m[2]) && m[3] == ' ')
+ m += 4;
+ VA_START(msg);
+ (void) vfprintf(stderr, m, ap);
+ VA_END;
+ (void) fprintf(stderr, "\n");
+}
+
+void
+dumpfd(fd, printclosed, logit)
+ int fd;
+ bool printclosed;
+ bool logit;
+{
+ return;
+}