Use sendmail's version of vacation. It is command line and database
compatible with the old version but includes new functionality and bug fixes. Since it is not part of the NO_SENDMAIL make.conf option, libsmdb and libsmutil should always be built for vacation's sake. PR: 15227
This commit is contained in:
parent
2c684a4ea2
commit
229a086ed1
@ -26,7 +26,7 @@ SUBDIR= ${_csu} libcom_err ${_libcrypt} msun libmd \
|
||||
libftpio libgnumalloc ${_libio} libipsec libipx libkvm libmenu \
|
||||
${_libncp} \
|
||||
libnetgraph libopie libpam libpanel libpcap \
|
||||
libposix1e libresolv librpcsvc ${_libsmdb} libss ${_libsmutil} \
|
||||
libposix1e libresolv librpcsvc libsmdb libss libsmutil \
|
||||
libstand ${_libtelnet} libusb ${_libvgl} libwrap libxpg4 liby libz
|
||||
|
||||
.if exists(${.CURDIR}/csu/${MACHINE_ARCH}-${OBJFORMAT})
|
||||
@ -43,11 +43,6 @@ _libc_r= libc_r
|
||||
_libbind= libbind
|
||||
.endif
|
||||
|
||||
.if !defined(NO_SENDMAIL)
|
||||
_libsmdb= libsmdb
|
||||
_libsmutil= libsmutil
|
||||
.endif
|
||||
|
||||
_libcrypt= libcrypt
|
||||
.if exists(${.CURDIR}/../secure) && !defined(NOSECURE) && !defined(NOCRYPT) && !defined(NO_DESCRYPT)
|
||||
# Build both libraries. They have different names, so no harm,
|
||||
|
@ -1,7 +1,36 @@
|
||||
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# $FreeBSD$
|
||||
|
||||
SENDMAIL_DIR=${.CURDIR}/../../contrib/sendmail
|
||||
.PATH: ${SENDMAIL_DIR}/vacation
|
||||
|
||||
PROG= vacation
|
||||
CFLAGS+= -Wall
|
||||
SRCS= vacation.c
|
||||
MAN8= vacation.1
|
||||
CFLAGS+=-I${SENDMAIL_DIR}/src -I${SENDMAIL_DIR}/include
|
||||
CFLAGS+=-DNEWDB -DNOT_SENDMAIL
|
||||
CFLAGS+=-D_FFR_LISTDB -D_FFR_DEBUG
|
||||
|
||||
.if exists(${.OBJDIR}/../../lib/libsmdb)
|
||||
LIBSMDBDIR:= ${.OBJDIR}/../../lib/libsmdb
|
||||
.else
|
||||
LIBSMDBDIR!= cd ${.CURDIR}/../../lib/libsmdb; make -V .OBJDIR
|
||||
.endif
|
||||
LIBSMDB:= ${LIBSMDBDIR}/libsmdb.a
|
||||
|
||||
.if exists(${.OBJDIR}/../../lib/libsmutil)
|
||||
LIBSMUTILDIR:= ${.OBJDIR}/../../lib/libsmutil
|
||||
.else
|
||||
LIBSMUTILDIR!= cd ${.CURDIR}/../../lib/libsmutil; make -V .OBJDIR
|
||||
.endif
|
||||
LIBSMUTIL:= ${LIBSMUTILDIR}/libsmutil.a
|
||||
|
||||
DPADD+= ${LIBSMDB} ${LIBSMUTIL}
|
||||
LDADD+= ${LIBSMDB} ${LIBSMUTIL}
|
||||
|
||||
# User customizations to the sendmail build environment
|
||||
CFLAGS+=${SENDMAIL_CFLAGS}
|
||||
LDFLAGS+=${SENDMAIL_LDFLAGS}
|
||||
LDADD+=${SENDMAIL_LDADD}
|
||||
DPADD+=${SENDMAIL_DPADD}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -1,202 +0,0 @@
|
||||
.\" Copyright (c) 1985, 1987, 1990, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" From: @(#)vacation.1 8.1 (Berkeley) 6/16/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 16, 1993
|
||||
.Dt VACATION 1
|
||||
.Os BSD 4.3
|
||||
.Sh NAME
|
||||
.Nm vacation
|
||||
.Nd return ``I am not here'' indication
|
||||
.Sh SYNOPSIS
|
||||
.Nm vacation
|
||||
.Op Fl d
|
||||
.Fl i
|
||||
.Op Fl r Ar interval
|
||||
.Nm vacation
|
||||
.Op Fl d
|
||||
.Fl l
|
||||
.Nm vacation
|
||||
.Op Fl d
|
||||
.Op Fl a Ar alias
|
||||
.Ar login
|
||||
.Sh DESCRIPTION
|
||||
.Nm 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
|
||||
.Pa .forward
|
||||
file. For example, your
|
||||
.Pa .forward
|
||||
file might have:
|
||||
.Bd -literal -offset indent
|
||||
\eeric, "|/usr/bin/vacation -a allman eric"
|
||||
.Ed
|
||||
which would send messages to you (assuming your login name was eric) and
|
||||
reply to any messages for
|
||||
.Dq eric
|
||||
or
|
||||
.Dq allman .
|
||||
.Pp
|
||||
Available options:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a Ar alias
|
||||
Handle messages for
|
||||
.Ar alias
|
||||
in the same manner as those received for the user's
|
||||
login name.
|
||||
.It Fl d
|
||||
Enable debugging mode.
|
||||
See below.
|
||||
.It Fl i
|
||||
Initialize the vacation database files. It should be used
|
||||
before you modify your
|
||||
.Pa .forward
|
||||
file.
|
||||
.It Fl r
|
||||
Set the reply interval to
|
||||
.Ar interval
|
||||
days. The default is one week. An interval of
|
||||
.Dq 0
|
||||
means that
|
||||
a reply is sent to each message, and an interval of
|
||||
.Dq Li infinite
|
||||
(actually, any non-numeric character) will never send more than
|
||||
one reply. It should be noted that intervals of
|
||||
.Dq Li \&0
|
||||
are quite
|
||||
dangerous, as it allows mailers to get into
|
||||
.Dq I am on vacation
|
||||
loops.
|
||||
.It Fl l
|
||||
Print the contents of the vacation database files. For each entry,
|
||||
the address the reply has been sent to and the associated time will
|
||||
be printed to standard output.
|
||||
.El
|
||||
.Pp
|
||||
No message will be sent unless
|
||||
.Ar login
|
||||
(or an
|
||||
.Ar alias
|
||||
supplied using the
|
||||
.Fl a
|
||||
option) is part of either the
|
||||
.Dq To:
|
||||
or
|
||||
.Dq Cc:
|
||||
headers of the mail.
|
||||
No messages from
|
||||
.Dq ???-REQUEST ,
|
||||
.Dq Postmaster ,
|
||||
.Dq Tn UUCP ,
|
||||
.Dq MAILER ,
|
||||
or
|
||||
.Dq MAILER-DAEMON
|
||||
will be replied to (where these strings are
|
||||
case insensitive) nor is a notification sent if a
|
||||
.Dq Precedence: bulk
|
||||
or
|
||||
.Dq Precedence: junk
|
||||
line is included in the mail headers.
|
||||
The people who have sent you messages are maintained as a
|
||||
.Xr hash 3
|
||||
database in the file
|
||||
.Pa .vacation.db
|
||||
in your home directory.
|
||||
.Pp
|
||||
.Nm Vacation
|
||||
expects a file
|
||||
.Pa .vacation.msg ,
|
||||
in your home directory, containing a message to be sent back to each
|
||||
sender. It should be an entire message (including headers). For
|
||||
example, it might contain:
|
||||
.Pp
|
||||
.Bd -unfilled -offset indent -compact
|
||||
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
|
||||
.Ed
|
||||
.Pp
|
||||
.Nm Vacation
|
||||
reads the first line from the standard input for a
|
||||
.Ux
|
||||
.Dq From
|
||||
line to determine the sender.
|
||||
.Xr Sendmail 8
|
||||
includes this
|
||||
.Dq From
|
||||
line automatically.
|
||||
.Pp
|
||||
Fatal errors, such as calling
|
||||
.Nm vacation
|
||||
with incorrect arguments, or with non-existent
|
||||
.Ar login Ns Ar s ,
|
||||
are logged in the system log file, using
|
||||
.Xr syslog 3
|
||||
unless debugging mode is enabled with the
|
||||
.Fl d
|
||||
option, in which case they are written to the standard error output.
|
||||
.Pp
|
||||
Building on the example provided above, you might choose to have errors
|
||||
redirected to a file while you are testing vacation's operation with
|
||||
the following in your
|
||||
.Pa .forward
|
||||
file:
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
\eeric, "|/bin/sh -c '/usr/bin/vacation -d -a allman eric' 2>/home/eric/.vacation.log"
|
||||
.Ed
|
||||
.Sh DIAGNOSTICS
|
||||
The
|
||||
.Nm
|
||||
utility exits 0 on success, and >0 if an error occurs.
|
||||
.Sh FILES
|
||||
.Bl -tag -width "vacation.dirxxx" -compact
|
||||
.It Pa ~/.vacation.db
|
||||
database file
|
||||
.It Pa ~/.vacation.msg
|
||||
message to send
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr syslog 3 ,
|
||||
.Xr sendmail 8 ,
|
||||
.Xr syslogd 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm vacation
|
||||
command appeared in
|
||||
.Bx 4.3 .
|
@ -1,525 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1983, 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1983, 1987, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)from: vacation.c 8.2 (Berkeley) 1/26/94";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
** Vacation
|
||||
** Copyright (c) 1983 Eric P. Allman
|
||||
** Berkeley, California
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#include <db.h>
|
||||
#include <time.h>
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <paths.h>
|
||||
|
||||
/*
|
||||
* VACATION -- return a message to the sender when on vacation.
|
||||
*
|
||||
* This program is invoked as a message receiver. It returns a
|
||||
* message specified by the user to whomever sent the mail, taking
|
||||
* care not to return a message too often to prevent "I am on
|
||||
* vacation" loops.
|
||||
*/
|
||||
|
||||
#define MAXLINE 1024 /* max line from mail header */
|
||||
#define VDB ".vacation.db" /* dbm's database */
|
||||
#define VMSG ".vacation.msg" /* vacation message */
|
||||
|
||||
typedef struct alias {
|
||||
struct alias *next;
|
||||
char *name;
|
||||
} ALIAS;
|
||||
ALIAS *names;
|
||||
|
||||
DB *db;
|
||||
|
||||
char from[MAXLINE];
|
||||
void (*msglog)(int, const char *, ...) = &syslog;
|
||||
|
||||
static int isdelim __P((int));
|
||||
static int junkmail __P((void));
|
||||
static void listdb __P((void));
|
||||
static int nsearch __P((char *, char *));
|
||||
static void readheaders __P((void));
|
||||
static int recent __P((void));
|
||||
static void sendmessage __P((char *));
|
||||
static void setinterval __P((time_t));
|
||||
static void setreply __P((void));
|
||||
static void usage __P((void));
|
||||
static void debuglog __P((int, const char *, ...));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct passwd *pw;
|
||||
ALIAS *cur;
|
||||
time_t interval;
|
||||
int ch, iflag, lflag, mfail, ufail;
|
||||
|
||||
opterr = iflag = lflag = mfail = ufail = 0;
|
||||
interval = -1;
|
||||
while ((ch = getopt(argc, argv, "a:dIilr:")) != -1) {
|
||||
switch((char)ch) {
|
||||
case 'a': /* alias */
|
||||
if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS)))) {
|
||||
mfail++;
|
||||
break;
|
||||
}
|
||||
cur->name = optarg;
|
||||
cur->next = names;
|
||||
names = cur;
|
||||
break;
|
||||
case 'd': /* debug mode */
|
||||
msglog = &debuglog;
|
||||
break;
|
||||
case 'I': /* backward compatible */
|
||||
case 'i': /* init the database */
|
||||
iflag = 1;
|
||||
break;
|
||||
case 'l':
|
||||
lflag = 1; /* list the database */
|
||||
break;
|
||||
case 'r':
|
||||
if (isdigit(*optarg)) {
|
||||
interval = atol(optarg) * 86400;
|
||||
if (interval < 0)
|
||||
ufail++;
|
||||
}
|
||||
else
|
||||
interval = LONG_MAX;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
ufail++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Only die on the above malloc and usage errors here so that the
|
||||
* correct logging medium is used.
|
||||
*/
|
||||
if (mfail) {
|
||||
msglog(LOG_ERR, "vacation: malloc failed\n");
|
||||
exit(EX_TEMPFAIL);
|
||||
}
|
||||
else if (ufail)
|
||||
usage();
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 1) {
|
||||
if (!iflag && !lflag)
|
||||
usage();
|
||||
if (!(pw = getpwuid(getuid()))) {
|
||||
msglog(LOG_ERR,
|
||||
"vacation: no such user uid %u.\n", getuid());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (!(pw = getpwnam(*argv))) {
|
||||
msglog(LOG_ERR, "vacation: no such user %s.\n", *argv);
|
||||
exit(1);
|
||||
}
|
||||
if (chdir(pw->pw_dir)) {
|
||||
msglog(LOG_NOTICE,
|
||||
"vacation: no such directory %s.\n", pw->pw_dir);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
db = dbopen(VDB, O_CREAT|O_RDWR | (iflag ? O_TRUNC : 0),
|
||||
S_IRUSR|S_IWUSR, DB_HASH, NULL);
|
||||
if (!db) {
|
||||
msglog(LOG_NOTICE, "vacation: %s: %s\n", VDB, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (lflag)
|
||||
listdb();
|
||||
else if (interval != -1)
|
||||
setinterval(interval);
|
||||
|
||||
if (iflag || lflag) {
|
||||
(void)(db->close)(db);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!(cur = malloc((u_int)sizeof(ALIAS)))) {
|
||||
msglog(LOG_ERR, "vacation: malloc failed\n");
|
||||
exit(EX_TEMPFAIL);
|
||||
}
|
||||
cur->name = pw->pw_name;
|
||||
cur->next = names;
|
||||
names = cur;
|
||||
|
||||
readheaders();
|
||||
if (!recent()) {
|
||||
setreply();
|
||||
(void)(db->close)(db);
|
||||
sendmessage(pw->pw_name);
|
||||
}
|
||||
else
|
||||
(void)(db->close)(db);
|
||||
exit(0);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* readheaders --
|
||||
* read mail headers
|
||||
*/
|
||||
static void
|
||||
readheaders()
|
||||
{
|
||||
register ALIAS *cur;
|
||||
register char *p;
|
||||
int tome, cont;
|
||||
char buf[MAXLINE];
|
||||
|
||||
cont = tome = 0;
|
||||
while (fgets(buf, sizeof(buf), stdin) && *buf != '\n')
|
||||
switch(*buf) {
|
||||
case 'F': /* "From " */
|
||||
cont = 0;
|
||||
if (!strncmp(buf, "From ", 5)) {
|
||||
for (p = buf + 5; *p && *p != ' '; ++p);
|
||||
*p = '\0';
|
||||
(void)strcpy(from, buf + 5);
|
||||
if ((p = index(from, '\n')))
|
||||
*p = '\0';
|
||||
if (junkmail())
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
case 'P': /* "Precedence:" */
|
||||
cont = 0;
|
||||
if (strncasecmp(buf, "Precedence", 10) ||
|
||||
(buf[10] != ':' && buf[10] != ' ' && buf[10] != '\t'))
|
||||
break;
|
||||
if (!(p = index(buf, ':')))
|
||||
break;
|
||||
while (*++p && isspace(*p));
|
||||
if (!*p)
|
||||
break;
|
||||
if (!strncasecmp(p, "junk", 4) ||
|
||||
!strncasecmp(p, "bulk", 4) ||
|
||||
!strncasecmp(p, "list", 4))
|
||||
exit(0);
|
||||
break;
|
||||
case 'C': /* "Cc:" */
|
||||
if (strncmp(buf, "Cc:", 3))
|
||||
break;
|
||||
cont = 1;
|
||||
goto findme;
|
||||
case 'T': /* "To:" */
|
||||
if (strncmp(buf, "To:", 3))
|
||||
break;
|
||||
cont = 1;
|
||||
goto findme;
|
||||
default:
|
||||
if (!isspace(*buf) || !cont || tome) {
|
||||
cont = 0;
|
||||
break;
|
||||
}
|
||||
findme: for (cur = names; !tome && cur; cur = cur->next)
|
||||
tome += nsearch(cur->name, buf);
|
||||
}
|
||||
if (!tome)
|
||||
exit(0);
|
||||
if (!*from) {
|
||||
msglog(LOG_NOTICE, "vacation: no initial \"From\" line.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nsearch --
|
||||
* do a nice, slow, search of a string for a substring.
|
||||
*/
|
||||
static int
|
||||
nsearch(name, str)
|
||||
register char *name, *str;
|
||||
{
|
||||
register int len;
|
||||
|
||||
for (len = strlen(name); *str; ++str)
|
||||
if (*str == *name &&
|
||||
!strncasecmp(name, str, len) &&
|
||||
isdelim((unsigned char)str[len]))
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* junkmail --
|
||||
* read the header and return if automagic/junk/bulk/list mail
|
||||
*/
|
||||
static int
|
||||
junkmail()
|
||||
{
|
||||
static struct ignore {
|
||||
char *name;
|
||||
int len;
|
||||
} ignore[] = {
|
||||
{"-request", 8}, {"postmaster", 10}, {"uucp", 4},
|
||||
{"mailer-daemon", 13}, {"mailer", 6}, {"-relay", 6},
|
||||
{NULL, 0},
|
||||
};
|
||||
register struct ignore *cur;
|
||||
register int len;
|
||||
register char *p;
|
||||
|
||||
/*
|
||||
* 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 = index(from, '%')))
|
||||
if (!((p = index(from, '@')))) {
|
||||
if ((p = rindex(from, '!')))
|
||||
++p;
|
||||
else
|
||||
p = from;
|
||||
for (; *p; ++p);
|
||||
}
|
||||
len = p - from;
|
||||
for (cur = ignore; cur->name; ++cur)
|
||||
if (len >= cur->len &&
|
||||
!strncasecmp(cur->name, p - cur->len, cur->len))
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
#define VIT "__VACATION__INTERVAL__TIMER__"
|
||||
|
||||
/*
|
||||
* recent --
|
||||
* find out if user has gotten a vacation message recently.
|
||||
* use bcopy for machines with alignment restrictions
|
||||
*/
|
||||
static int
|
||||
recent()
|
||||
{
|
||||
DBT key, data;
|
||||
time_t then, next;
|
||||
|
||||
/* get interval time */
|
||||
key.data = VIT;
|
||||
key.size = sizeof(VIT);
|
||||
if ((db->get)(db, &key, &data, 0))
|
||||
next = 86400 * 7;
|
||||
else
|
||||
bcopy(data.data, &next, sizeof(next));
|
||||
|
||||
/* get record for this address */
|
||||
key.data = from;
|
||||
key.size = strlen(from);
|
||||
if (!(db->get)(db, &key, &data, 0)) {
|
||||
bcopy(data.data, &then, sizeof(then));
|
||||
if (next == LONG_MAX || then + next > time(NULL))
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* setinterval --
|
||||
* store the reply interval
|
||||
*/
|
||||
static void
|
||||
setinterval(interval)
|
||||
time_t interval;
|
||||
{
|
||||
DBT key, data;
|
||||
|
||||
key.data = VIT;
|
||||
key.size = sizeof(VIT);
|
||||
data.data = &interval;
|
||||
data.size = sizeof(interval);
|
||||
(void)(db->put)(db, &key, &data, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* setreply --
|
||||
* store that this user knows about the vacation.
|
||||
*/
|
||||
static void
|
||||
setreply()
|
||||
{
|
||||
DBT key, data;
|
||||
time_t now;
|
||||
|
||||
key.data = from;
|
||||
key.size = strlen(from);
|
||||
(void)time(&now);
|
||||
data.data = &now;
|
||||
data.size = sizeof(now);
|
||||
(void)(db->put)(db, &key, &data, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* sendmessage --
|
||||
* exec sendmail to send the vacation file to sender
|
||||
*/
|
||||
static void
|
||||
sendmessage(myname)
|
||||
char *myname;
|
||||
{
|
||||
FILE *mfp, *sfp;
|
||||
int i;
|
||||
int pvect[2];
|
||||
char buf[MAXLINE];
|
||||
|
||||
mfp = fopen(VMSG, "r");
|
||||
if (mfp == NULL) {
|
||||
msglog(LOG_NOTICE, "vacation: no ~%s/%s file.\n", myname, VMSG);
|
||||
exit(1);
|
||||
}
|
||||
if (pipe(pvect) < 0) {
|
||||
msglog(LOG_ERR, "vacation: pipe: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
i = fork();
|
||||
if (i < 0) {
|
||||
msglog(LOG_ERR, "vacation: fork: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (i == 0) {
|
||||
dup2(pvect[0], 0);
|
||||
close(pvect[0]);
|
||||
close(pvect[1]);
|
||||
close(fileno(mfp));
|
||||
execl(_PATH_SENDMAIL, "sendmail", "-f", myname, "--", from, NULL);
|
||||
msglog(LOG_ERR, "vacation: can't exec %s: %s",
|
||||
_PATH_SENDMAIL, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
close(pvect[0]);
|
||||
sfp = fdopen(pvect[1], "w");
|
||||
fprintf(sfp, "To: %s\n", from);
|
||||
while (fgets(buf, sizeof buf, mfp))
|
||||
fputs(buf, sfp);
|
||||
fclose(mfp);
|
||||
fclose(sfp);
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
msglog(LOG_NOTICE, "uid %u: usage: vacation [-d] [-i [-rinterval]] [-l] [-a alias] login\n",
|
||||
getuid());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
listdb()
|
||||
{
|
||||
DBT key, data;
|
||||
int rv;
|
||||
time_t t;
|
||||
char user[MAXLINE];
|
||||
|
||||
while((rv = db->seq(db, &key, &data, R_NEXT)) == 0) {
|
||||
bcopy(key.data, user, key.size);
|
||||
user[key.size] = '\0';
|
||||
if (strcmp(user, VIT) == 0)
|
||||
continue;
|
||||
bcopy(data.data, &t, data.size);
|
||||
printf("%-40s %-10s", user, ctime(&t));
|
||||
}
|
||||
if (rv == -1)
|
||||
perror("IO error in database");
|
||||
}
|
||||
|
||||
/*
|
||||
* Is `c' a delimiting character for a recipient name?
|
||||
*/
|
||||
static int
|
||||
isdelim(c)
|
||||
int c;
|
||||
{
|
||||
/*
|
||||
* NB: don't use setlocale() before, headers are supposed to
|
||||
* consist only of ASCII (aka. C locale) characters.
|
||||
*/
|
||||
if (isalnum(c))
|
||||
return(0);
|
||||
if (c == '_' || c == '-' || c == '.')
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a message to the standard error for the convenience of end-users
|
||||
* debugging without access to the syslog messages.
|
||||
*/
|
||||
static void
|
||||
debuglog(int i, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
i = 0; /* Printing syslog priority not implemented */
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
Loading…
Reference in New Issue
Block a user