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 + -
显示快捷键?