⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alias.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
 * Copyright (c) 1988, 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.
 */

#include <sendmail.h>

#ifndef lint
static char id[] = "@(#)$Id: alias.c,v 8.142.4.3 2000/09/21 21:52:16 ca Exp $";
#endif /* ! lint */

# define SEPARATOR ':'
# define ALIAS_SPEC_SEPARATORS	" ,/:"

static MAP	*AliasFileMap = NULL;	/* the actual aliases.files map */
static int	NAliasFileMaps;	/* the number of entries in AliasFileMap */

static char	*aliaslookup __P((char *, int *));

/*
**  ALIAS -- Compute aliases.
**
**	Scans the alias file for an alias for the given address.
**	If found, it arranges to deliver to the alias list instead.
**	Uses libdbm database if -DDBM.
**
**	Parameters:
**		a -- address to alias.
**		sendq -- a pointer to the head of the send queue
**			to put the aliases in.
**		aliaslevel -- the current alias nesting depth.
**		e -- the current envelope.
**
**	Returns:
**		none
**
**	Side Effects:
**		Aliases found are expanded.
**
**	Deficiencies:
**		It should complain about names that are aliased to
**			nothing.
*/

void
alias(a, sendq, aliaslevel, e)
	register ADDRESS *a;
	ADDRESS **sendq;
	int aliaslevel;
	register ENVELOPE *e;
{
	register char *p;
	char *owner;
	auto int status = EX_OK;
	char obuf[MAXNAME + 7];

	if (tTd(27, 1))
		dprintf("alias(%s)\n", a->q_user);

	/* don't realias already aliased names */
	if (!QS_IS_OK(a->q_state))
		return;

	if (NoAlias)
		return;

	e->e_to = a->q_paddr;

	/*
	**  Look up this name.
	**
	**	If the map was unavailable, we will queue this message
	**	until the map becomes available; otherwise, we could
	**	bounce messages inappropriately.
	*/


#if _FFR_REDIRECTEMPTY
	/*
	**  envelope <> can't be sent to mailing lists, only owner-
	**  send spam of this type to owner- of the list
	**  ----  to stop spam from going to mailing lists!
	*/
	if (e->e_sender != NULL && *e->e_sender == '\0')
	{
		/* Look for owner of alias */
		(void) strlcpy(obuf, "owner-", sizeof obuf);
		(void) strlcat(obuf, a->q_user, sizeof obuf);
		if (aliaslookup(obuf, &status) != NULL)
		{
			if (LogLevel > 8)
				syslog(LOG_WARNING,
				       "possible spam from <> to list: %s, redirected to %s\n",
				       a->q_user, obuf);
			a->q_user = newstr(obuf);
		}
	}
#endif /* _FFR_REDIRECTEMPTY */

	p = aliaslookup(a->q_user, &status);
	if (status == EX_TEMPFAIL || status == EX_UNAVAILABLE)
	{
		a->q_state = QS_QUEUEUP;
		if (e->e_message == NULL)
			e->e_message = newstr("alias database unavailable");
		return;
	}
	if (p == NULL)
		return;

	/*
	**  Match on Alias.
	**	Deliver to the target list.
	*/

	if (tTd(27, 1))
		dprintf("%s (%s, %s) aliased to %s\n",
			a->q_paddr, a->q_host, a->q_user, p);
	if (bitset(EF_VRFYONLY, e->e_flags))
	{
		a->q_state = QS_VERIFIED;
		return;
	}
	message("aliased to %s", shortenstring(p, MAXSHORTSTR));
	if (LogLevel > 10)
		sm_syslog(LOG_INFO, e->e_id,
			"alias %.100s => %s",
			a->q_paddr, shortenstring(p, MAXSHORTSTR));
	a->q_flags &= ~QSELFREF;
	if (tTd(27, 5))
	{
		dprintf("alias: QS_EXPANDED ");
		printaddr(a, FALSE);
	}
	a->q_state = QS_EXPANDED;

	/*
	**  Always deliver aliased items as the default user.
	**  Setting q_gid to 0 forces deliver() to use DefUser
	**  instead of the alias name for the call to initgroups().
	*/

	a->q_uid = DefUid;
	a->q_gid = 0;
	a->q_fullname = NULL;
	a->q_flags |= QGOODUID|QALIAS;

	(void) sendtolist(p, a, sendq, aliaslevel + 1, e);
	if (bitset(QSELFREF, a->q_flags) && QS_IS_EXPANDED(a->q_state))
		a->q_state = QS_OK;

	/*
	**  Look for owner of alias
	*/

	(void) strlcpy(obuf, "owner-", sizeof obuf);
	if (strncmp(a->q_user, "owner-", 6) == 0 ||
	    strlen(a->q_user) > (SIZE_T) sizeof obuf - 7)
		(void) strlcat(obuf, "owner", sizeof obuf);
	else
		(void) strlcat(obuf, a->q_user, sizeof obuf);
	owner = aliaslookup(obuf, &status);
	if (owner == NULL)
		return;

	/* reflect owner into envelope sender */
	if (strpbrk(owner, ",:/|\"") != NULL)
		owner = obuf;
	a->q_owner = newstr(owner);

	/* announce delivery to this alias; NORECEIPT bit set later */
	if (e->e_xfp != NULL)
		fprintf(e->e_xfp, "Message delivered to mailing list %s\n",
			a->q_paddr);
	e->e_flags |= EF_SENDRECEIPT;
	a->q_flags |= QDELIVERED|QEXPANDED;
}
/*
**  ALIASLOOKUP -- look up a name in the alias file.
**
**	Parameters:
**		name -- the name to look up.
**		pstat -- a pointer to a place to put the status.
**
**	Returns:
**		the value of name.
**		NULL if unknown.
**
**	Side Effects:
**		none.
**
**	Warnings:
**		The return value will be trashed across calls.
*/

static char *
aliaslookup(name, pstat)
	char *name;
	int *pstat;
{
	static MAP *map = NULL;

	if (map == NULL)
	{
		STAB *s = stab("aliases", ST_MAP, ST_FIND);

		if (s == NULL)
			return NULL;
		map = &s->s_map;
	}
	DYNOPENMAP(map);

	/* special case POstMastER -- always use lower case */
	if (strcasecmp(name, "postmaster") == 0)
		name = "postmaster";

	return (*map->map_class->map_lookup)(map, name, NULL, pstat);
}
/*
**  SETALIAS -- set up an alias map
**
**	Called when reading configuration file.
**
**	Parameters:
**		spec -- the alias specification
**
**	Returns:
**		none.
*/

void
setalias(spec)
	char *spec;
{
	register char *p;
	register MAP *map;
	char *class;
	STAB *s;

	if (tTd(27, 8))
		dprintf("setalias(%s)\n", spec);

	for (p = spec; p != NULL; )
	{
		char buf[50];

		while (isascii(*p) && isspace(*p))
			p++;
		if (*p == '\0')
			break;
		spec = p;

		if (NAliasFileMaps >= MAXMAPSTACK)
		{
			syserr("Too many alias databases defined, %d max",
				MAXMAPSTACK);
			return;
		}
		if (AliasFileMap == NULL)
		{
			(void) strlcpy(buf, "aliases.files sequence",
				       sizeof buf);
			AliasFileMap = makemapentry(buf);
			if (AliasFileMap == NULL)
			{
				syserr("setalias: cannot create aliases.files map");
				return;
			}
		}
		(void) snprintf(buf, sizeof buf, "Alias%d", NAliasFileMaps);
		s = stab(buf, ST_MAP, ST_ENTER);
		map = &s->s_map;
		memset(map, '\0', sizeof *map);
		map->map_mname = s->s_name;
		p = strpbrk(p,ALIAS_SPEC_SEPARATORS);
		if (p != NULL && *p == SEPARATOR)
		{
			/* map name */
			*p++ = '\0';
			class = spec;
			spec = p;
		}
		else
		{
			class = "implicit";
			map->map_mflags = MF_INCLNULL;
		}

		/* find end of spec */
		if (p != NULL)
		{
			bool quoted = FALSE;

			for (; *p != '\0'; p++)
			{
				/*
				**  Don't break into a quoted string.
				**  Needed for ldap maps which use
				**  commas in their specifications.
				*/

				if (*p == '"')
					quoted = !quoted;
				else if (*p == ',' && !quoted)
					break;
			}

			/* No more alias specifications follow */
			if (*p == '\0')
				p = NULL;
		}
		if (p != NULL)
			*p++ = '\0';

		if (tTd(27, 20))
			dprintf("  map %s:%s %s\n", class, s->s_name, spec);

		/* look up class */
		s = stab(class, ST_MAPCLASS, ST_FIND);
		if (s == NULL)
		{
			syserr("setalias: unknown alias class %s", class);
		}
		else if (!bitset(MCF_ALIASOK, s->s_mapclass.map_cflags))
		{
			syserr("setalias: map class %s can't handle aliases",
				class);
		}
		else
		{
			map->map_class = &s->s_mapclass;
			if (map->map_class->map_parse(map, spec))
			{
				map->map_mflags |= MF_VALID|MF_ALIAS;
				AliasFileMap->map_stack[NAliasFileMaps++] = map;
			}
		}
	}
}
/*
**  ALIASWAIT -- wait for distinguished @:@ token to appear.
**
**	This can decide to reopen or rebuild the alias file
**
**	Parameters:
**		map -- a pointer to the map descriptor for this alias file.
**		ext -- the filename extension (e.g., ".db") for the
**			database file.
**		isopen -- if set, the database is already open, and we
**			should check for validity; otherwise, we are
**			just checking to see if it should be created.
**
**	Returns:
**		TRUE -- if the database is open when we return.
**		FALSE -- if the database is closed when we return.
*/

bool
aliaswait(map, ext, isopen)
	MAP *map;
	char *ext;
	bool isopen;
{
	bool attimeout = FALSE;
	time_t mtime;
	struct stat stb;
	char buf[MAXNAME + 1];

	if (tTd(27, 3))
		dprintf("aliaswait(%s:%s)\n",
			map->map_class->map_cname, map->map_file);
	if (bitset(MF_ALIASWAIT, map->map_mflags))
		return isopen;
	map->map_mflags |= MF_ALIASWAIT;

	if (SafeAlias > 0)
	{
		auto int st;
		time_t toolong = curtime() + SafeAlias;
		unsigned int sleeptime = 2;

		while (isopen &&
		       map->map_class->map_lookup(map, "@", NULL, &st) == NULL)
		{
			if (curtime() > toolong)
			{
				/* we timed out */
				attimeout = TRUE;
				break;
			}

			/*
			**  Close and re-open the alias database in case
			**  the one is mv'ed instead of cp'ed in.
			*/

			if (tTd(27, 2))
				dprintf("aliaswait: sleeping for %u seconds\n",
					sleeptime);

			map->map_class->map_close(map);
			map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
			(void) sleep(sleeptime);
			sleeptime *= 2;
			if (sleeptime > 60)
				sleeptime = 60;
			isopen = map->map_class->map_open(map, O_RDONLY);
		}
	}

	/* see if we need to go into auto-rebuild mode */
	if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
	{
		if (tTd(27, 3))
			dprintf("aliaswait: not rebuildable\n");
		map->map_mflags &= ~MF_ALIASWAIT;
		return isopen;
	}
	if (stat(map->map_file, &stb) < 0)
	{
		if (tTd(27, 3))
			dprintf("aliaswait: no source file\n");
		map->map_mflags &= ~MF_ALIASWAIT;
		return isopen;
	}
	mtime = stb.st_mtime;
	snprintf(buf, sizeof buf, "%s%s",
		map->map_file, ext == NULL ? "" : ext);
	if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || attimeout)
	{
#if !_FFR_REMOVE_AUTOREBUILD
		/* database is out of date */
		if (AutoRebuild &&
		    stb.st_ino != 0 &&
		    (stb.st_uid == geteuid() ||
		     (geteuid() == 0 && stb.st_uid == TrustedUid)))
		{
			bool oldSuprErrs;

			message("auto-rebuilding alias database %s", buf);
			oldSuprErrs = SuprErrs;
			SuprErrs = TRUE;
			if (isopen)
			{
				map->map_class->map_close(map);
				map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
			}
			(void) rebuildaliases(map, TRUE);
			isopen = map->map_class->map_open(map, O_RDONLY);
			SuprErrs = oldSuprErrs;
		}
		else
		{
			if (LogLevel > 3)
				sm_syslog(LOG_INFO, NOQID,
					"alias database %s out of date",
					buf);
			message("Warning: alias database %s out of date", buf);
		}
#else /* !_FFR_REMOVE_AUTOREBUILD */
		if (LogLevel > 3)
			sm_syslog(LOG_INFO, NOQID,
				  "alias database %s out of date",
				  buf);
		message("Warning: alias database %s out of date", buf);
#endif /* !_FFR_REMOVE_AUTOREBUILD */
	}
	map->map_mflags &= ~MF_ALIASWAIT;
	return isopen;
}
/*
**  REBUILDALIASES -- rebuild the alias database.
**
**	Parameters:
**		map -- the database to rebuild.
**		automatic -- set if this was automatically generated.
**
**	Returns:
**		TRUE if successful; FALSE otherwise.
**
**	Side Effects:
**		Reads the text version of the database, builds the
**		DBM or DB version.
*/

bool
rebuildaliases(map, automatic)
	register MAP *map;
	bool automatic;
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -