vacation.c
来自「< linux网络编程工具>>配套源码」· C语言 代码 · 共 1,069 行 · 第 1/2 页
C
1,069 行
for (cur = Names;
!tome && cur != NULL;
cur = cur->next)
tome = nsearch(cur->name, buf);
}
}
if (!tome)
EXITIT(EX_OK);
if (*From == '\0')
{
msglog(LOG_NOTICE, "vacation: no initial \"From \" line.\n");
EXITIT(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] == '/')
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", errstring(errno));
exit(EX_OSERR);
}
i = fork();
if (i < 0)
{
msglog(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", "-oi",
"-f", myname, "--", From, NULL);
msglog(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);
msglog(LOG_ERR, "vacation: can't open pipe to sendmail");
exit(EX_UNAVAILABLE);
}
}
void
usage()
{
msglog(LOG_NOTICE, "uid %u: usage: vacation [-i] [-a alias]%s [-f db]%s [-m msg] [-r interval] [-s sender] [-t time] [-x] [-z] login\n",
getuid(),
#if _FFR_DEBUG
" [-d]",
#else /* _FFR_DEBUG */
"",
#endif /* _FFR_DEBUG */
#if _FFR_LISTDB
" [-l]"
#else /* _FFR_LISTDB */
""
#endif /* _FFR_LISTDB */
);
exit(EX_USAGE);
}
#if _FFR_LISTDB
/*
** 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)
{
fprintf(stderr, "vacation: set cursor: %s\n",
errstring(result));
return;
}
while ((result = cursor->smdbc_get(cursor, &db_key, &db_value,
SMDB_CURSOR_GET_NEXT)) == SMDBE_OK)
{
/* skip magic VIT entry */
if ((int)db_key.data.size -1 == strlen(VIT) &&
strncmp((char *)db_key.data.data, VIT,
(int)db_key.data.size - 1) == 0)
continue;
/* skip bogus values */
if (db_value.data.size != sizeof t)
{
fprintf(stderr, "vacation: %.*s invalid time stamp\n",
(int) db_key.data.size,
(char *) db_key.data.data);
continue;
}
memcpy(&t, db_value.data.data, sizeof t);
if (db_key.data.size > 40)
db_key.data.size = 40;
printf("%-40.*s %-10s",
(int) db_key.data.size, (char *) db_key.data.data,
ctime(&t));
memset(&db_key, '\0', sizeof db_key);
memset(&db_value, '\0', sizeof db_value);
}
if (result != SMDBE_OK && result != SMDBE_LAST_ENTRY)
{
fprintf(stderr, "vacation: get value at cursor: %s\n",
errstring(result));
if (cursor != NULL)
{
(void) cursor->smdbc_close(cursor);
cursor = NULL;
}
return;
}
(void) cursor->smdbc_close(cursor);
cursor = NULL;
}
#endif /* _FFR_LISTDB */
#if _FFR_DEBUG
/*
** 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 void
#ifdef __STDC__
debuglog(int i, const char *fmt, ...)
#else /* __STDC__ */
debuglog(i, fmt, va_alist)
int i;
const char *fmt;
va_dcl
#endif /* __STDC__ */
{
VA_LOCAL_DECL
VA_START(fmt);
vfprintf(stderr, fmt, ap);
VA_END;
}
#endif /* _FFR_DEBUG */
/*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;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?