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

📄 deliver.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)deliver.c	4.1	(ULTRIX)	7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1987 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************/# include <sys/ioctl.h># include <signal.h># include <errno.h># include "sendmail.h"# include <sys/stat.h># include <netdb.h># include <sys/svcinfo.h># include <arpa/nameser.h># include <resolv.h>extern int h_errno;/***  DELIVER -- Deliver a message to a list of addresses.****	This routine delivers to everyone on the same host as the**	user on the head of the list.  It is clever about mailers**	that don't handle multiple users.  It is NOT guaranteed**	that it will deliver to all these addresses however -- so**	deliver should be called once for each address on the**	list.****	Parameters:**		e -- the envelope to deliver.**		firstto -- head of the address list to deliver to.****	Returns:**		zero -- successfully delivered.**		else -- some failure, see ExitStat for more info.****	Side Effects:**		The standard input is passed off to someone.*/deliver(e, firstto)	register ENVELOPE *e;	ADDRESS *firstto;{	char *host;			/* host being sent to */	char *user;			/* user being sent to */	char **pvp;	register char **mvp;	register char *p;	register MAILER *m;		/* mailer for this recipient */	ADDRESS *ctladdr;	register ADDRESS *to = firstto;	bool clever = FALSE;		/* running user smtp to this mailer */	ADDRESS *tochain = NULL;	/* chain of users in this mailer call */	int rcode;			/* response code */	char *pv[MAXPV+1];	char tobuf[MAXLINE-50];		/* text line of to people */	char buf[MAXNAME];	char tfrombuf[MAXNAME];		/* translated from person */	extern bool checkcompat();	extern ADDRESS *getctladdr();	extern char *remotename();	errno = 0;	if (bitset(QDONTSEND, to->q_flags))		return (0);	m = to->q_mailer;	host = to->q_host;# ifdef DEBUG	if (tTd(10, 1))		printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n",			m->m_mno, host, to->q_user);# endif DEBUG	/*	**  If this mailer is expensive, and if we don't want to make	**  connections now, just mark these addresses and return.	**	This is useful if we want to batch connections to	**	reduce load.  This will cause the messages to be	**	queued up, and a daemon will come along to send the	**	messages later.	**		This should be on a per-mailer basis.	*/	if (NoConnect && !QueueRun && bitnset(M_EXPENSIVE, m->m_flags) &&	    !Verbose)	{		for (; to != NULL; to = to->q_next)		{			if (bitset(QDONTSEND, to->q_flags) || to->q_mailer != m)				continue;			to->q_flags |= QQUEUEUP|QDONTSEND;			e->e_to = to->q_paddr;			message(Arpa_Info, "queued");			if (LogLevel > 4)				logdelivery("queued");		}		e->e_to = NULL;		return (0);	}	/*	**  Do initial argv setup.	**	Insert the mailer name.  Notice that $x expansion is	**	NOT done on the mailer name.  Then, if the mailer has	**	a picky -f flag, we insert it as appropriate.  This	**	code does not check for 'pv' overflow; this places a	**	manifest lower limit of 4 for MAXPV.	**		The from address rewrite is expected to make	**		the address relative to the other end.	*/	/* rewrite from address, using rewriting rules */	expand("\001f", buf, &buf[sizeof buf - 1], e);	(void) strcpy(tfrombuf, remotename(buf, m, TRUE, TRUE));	define('g', tfrombuf, e);		/* translated sender address */	define('h', host, e);			/* to host */	Errors = 0;	pvp = pv;	*pvp++ = m->m_argv[0];	/* insert -f or -r flag as appropriate */	if (FromFlag && (bitnset(M_FOPT, m->m_flags) || bitnset(M_ROPT, m->m_flags)))	{		if (bitnset(M_FOPT, m->m_flags))			*pvp++ = "-f";		else			*pvp++ = "-r";		expand("\001g", buf, &buf[sizeof buf - 1], e);		*pvp++ = newstr(buf);	}	/*	**  Append the other fixed parts of the argv.  These run	**  up to the first entry containing "$u".  There can only	**  be one of these, and there are only a few more slots	**  in the pv after it.	*/	for (mvp = m->m_argv; (p = *++mvp) != NULL; )	{		while ((p = index(p, '\001')) != NULL)			if (*++p == 'u')				break;		if (p != NULL)			break;		/* this entry is safe -- go ahead and process it */		expand(*mvp, buf, &buf[sizeof buf - 1], e);		*pvp++ = newstr(buf);		if (pvp >= &pv[MAXPV - 3])		{			syserr("Too many parameters to %s before $u", pv[0]);			return (-1);		}	}	/*	**  If we have no substitution for the user name in the argument	**  list, we know that we must supply the names otherwise -- and	**  SMTP is the answer!!	*/	if (*mvp == NULL)	{		/* running SMTP */# ifdef SMTP		clever = TRUE;		*pvp = NULL;# else SMTP		/* oops!  we don't implement SMTP */		syserr("SMTP style mailer");		return (EX_SOFTWARE);# endif SMTP	}	/*	**  At this point *mvp points to the argument with $u.  We	**  run through our address list and append all the addresses	**  we can.  If we run out of space, do not fret!  We can	**  always send another copy later.	*/	tobuf[0] = '\0';	e->e_to = tobuf;	ctladdr = NULL;	for (; to != NULL; to = to->q_next)	{		/* avoid sending multiple recipients to dumb mailers */		if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags))			break;		/* if already sent or not for this host, don't send */		if (bitset(QDONTSEND, to->q_flags) ||		    strcmp(to->q_host, host) != 0 ||		    to->q_mailer != firstto->q_mailer)			continue;		/* avoid overflowing tobuf */		if (sizeof tobuf - (strlen(to->q_paddr) + strlen(tobuf) + 2) < 0)			break;# ifdef DEBUG		if (tTd(10, 1))		{			printf("\nsend to ");			printaddr(to, FALSE);		}# endif DEBUG		/* compute effective uid/gid when sending */		if (to->q_mailer == ProgMailer)			ctladdr = getctladdr(to);		user = to->q_user;		e->e_to = to->q_paddr;		to->q_flags |= QDONTSEND;		/*		**  Check to see that these people are allowed to		**  talk to each other.		*/		if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize)		{			usrerr("Message is too large; %ld bytes max", m->m_maxsize);			NoReturn = TRUE;			giveresponse(EX_UNAVAILABLE, m, e);			continue;		}		if (!checkcompat(to))		{			giveresponse(EX_UNAVAILABLE, m, e);			continue;		}		/*		**  Strip quote bits from names if the mailer is dumb		**	about them.		*/		if (bitnset(M_STRIPQ, m->m_flags))		{			stripquotes(user, TRUE);			stripquotes(host, TRUE);		}		else		{			stripquotes(user, FALSE);			stripquotes(host, FALSE);		}		/* hack attack -- delivermail compatibility */		if (m == ProgMailer && *user == '|')			user++;		/*		**  If an error message has already been given, don't		**	bother to send to this address.		**		**	>>>>>>>>>> This clause assumes that the local mailer		**	>> NOTE >> cannot do any further aliasing; that		**	>>>>>>>>>> function is subsumed by sendmail.		*/		if (bitset(QBADADDR|QQUEUEUP, to->q_flags))			continue;		/* save statistics.... */		markstats(e, to);		/*		**  See if this user name is "special".		**	If the user name has a slash in it, assume that this		**	is a file -- send it off without further ado.  Note		**	that this type of addresses is not processed along		**	with the others, so we fudge on the To person.		*/		if (m == LocalMailer)		{			if (user[0] == '/')			{				rcode = mailfile(user, getctladdr(to));				giveresponse(rcode, m, e);				continue;			}		}		/*		**  Address is verified -- add this user to mailer		**  argv, and add it to the print list of recipients.		*/		/* link together the chain of recipients */		to->q_tchain = tochain;		tochain = to;		/* create list of users for error messages */		(void) strcat(tobuf, ",");		(void) strcat(tobuf, to->q_paddr);		define('u', user, e);		/* to user */		define('z', to->q_home, e);	/* user's home */		/*		**  Expand out this user into argument list.		*/		if (!clever)		{			expand(*mvp, buf, &buf[sizeof buf - 1], e);			*pvp++ = newstr(buf);			if (pvp >= &pv[MAXPV - 2])			{				/* allow some space for trailing parms */				break;			}		}	}	/* see if any addresses still exist */	if (tobuf[0] == '\0')	{		define('g', (char *) NULL, e);		return (0);	}	/* print out messages as full list */	e->e_to = tobuf + 1;	/*	**  Fill out any parameters after the $u parameter.	*/	while (!clever && *++mvp != NULL)	{		expand(*mvp, buf, &buf[sizeof buf - 1], e);		*pvp++ = newstr(buf);		if (pvp >= &pv[MAXPV])			syserr("deliver: pv overflow after $u for %s", pv[0]);	}	*pvp++ = NULL;	/*	**  Call the mailer.	**	The argument vector gets built, pipes	**	are created as necessary, and we fork & exec as	**	appropriate.	**	If we are running SMTP, we just need to clean up.	*/	if (index(host, '.') != 0)	/* canonical if has dots */		_res.options &= ~(RES_DEFNAMES | RES_DNSRCH);	else				/* not canonical 'cause local */		_res.options &= ~(RES_DNSRCH);# ifdef SMTP	if (clever)	{		register int i;		register struct svcinfo *svcinfo;		expand("\001w", buf, &buf[sizeof buf - 1], e);		rcode = EX_OK;		nmx = 1;		mxhosts[0] = host;		if ((svcinfo = getsvc()) != NULL)			for (i = 0; (svc_lastlookup = svcinfo->svcpath[SVC_HOSTS][i++]) != SVC_LAST; )				if (svc_lastlookup == SVC_BIND)				{					if ((nmx = getmxrr(host, mxhosts, buf, &rcode)) < 0) {						if (rcode == EX_NOHOST) {							/*							 * ignore not having a host in BIND							 * as we may later find it elsewhere							 */#ifdef DEBUG							printf("getmxrr: EX_NOHOST\n");#endif DEBUG							rcode = EX_OK;							nmx = 1;							mxhosts[0] = host;						}					}					else {#ifdef DEBUG						printf("getmxrr() found the following hosts:\n");						for (i = 0; i < nmx; i++)							printf("   %s\n", mxhosts[i]);#endif						/* Just done successful MX lookup */						break;					}					/* break out of loop now have called getmxrr() */					break;				}		/* send the initial SMTP protocol		 */		if (rcode == EX_OK)		{			message(Arpa_Info, "Connecting to %s (%s)...", mxhosts[0], m->m_name);#ifndef DNUMODS			rcode = smtpinit(m, pv);#else DNUMODS			rcode = smtpinit(m, pv, e);#endif DNUMODS		}		if (rcode == EX_OK)		{			/* send the recipient list			 */			tobuf[0] = '\0';			for (to = tochain; to != NULL; to = to->q_tchain)			{				int i;				e->e_to = to->q_paddr;				i = smtprcpt(to, m);				if (i != EX_OK)				{					markfailure(e, to, i);					giveresponse(i, m, e);				}				else				{					(void) strcat(tobuf, ",");					(void) strcat(tobuf, to->q_paddr);				}			}			/* now send the data */			if (tobuf[0] == '\0')				e->e_to = NULL;			else			{				e->e_to = tobuf + 1;				rcode = smtpdata(m, e);#ifdef DNUMODS				if( rcode == EX_OK ) {				    extern int SmtpMultiStatus;				    if( ! SmtpMultiStatus )					rcode = smtpdeliverstat(m);				    else					for (tobuf[0] = '\0', to = tochain; to != NULL; to = to->q_tchain)					{					    int i;					    e->e_to = to->q_paddr;					    i = smtpdeliverstat(m);					    if( i != EX_OK ) {						markfailure(e, to, i);						giveresponse(i, m, e);					    }					    else					    {						(void) strcat(tobuf, ",");						(void) strcat(tobuf, to->q_paddr);					    }					}				}#endif DNUMODS			}			/* now close the connection */			smtpquit(m);		}	}	else# endif SMTP	{		message(Arpa_Info, "Connecting to %s (%s)...", host, m->m_name);		rcode = sendoff(e, m, pv, ctladdr);	}	_res.options |= (RES_DEFNAMES | RES_DNSRCH);	/*	**  Do final status disposal.	**	We check for something in tobuf for the SMTP case.	**	If we got a temporary failure, arrange to queue the	**		addressees.	*/	if (tobuf[0] != '\0')		giveresponse(rcode, m, e);	if (rcode != EX_OK)	{		for (to = tochain; to != NULL; to = to->q_tchain)			markfailure(e, to, rcode);	}	errno = 0;	define('g', (char *) NULL, e);	return (rcode);}/***  MARKFAILURE -- mark a failure on a specific address.****	Parameters:**		e -- the envelope we are sending.

⌨️ 快捷键说明

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