diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2000-04-02 19:05:59 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2000-04-02 19:05:59 +0000 |
commit | 43225228859332051b0497d6732b906e2c753f85 (patch) | |
tree | e1545792a305da6620c54b122c51c207dd70accd /gnu/usr.sbin/sendmail/vacation | |
parent | 0b21c002091512c23501e805cd064cdc94f0a312 (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/Build | 13 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/vacation/Makefile | 17 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/vacation/Makefile.m4 | 19 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/vacation/vacation.0 | 132 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/vacation/vacation.1 | 194 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/vacation/vacation.c | 828 |
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; +} |