diff options
Diffstat (limited to 'contrib/sendmail/vacation')
-rw-r--r-- | contrib/sendmail/vacation/Makefile | 17 | ||||
-rw-r--r-- | contrib/sendmail/vacation/Makefile.m4 | 23 | ||||
-rw-r--r-- | contrib/sendmail/vacation/vacation.1 | 285 | ||||
-rw-r--r-- | contrib/sendmail/vacation/vacation.c | 1180 |
4 files changed, 0 insertions, 1505 deletions
diff --git a/contrib/sendmail/vacation/Makefile b/contrib/sendmail/vacation/Makefile deleted file mode 100644 index 7cc577f..0000000 --- a/contrib/sendmail/vacation/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# $Id: 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/contrib/sendmail/vacation/Makefile.m4 b/contrib/sendmail/vacation/Makefile.m4 deleted file mode 100644 index 8979d5d..0000000 --- a/contrib/sendmail/vacation/Makefile.m4 +++ /dev/null @@ -1,23 +0,0 @@ -dnl $Id: Makefile.m4,v 8.26 2006/06/28 21:08:05 ca Exp $ -include(confBUILDTOOLSDIR`/M4/switch.m4') - -define(`confREQUIRE_LIBSM', `true') -define(`confREQUIRE_SM_OS_H', `true') -# 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(`sm') -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/contrib/sendmail/vacation/vacation.1 b/contrib/sendmail/vacation/vacation.1 deleted file mode 100644 index 6c1418a..0000000 --- a/contrib/sendmail/vacation/vacation.1 +++ /dev/null @@ -1,285 +0,0 @@ -.\" Copyright (c) 1999-2002 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. -.\" -.\" -.\" $Id: vacation.1,v 8.34 2002/06/27 23:51:52 ca Exp $ -.\" -.TH VACATION 1 "$Date: 2002/06/27 23:51:52 $" -.SH NAME -vacation -\- E-mail auto-responder -.SH SYNOPSIS -.B vacation -.RB [ \-a -.IR alias ] -.RB [ \-C -.IR cffile ] -.RB [ \-d ] -.RB [ \-f -.IR database ] -.RB [ \-i ] -.RB [ \-I ] -.RB [ \-j ] -.RB [ \-l ] -.RB [ \-m -.IR message ] -.RB [ \-R -.IR returnaddr ] -.RB [ \-r -.IR interval ] -.RB [ \-s -.IR address ] -.RB [ \-t -.IR time ] -.RB [ \-U ] -.RB [ \-x ] -.RB [ \-z ] -.I login -.SH DESCRIPTION -.B Vacation -returns a message, -.IR ~/.vacation.msg -by default, to the sender informing them that you are currently not -reading your mail. -The message is only sent to each sender once per reply interval (see -.B \-r -below). -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 -.I alias -in the same manner as those received for the user's -login name. -.TP -.BI \-C " cfpath" -Specify pathname of the sendmail configuration file. -This option is ignored if -.B \-U -is specified. -This option defaults to the standard sendmail configuration file, -located at /etc/mail/sendmail.cf on most systems. -.TP -.B \-d -Send error/debug messages to stderr instead of syslog. -Otherwise, 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). -This should only be used on the command line, not in your -.I .forward -file. -.TP -.BI \-f " filename" -Use -.I filename -as name of the database instead of -.IR ~/.vacation.db -or -.IR ~/.vacation.{dir,pag} . -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. -This should only be used on the command line, not in your -.I .forward -file. -.TP -.B \-I -Same as -.B \-i -(for backwards compatibility). -This should only be used on the command line, not in your -.I .forward -file. -.TP -.B \-j -Respond to the message regardless of whether the login is listed as -a recipient for the message. -Do not use this flag unless you are sure of the consequences. -For example, this will cause -.i vacation -to reply to mailing list messages which may result in removing -you from the list. -.TP -.B \-l -List the content of the vacation database file including the address -and the associated time of the last auto-response to that address. -This should only be used on the command line, not in 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 " returnaddr" -Set the reply envelope sender address -.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. -The -.B \-r -option should only be used when the vacation database is initialized -(see -.B \-i -above). -.TP -.BI \-s " address" -Use -.I address -instead of the incoming message sender address on the -.I From -line as the recipient for the vacation message. -.TP -.BI \-t " time" -Ignored, available only for compatibility with Sun's -vacation program. -.TP -.B \-U -Do not attempt to lookup -.I login -in the password file. -The -f and -m options must be used to specify the database and message file -since there is no home directory for the default settings for these options. -.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. -This should only be used on the command line, not in your -.I .forward -file. -.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 -.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 -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'', -``???-RELAY'', -``???-OWNER'', -``OWNER-???'', -``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) -or -dbm(3) -database in the file -.I .vacation.db -or -.I .vacation.{dir,pag} -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 -.SH FILES -.TP 1.8i -~/.vacation.db -default database file for db(3) -.TP 1.8i -~/.vacation.{dir,pag} -default database file for dbm(3) -.TP -~/.vacation.msg -default message to send -.SH SEE ALSO -sendmail(8), -syslog(8) -.SH HISTORY -The -.B vacation -command appeared in -4.3BSD. diff --git a/contrib/sendmail/vacation/vacation.c b/contrib/sendmail/vacation/vacation.c deleted file mode 100644 index 10712b8..0000000 --- a/contrib/sendmail/vacation/vacation.c +++ /dev/null @@ -1,1180 +0,0 @@ -/* - * Copyright (c) 1999-2002 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. - * - */ - -#include <sm/gen.h> - -SM_IDSTR(copyright, -"@(#) Copyright (c) 1999-2001 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") - -SM_IDSTR(id, "@(#)$Id: vacation.c,v 8.144 2007/05/11 18:50:36 ca Exp $") - - -#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 <sm/sysexits.h> - -#include <sm/cf.h> -#include <sm/mbdb.h> -#include "sendmail/sendmail.h" -#include <sendmail/pathnames.h> -#include "libsmdb/smdb.h" - -#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; -gid_t RunAsGid; -char *RunAsUserName; -int Verbose = 2; -bool DontInitGroups = false; -uid_t TrustedUid = 0; -BITMAP256 DontBlameSendmail; - -static int readheaders __P((bool)); -static bool junkmail __P((char *)); -static bool nsearch __P((char *, char *)); -static void usage __P((void)); -static void setinterval __P((time_t)); -static bool recent __P((void)); -static void setreply __P((char *, time_t)); -static void sendmessage __P((char *, char *, char *)); -static void xclude __P((SM_FILE_T *)); - -/* -** 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 - -typedef struct alias -{ - char *name; - struct alias *next; -} ALIAS; - -ALIAS *Names = NULL; - -SMDB_DATABASE *Db; - -char From[MAXLINE]; -bool CloseMBDB = false; - -#if defined(__hpux) || defined(__osf__) -# ifndef SM_CONF_SYSLOG_INT -# define SM_CONF_SYSLOG_INT 1 -# endif /* SM_CONF_SYSLOG_INT */ -#endif /* defined(__hpux) || defined(__osf__) */ - -#if SM_CONF_SYSLOG_INT -# define SYSLOG_RET_T int -# define SYSLOG_RET return 0 -#else /* SM_CONF_SYSLOG_INT */ -# define SYSLOG_RET_T void -# define SYSLOG_RET -#endif /* SM_CONF_SYSLOG_INT */ - -typedef SYSLOG_RET_T SYSLOG_T __P((int, const char *, ...)); -SYSLOG_T *msglog = syslog; -static SYSLOG_RET_T debuglog __P((int, const char *, ...)); -static void eatmsg __P((void)); -static void listdb __P((void)); - -/* exit after reading input */ -#define EXITIT(excode) \ -{ \ - eatmsg(); \ - if (CloseMBDB) \ - { \ - sm_mbdb_terminate(); \ - CloseMBDB = false; \ - } \ - return excode; \ -} - -#define EXITM(excode) \ -{ \ - if (!initdb && !list) \ - eatmsg(); \ - if (CloseMBDB) \ - { \ - sm_mbdb_terminate(); \ - CloseMBDB = false; \ - } \ - exit(excode); \ -} - -int -main(argc, argv) - int argc; - char **argv; -{ - bool alwaysrespond = false; - bool initdb, exclude; - bool runasuser = false; - bool list = false; - int mfail = 0, ufail = 0; - int ch; - int result; - long sff; - time_t interval; - struct passwd *pw; - ALIAS *cur; - char *dbfilename = NULL; - char *msgfilename = NULL; - char *cfpath = NULL; - char *name; - char *returnaddr = NULL; - SMDB_USER_INFO user_info; - static char rnamebuf[MAXNAME]; - extern int optind, opterr; - extern char *optarg; - - /* 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'; - sm_snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name); - } - else - sm_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; - initdb = false; - exclude = false; - interval = INTERVAL_UNDEF; - *From = '\0'; - - -#define OPTIONS "a:C:df:Iijlm:R:r:s:t:Uxz" - - while (mfail == 0 && ufail == 0 && - (ch = getopt(argc, argv, OPTIONS)) != -1) - { - switch((char)ch) - { - case 'a': /* alias */ - cur = (ALIAS *) malloc((unsigned int) sizeof(ALIAS)); - if (cur == NULL) - { - mfail++; - break; - } - cur->name = optarg; - cur->next = Names; - Names = cur; - break; - - case 'C': - cfpath = optarg; - break; - - case 'd': /* debug mode */ - msglog = debuglog; - break; - - case 'f': /* alternate database */ - dbfilename = optarg; - break; - - case 'I': /* backward compatible */ - case 'i': /* init the database */ - initdb = true; - break; - - case 'j': - alwaysrespond = true; - break; - - case 'l': - list = true; /* list the database */ - break; - - case 'm': /* alternate message file */ - msgfilename = optarg; - break; - - case 'R': - returnaddr = optarg; - break; - - case 'r': - if (isascii(*optarg) && isdigit(*optarg)) - { - interval = atol(optarg) * SECSPERDAY; - if (interval < 0) - ufail++; - } - else - interval = ONLY_ONCE; - break; - - case 's': /* alternate sender name */ - (void) sm_strlcpy(From, optarg, sizeof From); - break; - - case 't': /* SunOS: -t1d (default expire) */ - break; - - case 'U': /* run as single user mode */ - runasuser = true; - break; - - case 'x': - exclude = true; - break; - - case 'z': - returnaddr = "<>"; - break; - - case '?': - default: - ufail++; - break; - } - } - argc -= optind; - argv += optind; - - if (mfail != 0) - { - msglog(LOG_NOTICE, - "vacation: can't allocate memory for alias.\n"); - EXITM(EX_TEMPFAIL); - } - if (ufail != 0) - usage(); - - if (argc != 1) - { - if (!initdb && !list && !exclude) - usage(); - if ((pw = getpwuid(getuid())) == NULL) - { - msglog(LOG_ERR, - "vacation: no such user uid %u.\n", getuid()); - EXITM(EX_NOUSER); - } - name = pw->pw_name; - user_info.smdbu_id = pw->pw_uid; - user_info.smdbu_group_id = pw->pw_gid; - (void) sm_strlcpy(user_info.smdbu_name, pw->pw_name, - SMDB_MAX_USER_NAME_LEN); - if (chdir(pw->pw_dir) != 0) - { - msglog(LOG_NOTICE, - "vacation: no such directory %s.\n", - pw->pw_dir); - EXITM(EX_NOINPUT); - } - } - else if (runasuser) - { - name = *argv; - if (dbfilename == NULL || msgfilename == NULL) - { - msglog(LOG_NOTICE, - "vacation: -U requires setting both -f and -m\n"); - EXITM(EX_NOINPUT); - } - user_info.smdbu_id = pw->pw_uid; - user_info.smdbu_group_id = pw->pw_gid; - (void) sm_strlcpy(user_info.smdbu_name, pw->pw_name, - SMDB_MAX_USER_NAME_LEN); - } - else - { - int err; - SM_CF_OPT_T mbdbname; - SM_MBDB_T user; - - cfpath = getcfname(0, 0, SM_GET_SENDMAIL_CF, cfpath); - mbdbname.opt_name = "MailboxDatabase"; - mbdbname.opt_val = "pw"; - (void) sm_cf_getopt(cfpath, 1, &mbdbname); - err = sm_mbdb_initialize(mbdbname.opt_val); - if (err != EX_OK) - { - msglog(LOG_ERR, - "vacation: can't open mailbox database: %s.\n", - sm_strexit(err)); - EXITM(err); - } - CloseMBDB = true; - err = sm_mbdb_lookup(*argv, &user); - if (err == EX_NOUSER) - { - msglog(LOG_ERR, "vacation: no such user %s.\n", *argv); - EXITM(EX_NOUSER); - } - if (err != EX_OK) - { - msglog(LOG_ERR, - "vacation: can't read mailbox database: %s.\n", - sm_strexit(err)); - EXITM(err); - } - name = user.mbdb_name; - if (chdir(user.mbdb_homedir) != 0) - { - msglog(LOG_NOTICE, - "vacation: no such directory %s.\n", - user.mbdb_homedir); - EXITM(EX_NOINPUT); - } - user_info.smdbu_id = user.mbdb_uid; - user_info.smdbu_group_id = user.mbdb_gid; - (void) sm_strlcpy(user_info.smdbu_name, user.mbdb_name, - SMDB_MAX_USER_NAME_LEN); - } - - if (dbfilename == NULL) - dbfilename = VDB; - if (msgfilename == NULL) - msgfilename = VMSG; - - sff = SFF_CREAT; - if (getegid() != getgid()) - { - /* Allow a set-group-ID vacation binary */ - RunAsGid = user_info.smdbu_group_id = getegid(); - sff |= SFF_OPENASROOT; - } - if (getuid() == 0) - { - /* Allow root to initialize user's vacation databases */ - sff |= SFF_OPENASROOT|SFF_ROOTOK; - - /* ... safely */ - sff |= SFF_NOSLINK|SFF_NOHLINK|SFF_REGONLY; - } - - - result = smdb_open_database(&Db, dbfilename, - O_CREAT|O_RDWR | (initdb ? O_TRUNC : 0), - S_IRUSR|S_IWUSR, sff, - SMDB_TYPE_DEFAULT, &user_info, NULL); - if (result != SMDBE_OK) - { - msglog(LOG_NOTICE, "vacation: %s: %s\n", dbfilename, - sm_errstring(result)); - EXITM(EX_DATAERR); - } - - if (list) - { - listdb(); - (void) Db->smdb_close(Db); - exit(EX_OK); - } - - if (interval != INTERVAL_UNDEF) - setinterval(interval); - - if (initdb && !exclude) - { - (void) Db->smdb_close(Db); - exit(EX_OK); - } - - if (exclude) - { - xclude(smioin); - (void) Db->smdb_close(Db); - EXITM(EX_OK); - } - - if ((cur = (ALIAS *) malloc((unsigned int) sizeof(ALIAS))) == NULL) - { - msglog(LOG_NOTICE, - "vacation: can't allocate memory for username.\n"); - (void) Db->smdb_close(Db); - EXITM(EX_OSERR); - } - cur->name = name; - cur->next = Names; - Names = cur; - - result = readheaders(alwaysrespond); - if (result == EX_OK && !recent()) - { - time_t now; - - (void) time(&now); - setreply(From, now); - (void) Db->smdb_close(Db); - sendmessage(name, msgfilename, returnaddr); - } - else - (void) Db->smdb_close(Db); - if (result == EX_NOUSER) - result = EX_OK; - exit(result); -} - -/* -** EATMSG -- read stdin till EOF -** -** Parameters: -** none. -** -** Returns: -** nothing. -** -*/ - -static void -eatmsg() -{ - /* - ** read the rest of the e-mail and ignore it to avoid problems - ** with EPIPE in sendmail - */ - while (getc(stdin) != EOF) - continue; -} - -/* -** READHEADERS -- read mail headers -** -** Parameters: -** alwaysrespond -- respond regardless of whether msg is to me -** -** Returns: -** a exit code: NOUSER if no reply, OK if reply, * if error -** -** Side Effects: -** may exit(). -** -*/ - -static int -readheaders(alwaysrespond) - bool alwaysrespond; -{ - bool tome, cont; - register char *p; - register ALIAS *cur; - char buf[MAXLINE]; - - cont = false; - tome = alwaysrespond; - while (sm_io_fgets(smioin, SM_TIME_DEFAULT, buf, sizeof(buf)) && - *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') - { - msglog(LOG_NOTICE, - "vacation: badly formatted \"From \" line.\n"); - EXITIT(EX_DATAERR); - } - } - else if (*p == '"') - quoted = !quoted; - else if (*p == '\r' || *p == '\n') - break; - else if (*p == ' ' && !quoted) - break; - p++; - } - if (quoted) - { - msglog(LOG_NOTICE, - "vacation: badly formatted \"From \" line.\n"); - EXITIT(EX_DATAERR); - } - *p = '\0'; - - /* ok since both strings have MAXLINE length */ - if (*From == '\0') - (void) sm_strlcpy(From, buf + 5, - sizeof From); - if ((p = strchr(buf + 5, '\n')) != NULL) - *p = '\0'; - if (junkmail(buf + 5)) - EXITIT(EX_NOUSER); - } - 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) - EXITIT(EX_NOUSER); - 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) - EXITIT(EX_NOUSER); - if (*From == '\0') - { - msglog(LOG_NOTICE, "vacation: no initial \"From \" line.\n"); - EXITIT(EX_DATAERR); - } - EXITIT(EX_OK); -} - -/* -** 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? -** -*/ - -static 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? -** -*/ - -struct ignore -{ - char *name; - size_t len; -}; - -typedef struct ignore IGNORE_T; - -#define MAX_USER_LEN 256 /* maximum length of local part (sender) */ - -/* delimiters for the local part of an address */ -#define isdelim(c) ((c) == '%' || (c) == '@' || (c) == '+') - -static bool -junkmail(from) - char *from; -{ - bool quot; - char *e; - size_t len; - IGNORE_T *cur; - char sender[MAX_USER_LEN]; - static IGNORE_T ignore[] = - { - { "postmaster", 10 }, - { "uucp", 4 }, - { "mailer-daemon", 13 }, - { "mailer", 6 }, - { NULL, 0 } - }; - - static IGNORE_T ignorepost[] = - { - { "-request", 8 }, - { "-relay", 6 }, - { "-owner", 6 }, - { NULL, 0 } - }; - - static IGNORE_T ignorepre[] = - { - { "owner-", 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 - */ - - quot = false; - e = from; - len = 0; - while (*e != '\0' && (quot || !isdelim(*e))) - { - if (*e == '"') - { - quot = !quot; - ++e; - continue; - } - if (*e == '\\') - { - if (*(++e) == '\0') - { - /* '\\' at end of string? */ - break; - } - if (len < MAX_USER_LEN) - sender[len++] = *e; - ++e; - continue; - } - if (*e == '!' && !quot) - { - len = 0; - sender[len] = '\0'; - } - else - if (len < MAX_USER_LEN) - sender[len++] = *e; - ++e; - } - if (len < MAX_USER_LEN) - sender[len] = '\0'; - else - sender[MAX_USER_LEN - 1] = '\0'; - - if (len <= 0) - return false; -#if 0 - if (quot) - return false; /* syntax error... */ -#endif /* 0 */ - - /* test prefixes */ - for (cur = ignorepre; cur->name != NULL; ++cur) - { - if (len >= cur->len && - strncasecmp(cur->name, sender, cur->len) == 0) - return true; - } - - /* - ** If the name is truncated, don't test the rest. - ** We could extract the "tail" of the sender address and - ** compare it it ignorepost, however, it seems not worth - ** the effort. - ** The address surely can't match any entry in ignore[] - ** (as long as all of them are shorter than MAX_USER_LEN). - */ - - if (len > MAX_USER_LEN) - return false; - - /* test full local parts */ - for (cur = ignore; cur->name != NULL; ++cur) - { - if (len == cur->len && - strncasecmp(cur->name, sender, cur->len) == 0) - return true; - } - - /* test postfixes */ - for (cur = ignorepost; cur->name != NULL; ++cur) - { - if (len >= cur->len && - strncasecmp(cur->name, e - cur->len - 1, - 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. -** -*/ - -static 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 = VIT; - key.size = sizeof(VIT); - - st = Db->smdb_get(Db, &key, &data, 0); - if (st != SMDBE_OK) - next = SECSPERDAY * DAYSPERWEEK; - else - memmove(&next, data.data, sizeof(next)); - - memset(&data, '\0', sizeof data); - - /* get record for this address */ - key.data = From; - key.size = strlen(From); - - do - { - st = Db->smdb_get(Db, &key, &data, 0); - if (st == SMDBE_OK) - { - memmove(&then, 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 = domain; - key.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. -*/ - -static void -setinterval(interval) - time_t interval; -{ - SMDB_DBENT key, data; - - memset(&key, '\0', sizeof key); - memset(&data, '\0', sizeof data); - - key.data = VIT; - key.size = sizeof(VIT); - data.data = (char*) &interval; - 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. -*/ - -static 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 = from; - key.size = strlen(from); - data.data = (char*) &when; - 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. -*/ - -static void -xclude(f) - SM_FILE_T *f; -{ - char buf[MAXLINE], *p; - - if (f == NULL) - return; - while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof buf)) - { - 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. -** sender -- use as sender address -** -** Returns: -** nothing. -** -** Side Effects: -** sends vacation reply. -*/ - -static void -sendmessage(myname, msgfn, sender) - char *myname; - char *msgfn; - char *sender; -{ - SM_FILE_T *mfp, *sfp; - int i; - int pvect[2]; - char *pv[8]; - char buf[MAXLINE]; - - mfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, msgfn, SM_IO_RDONLY, NULL); - if (mfp == NULL) - { - if (msgfn[0] == '/') - msglog(LOG_NOTICE, "vacation: no %s file.\n", msgfn); - else - msglog(LOG_NOTICE, "vacation: no ~%s/%s file.\n", - myname, msgfn); - exit(EX_NOINPUT); - } - if (pipe(pvect) < 0) - { - msglog(LOG_ERR, "vacation: pipe: %s", sm_errstring(errno)); - exit(EX_OSERR); - } - pv[0] = "sendmail"; - pv[1] = "-oi"; - pv[2] = "-f"; - if (sender != NULL) - pv[3] = sender; - else - pv[3] = myname; - pv[4] = "--"; - pv[5] = From; - pv[6] = NULL; - i = fork(); - if (i < 0) - { - msglog(LOG_ERR, "vacation: fork: %s", sm_errstring(errno)); - exit(EX_OSERR); - } - if (i == 0) - { - (void) dup2(pvect[0], 0); - (void) close(pvect[0]); - (void) close(pvect[1]); - (void) sm_io_close(mfp, SM_TIME_DEFAULT); - (void) execv(_PATH_SENDMAIL, pv); - msglog(LOG_ERR, "vacation: can't exec %s: %s", - _PATH_SENDMAIL, sm_errstring(errno)); - exit(EX_UNAVAILABLE); - } - /* check return status of the following calls? XXX */ - (void) close(pvect[0]); - if ((sfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, - (void *) &(pvect[1]), - SM_IO_WRONLY, NULL)) != NULL) - { - (void) sm_io_fprintf(sfp, SM_TIME_DEFAULT, "To: %s\n", From); - (void) sm_io_fprintf(sfp, SM_TIME_DEFAULT, - "Auto-Submitted: auto-replied\n"); - while (sm_io_fgets(mfp, SM_TIME_DEFAULT, buf, sizeof buf)) - (void) sm_io_fputs(sfp, SM_TIME_DEFAULT, buf); - (void) sm_io_close(mfp, SM_TIME_DEFAULT); - (void) sm_io_close(sfp, SM_TIME_DEFAULT); - } - else - { - (void) sm_io_close(mfp, SM_TIME_DEFAULT); - msglog(LOG_ERR, "vacation: can't open pipe to sendmail"); - exit(EX_UNAVAILABLE); - } -} - -static void -usage() -{ - msglog(LOG_NOTICE, - "uid %u: usage: vacation [-a alias] [-C cfpath] [-d] [-f db] [-i] [-j] [-l] [-m msg] [-R returnaddr] [-r interval] [-s sender] [-t time] [-U] [-x] [-z] login\n", - getuid()); - exit(EX_USAGE); -} - -/* -** LISTDB -- list the contents of the vacation database -** -** Parameters: -** none. -** -** Returns: -** nothing. -*/ - -static void -listdb() -{ - int result; - time_t t; - SMDB_CURSOR *cursor = NULL; - SMDB_DBENT db_key, db_value; - - memset(&db_key, '\0', sizeof db_key); - memset(&db_value, '\0', sizeof db_value); - - result = Db->smdb_cursor(Db, &cursor, 0); - if (result != SMDBE_OK) - { - sm_io_fprintf(smioerr, SM_TIME_DEFAULT, - "vacation: set cursor: %s\n", - sm_errstring(result)); - return; - } - - while ((result = cursor->smdbc_get(cursor, &db_key, &db_value, - SMDB_CURSOR_GET_NEXT)) == SMDBE_OK) - { - char *timestamp; - - /* skip magic VIT entry */ - if (db_key.size == strlen(VIT) + 1 && - strncmp((char *)db_key.data, VIT, - (int)db_key.size - 1) == 0) - continue; - - /* skip bogus values */ - if (db_value.size != sizeof t) - { - sm_io_fprintf(smioerr, SM_TIME_DEFAULT, - "vacation: %.*s invalid time stamp\n", - (int) db_key.size, (char *) db_key.data); - continue; - } - - memcpy(&t, db_value.data, sizeof t); - - if (db_key.size > 40) - db_key.size = 40; - - if (t <= 0) - { - /* must be an exclude */ - timestamp = "(exclusion)\n"; - } - else - { - timestamp = ctime(&t); - } - sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%-40.*s %-10s", - (int) db_key.size, (char *) db_key.data, - timestamp); - - memset(&db_key, '\0', sizeof db_key); - memset(&db_value, '\0', sizeof db_value); - } - - if (result != SMDBE_OK && result != SMDBE_LAST_ENTRY) - { - sm_io_fprintf(smioerr, SM_TIME_DEFAULT, - "vacation: get value at cursor: %s\n", - sm_errstring(result)); - if (cursor != NULL) - { - (void) cursor->smdbc_close(cursor); - cursor = NULL; - } - return; - } - (void) cursor->smdbc_close(cursor); - cursor = NULL; -} - -/* -** DEBUGLOG -- write message to standard error -** -** Append a message to the standard error for the convenience of -** end-users debugging without access to the syslog messages. -** -** Parameters: -** i -- syslog log level -** fmt -- string format -** -** Returns: -** nothing. -*/ - -/*VARARGS2*/ -static SYSLOG_RET_T -#ifdef __STDC__ -debuglog(int i, const char *fmt, ...) -#else /* __STDC__ */ -debuglog(i, fmt, va_alist) - int i; - const char *fmt; - va_dcl -#endif /* __STDC__ */ - -{ - SM_VA_LOCAL_DECL - - SM_VA_START(ap, fmt); - sm_io_vfprintf(smioerr, SM_TIME_DEFAULT, fmt, ap); - SM_VA_END(ap); - SYSLOG_RET; -} |