vacation.c
来自「< linux网络编程工具>>配套源码」· C语言 代码 · 共 1,069 行 · 第 1/2 页
C
1,069 行
/*
* 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-2000 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[] = "@(#)$Id: vacation.c,v 8.68.4.7 2000/09/05 21:48:45 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>
#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];
#if _FFR_DEBUG
void (*msglog)(int, const char *, ...) = &syslog;
static void debuglog __P((int, const char *, ...));
#else /* _FFR_DEBUG */
# define msglog syslog
#endif /* _FFR_DEBUG */
static void eatmsg __P((void));
/* exit after reading input */
#define EXITIT(excode) { \
eatmsg(); \
exit(excode); \
}
int
main(argc, argv)
int argc;
char **argv;
{
bool iflag, emptysender, exclude;
#if _FFR_LISTDB
bool lflag = FALSE;
#endif /* _FFR_LISTDB */
int mfail = 0, ufail = 0;
int ch;
int result;
long sff;
time_t interval;
struct passwd *pw;
ALIAS *cur;
char *dbfilename = VDB;
char *msgfilename = VMSG;
char *name;
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 *));
#if _FFR_LISTDB
#define EXITM(excode) { \
if (!iflag && !lflag) \
eatmsg(); \
exit(excode); \
}
#else /* _FFR_LISTDB */
#define EXITM(excode) { \
if (!iflag) \
eatmsg(); \
exit(excode); \
}
#endif /* _FFR_LISTDB */
/* 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';
#if _FFR_DEBUG && _FFR_LISTDB
# define OPTIONS "a:df:Iilm:r:s:t:xz"
#else /* _FFR_DEBUG && _FFR_LISTDB */
# if _FFR_DEBUG
# define OPTIONS "a:df:Iim:r:s:t:xz"
# else /* _FFR_DEBUG */
# if _FFR_LISTDB
# define OPTIONS "a:f:Iilm:r:s:t:xz"
# else /* _FFR_LISTDB */
# define OPTIONS "a:f:Iim:r:s:t:xz"
# endif /* _FFR_LISTDB */
# endif /* _FFR_DEBUG */
#endif /* _FFR_DEBUG && _FFR_LISTDB */
while (mfail == 0 && ufail == 0 &&
(ch = getopt(argc, argv, OPTIONS)) != -1)
{
switch((char)ch)
{
case 'a': /* alias */
cur = (ALIAS *)malloc((u_int)sizeof(ALIAS));
if (cur == NULL)
{
mfail++;
break;
}
cur->name = optarg;
cur->next = Names;
Names = cur;
break;
#if _FFR_DEBUG
case 'd': /* debug mode */
msglog = &debuglog;
break;
#endif /* _FFR_DEBUG */
case 'f': /* alternate database */
dbfilename = optarg;
break;
case 'I': /* backward compatible */
case 'i': /* init the database */
iflag = TRUE;
break;
#if _FFR_LISTDB
case 'l':
lflag = TRUE; /* list the database */
break;
#endif /* _FFR_LISTDB */
case 'm': /* alternate message file */
msgfilename = 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) 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:
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 (!iflag &&
#if _FFR_LISTDB
!lflag &&
#endif /* _FFR_LISTDB */
!exclude)
usage();
if ((pw = getpwuid(getuid())) == NULL)
{
msglog(LOG_ERR,
"vacation: no such user uid %u.\n", getuid());
EXITM(EX_NOUSER);
}
}
#if _FFR_BLACKBOX
name = *argv;
#else /* _FFR_BLACKBOX */
else if ((pw = getpwnam(*argv)) == NULL)
{
msglog(LOG_ERR, "vacation: no such user %s.\n", *argv);
EXITM(EX_NOUSER);
}
name = pw->pw_name;
if (chdir(pw->pw_dir) != 0)
{
msglog(LOG_NOTICE,
"vacation: no such directory %s.\n", pw->pw_dir);
EXITM(EX_NOINPUT);
}
#endif /* _FFR_BLACKBOX */
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);
sff = SFF_CREAT;
#if _FFR_BLACKBOX
if (getegid() != getgid())
RunAsGid = user_info.smdbu_group_id = getegid();
sff |= SFF_NOPATHCHECK|SFF_OPENASROOT;
#endif /* _FFR_BLACKBOX */
result = smdb_open_database(&Db, dbfilename,
O_CREAT|O_RDWR | (iflag ? 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,
errstring(result));
EXITM(EX_DATAERR);
}
#if _FFR_LISTDB
if (lflag)
{
static void listdb __P((void));
listdb();
(void)Db->smdb_close(Db);
exit(EX_OK);
}
#endif /* _FFR_LISTDB */
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);
EXITM(EX_OK);
}
if ((cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))) == NULL)
{
msglog(LOG_NOTICE,
"vacation: can't allocate memory for username.\n");
EXITM(EX_OSERR);
}
cur->name = name;
cur->next = Names;
Names = cur;
readheaders();
if (!recent())
{
time_t now;
(void) time(&now);
setreply(From, now);
result = Db->smdb_close(Db);
sendmessage(name, msgfilename, emptysender);
}
else
result = Db->smdb_close(Db);
exit(EX_OK);
/* NOTREACHED */
return EX_OK;
}
/*
** 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:
** none.
**
** Returns:
** nothing.
**
** Side Effects:
** may exit().
**
*/
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 (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')
{
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)strlcpy(From, buf + 5,
sizeof From);
if ((p = strchr(buf + 5, '\n')) != NULL)
*p = '\0';
if (junkmail(buf + 5))
EXITIT(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)
EXITIT(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:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?