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

📄 recipient.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1983 Eric P. Allman * Copyright (c) 1988, 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 lintstatic char sccsid[] = "@(#)recipient.c	8.44 (Berkeley) 2/28/94";#endif /* not lint */# include "sendmail.h"# include <pwd.h>/***  SENDTOLIST -- Designate a send list.****	The parameter is a comma-separated list of people to send to.**	This routine arranges to send to all of them.****	Parameters:**		list -- the send list.**		ctladdr -- the address template for the person to**			send to -- effective uid/gid are important.**			This is typically the alias that caused this**			expansion.**		sendq -- a pointer to the head of a queue to put**			these people into.**		e -- the envelope in which to add these recipients.****	Returns:**		The number of addresses actually on the list.****	Side Effects:**		none.*/# define MAXRCRSN	10sendtolist(list, ctladdr, sendq, e)	char *list;	ADDRESS *ctladdr;	ADDRESS **sendq;	register ENVELOPE *e;{	register char *p;	register ADDRESS *al;	/* list of addresses to send to */	bool firstone;		/* set on first address sent */	char delimiter;		/* the address delimiter */	int naddrs;	char *oldto = e->e_to;	if (list == NULL)	{		syserr("sendtolist: null list");		return 0;	}	if (tTd(25, 1))	{		printf("sendto: %s\n   ctladdr=", list);		printaddr(ctladdr, FALSE);	}	/* heuristic to determine old versus new style addresses */	if (ctladdr == NULL &&	    (strchr(list, ',') != NULL || strchr(list, ';') != NULL ||	     strchr(list, '<') != NULL || strchr(list, '(') != NULL))		e->e_flags &= ~EF_OLDSTYLE;	delimiter = ' ';	if (!bitset(EF_OLDSTYLE, e->e_flags) || ctladdr != NULL)		delimiter = ',';	firstone = TRUE;	al = NULL;	naddrs = 0;	for (p = list; *p != '\0'; )	{		auto char *delimptr;		register ADDRESS *a;		/* parse the address */		while ((isascii(*p) && isspace(*p)) || *p == ',')			p++;		a = parseaddr(p, NULLADDR, RF_COPYALL, delimiter, &delimptr, e);		p = delimptr;		if (a == NULL)			continue;		a->q_next = al;		a->q_alias = ctladdr;		/* see if this should be marked as a primary address */		if (ctladdr == NULL ||		    (firstone && *p == '\0' && bitset(QPRIMARY, ctladdr->q_flags)))			a->q_flags |= QPRIMARY;		if (ctladdr != NULL && sameaddr(ctladdr, a))			ctladdr->q_flags |= QSELFREF;		al = a;		firstone = FALSE;	}	/* arrange to send to everyone on the local send list */	while (al != NULL)	{		register ADDRESS *a = al;		al = a->q_next;		a = recipient(a, sendq, e);		/* arrange to inherit full name */		if (a->q_fullname == NULL && ctladdr != NULL)			a->q_fullname = ctladdr->q_fullname;		naddrs++;	}	e->e_to = oldto;	return (naddrs);}/***  RECIPIENT -- Designate a message recipient****	Saves the named person for future mailing.****	Parameters:**		a -- the (preparsed) address header for the recipient.**		sendq -- a pointer to the head of a queue to put the**			recipient in.  Duplicate supression is done**			in this queue.**		e -- the current envelope.****	Returns:**		The actual address in the queue.  This will be "a" if**		the address is not a duplicate, else the original address.****	Side Effects:**		none.*/ADDRESS *recipient(a, sendq, e)	register ADDRESS *a;	register ADDRESS **sendq;	register ENVELOPE *e;{	register ADDRESS *q;	ADDRESS **pq;	register struct mailer *m;	register char *p;	bool quoted = FALSE;		/* set if the addr has a quote bit */	int findusercount = 0;	char buf[MAXNAME];		/* unquoted image of the user name */	extern int safefile();	e->e_to = a->q_paddr;	m = a->q_mailer;	errno = 0;	if (tTd(26, 1))	{		printf("\nrecipient: ");		printaddr(a, FALSE);	}	/* if this is primary, add it to the original recipient list */	if (a->q_alias == NULL)	{		if (e->e_origrcpt == NULL)			e->e_origrcpt = a->q_paddr;		else if (e->e_origrcpt != a->q_paddr)			e->e_origrcpt = "";	}	/* break aliasing loops */	if (AliasLevel > MAXRCRSN)	{		usrerr("554 aliasing/forwarding loop broken");		return (a);	}	/*	**  Finish setting up address structure.	*/	/* set the queue timeout */	a->q_timeout = TimeOuts.to_q_return;	/* get unquoted user for file, program or user.name check */	(void) strcpy(buf, a->q_user);	for (p = buf; *p != '\0' && !quoted; p++)	{		if (*p == '\\')			quoted = TRUE;	}	stripquotes(buf);	/* check for direct mailing to restricted mailers */	if (m == ProgMailer)	{		if (a->q_alias == NULL)		{			a->q_flags |= QBADADDR;			usrerr("550 Cannot mail directly to programs");		}		else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))		{			a->q_flags |= QBADADDR;			usrerr("550 User %s@%s doesn't have a valid shell for mailing to programs",				a->q_alias->q_ruser, MyHostName);		}		else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))		{			a->q_flags |= QBADADDR;			usrerr("550 Address %s is unsafe for mailing to programs",				a->q_alias->q_paddr);		}	}	/*	**  Look up this person in the recipient list.	**	If they are there already, return, otherwise continue.	**	If the list is empty, just add it.  Notice the cute	**	hack to make from addresses suppress things correctly:	**	the QDONTSEND bit will be set in the send list.	**	[Please note: the emphasis is on "hack."]	*/	for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)	{		if (sameaddr(q, a))		{			if (tTd(26, 1))			{				printf("%s in sendq: ", a->q_paddr);				printaddr(q, FALSE);			}			if (!bitset(QPRIMARY, q->q_flags))			{				if (!bitset(QDONTSEND, a->q_flags))					message("duplicate suppressed");				q->q_flags |= a->q_flags;			}			else if (bitset(QSELFREF, q->q_flags))				q->q_flags |= a->q_flags & ~QDONTSEND;			a = q;			goto testselfdestruct;		}	}	/* add address on list */	*pq = a;	a->q_next = NULL;	/*	**  Alias the name and handle special mailer types.	*/  trylocaluser:	if (tTd(29, 7))		printf("at trylocaluser %s\n", a->q_user);	if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags))		goto testselfdestruct;	if (m == InclMailer)	{		a->q_flags |= QDONTSEND;		if (a->q_alias == NULL)		{			a->q_flags |= QBADADDR;			usrerr("550 Cannot mail directly to :include:s");		}		else		{			int ret;			message("including file %s", a->q_user);			ret = include(a->q_user, FALSE, a, sendq, e);			if (transienterror(ret))			{#ifdef LOG				if (LogLevel > 2)					syslog(LOG_ERR, "%s: include %s: transient error: %s",						e->e_id == NULL ? "NOQUEUE" : e->e_id,						a->q_user, errstring(ret));#endif				a->q_flags |= QQUEUEUP;				a->q_flags &= ~QDONTSEND;				usrerr("451 Cannot open %s: %s",					a->q_user, errstring(ret));			}			else if (ret != 0)			{				a->q_flags |= QBADADDR;				usrerr("550 Cannot open %s: %s",					a->q_user, errstring(ret));			}		}	}	else if (m == FileMailer)	{		extern bool writable();		/* check if writable or creatable */		if (a->q_alias == NULL)		{			a->q_flags |= QBADADDR;			usrerr("550 Cannot mail directly to files");		}		else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))		{			a->q_flags |= QBADADDR;			usrerr("550 User %s@%s doesn't have a valid shell for mailing to files",				a->q_alias->q_ruser, MyHostName);		}		else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))		{			a->q_flags |= QBADADDR;			usrerr("550 Address %s is unsafe for mailing to files",				a->q_alias->q_paddr);		}		else if (!writable(buf, getctladdr(a), SFF_ANYFILE))		{			a->q_flags |= QBADADDR;			giveresponse(EX_CANTCREAT, m, NULL, a->q_alias, e);		}	}	if (m != LocalMailer)	{		if (!bitset(QDONTSEND, a->q_flags))			e->e_nrcpts++;		goto testselfdestruct;	}	/* try aliasing */	alias(a, sendq, e);# ifdef USERDB	/* if not aliased, look it up in the user database */	if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags))	{		extern int udbexpand();		if (udbexpand(a, sendq, e) == EX_TEMPFAIL)		{			a->q_flags |= QQUEUEUP;			if (e->e_message == NULL)				e->e_message = newstr("Deferred: user database error");# ifdef LOG			if (LogLevel > 8)				syslog(LOG_INFO, "%s: deferred: udbexpand: %s",					e->e_id == NULL ? "NOQUEUE" : e->e_id,					errstring(errno));# endif			message("queued (user database error): %s",				errstring(errno));			e->e_nrcpts++;			goto testselfdestruct;		}	}# endif	/* if it was an alias or a UDB expansion, just return now */	if (bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags))		goto testselfdestruct;	/*	**  If we have a level two config file, then pass the name through	**  Ruleset 5 before sending it off.  Ruleset 5 has the right	**  to send rewrite it to another mailer.  This gives us a hook	**  after local aliasing has been done.	*/	if (tTd(29, 5))	{		printf("recipient: testing local?  cl=%d, rr5=%x\n\t",			ConfigLevel, RewriteRules[5]);		printaddr(a, FALSE);	}	if (!bitset(QNOTREMOTE, a->q_flags) && ConfigLevel >= 2 &&	    RewriteRules[5] != NULL)	{		maplocaluser(a, sendq, e);	}	/*	**  If it didn't get rewritten to another mailer, go ahead	**  and deliver it.	*/	if (!bitset(QDONTSEND|QQUEUEUP, a->q_flags))	{		auto bool fuzzy;		register struct passwd *pw;		extern struct passwd *finduser();		/* warning -- finduser may trash buf */		pw = finduser(buf, &fuzzy);		if (pw == NULL)		{			a->q_flags |= QBADADDR;			giveresponse(EX_NOUSER, m, NULL, a->q_alias, e);		}		else		{			char nbuf[MAXNAME];			if (fuzzy)			{				/* name was a fuzzy match */				a->q_user = newstr(pw->pw_name);				if (findusercount++ > 3)				{					a->q_flags |= QBADADDR;					usrerr("554 aliasing/forwarding loop for %s broken",						pw->pw_name);					return (a);				}				/* see if it aliases */				(void) strcpy(buf, pw->pw_name);				goto trylocaluser;			}			if (strcmp(pw->pw_dir, "/") == 0)				a->q_home = "";			else				a->q_home = newstr(pw->pw_dir);			a->q_uid = pw->pw_uid;			a->q_gid = pw->pw_gid;			a->q_ruser = newstr(pw->pw_name);			a->q_flags |= QGOODUID;			buildfname(pw->pw_gecos, pw->pw_name, nbuf);			if (nbuf[0] != '\0')				a->q_fullname = newstr(nbuf);			if (pw->pw_shell != NULL && pw->pw_shell[0] != '\0' &&			    !usershellok(pw->pw_shell))			{				a->q_flags |= QBOGUSSHELL;			}			if (!quoted)				forward(a, sendq, e);		}	}	if (!bitset(QDONTSEND, a->q_flags))		e->e_nrcpts++;  testselfdestruct:	if (tTd(26, 8))	{		printf("testselfdestruct: ");		printaddr(a, TRUE);	}	if (a->q_alias == NULL && a != &e->e_from &&	    bitset(QDONTSEND, a->q_flags))	{		q = *sendq;		while (q != NULL && bitset(QDONTSEND, q->q_flags))			q = q->q_next;		if (q == NULL)		{			a->q_flags |= QBADADDR;			usrerr("554 aliasing/forwarding loop broken");		}	}	return (a);}/***  FINDUSER -- find the password entry for a user.****	This looks a lot like getpwnam, except that it may want to**	do some fancier pattern matching in /etc/passwd.****	This routine contains most of the time of many sendmail runs.**	It deserves to be optimized.****	Parameters:**		name -- the name to match against.**		fuzzyp -- an outarg that is set to TRUE if this entry**			was found using the fuzzy matching algorithm;**			set to FALSE otherwise.****	Returns:**		A pointer to a pw struct.**		NULL if name is unknown or ambiguous.****	Side Effects:**		may modify name.*/struct passwd *finduser(name, fuzzyp)	char *name;	bool *fuzzyp;{	register struct passwd *pw;	register char *p;	extern struct passwd *getpwent();	extern struct passwd *getpwnam();	if (tTd(29, 4))		printf("finduser(%s): ", name);

⌨️ 快捷键说明

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