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

📄 deliver.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (tTd(11, 2))				printf("openmailer: running as r/euid=%d/%d\n",					getuid(), geteuid());			/* move into some "safe" directory */			if (m->m_execdir != NULL)			{				char *p, *q;				char buf[MAXLINE];				for (p = m->m_execdir; p != NULL; p = q)				{					q = strchr(p, ':');					if (q != NULL)						*q = '\0';					expand(p, buf, &buf[sizeof buf] - 1, e);					if (q != NULL)						*q++ = ':';					if (tTd(11, 20))						printf("openmailer: trydir %s\n",							buf);					if (buf[0] != '\0' && chdir(buf) >= 0)						break;				}			}			/* arrange to filter std & diag output of command */			if (clever)			{				(void) close(rpvect[0]);				if (dup2(rpvect[1], STDOUT_FILENO) < 0)				{					syserr("%s... openmailer(%s): cannot dup pipe %d for stdout",						e->e_to, m->m_name, rpvect[1]);					_exit(EX_OSERR);				}				(void) close(rpvect[1]);			}			else if (OpMode == MD_SMTP || OpMode == MD_DAEMON ||				  HoldErrs || DisConnected)			{				/* put mailer output in transcript */				if (dup2(fileno(e->e_xfp), STDOUT_FILENO) < 0)				{					syserr("%s... openmailer(%s): cannot dup xscript %d for stdout",						e->e_to, m->m_name,						fileno(e->e_xfp));					_exit(EX_OSERR);				}			}			if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0)			{				syserr("%s... openmailer(%s): cannot dup stdout for stderr",					e->e_to, m->m_name);				_exit(EX_OSERR);			}			/* arrange to get standard input */			(void) close(mpvect[1]);			if (dup2(mpvect[0], STDIN_FILENO) < 0)			{				syserr("%s... openmailer(%s): cannot dup pipe %d for stdin",					e->e_to, m->m_name, mpvect[0]);				_exit(EX_OSERR);			}			(void) close(mpvect[0]);			/* arrange for all the files to be closed */			for (i = 3; i < DtableSize; i++)			{				register int j;				if ((j = fcntl(i, F_GETFD, 0)) != -1)					(void) fcntl(i, F_SETFD, j | 1);			}			/*			**  Set up the mailer environment			**	TZ is timezone information.			**	SYSTYPE is Apollo software sys type (required).			**	ISP is Apollo hardware system type (required).			*/			i = 0;			env[i++] = "AGENT=sendmail";			for (ep = environ; *ep != NULL; ep++)			{				if (strncmp(*ep, "TZ=", 3) == 0 ||				    strncmp(*ep, "ISP=", 4) == 0 ||				    strncmp(*ep, "SYSTYPE=", 8) == 0)					env[i++] = *ep;			}			env[i++] = NULL;			/* run disconnected from terminal */			(void) setsid();			/* try to execute the mailer */			execve(m->m_mailer, pv, env);			saveerrno = errno;			syserr("Cannot exec %s", m->m_mailer);			if (m == LocalMailer || transienterror(saveerrno))				_exit(EX_OSERR);			_exit(EX_UNAVAILABLE);		}		/*		**  Set up return value.		*/		mci = (MCI *) xalloc(sizeof *mci);		bzero((char *) mci, sizeof *mci);		mci->mci_mailer = m;		mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN;		mci->mci_pid = pid;		(void) close(mpvect[0]);		mci->mci_out = fdopen(mpvect[1], "w");		if (mci->mci_out == NULL)		{			syserr("deliver: cannot create mailer output channel, fd=%d",				mpvect[1]);			(void) close(mpvect[1]);			if (clever)			{				(void) close(rpvect[0]);				(void) close(rpvect[1]);			}			rcode = EX_OSERR;			goto give_up;		}		if (clever)		{			(void) close(rpvect[1]);			mci->mci_in = fdopen(rpvect[0], "r");			if (mci->mci_in == NULL)			{				syserr("deliver: cannot create mailer input channel, fd=%d",					mpvect[1]);				(void) close(rpvect[0]);				fclose(mci->mci_out);				mci->mci_out = NULL;				rcode = EX_OSERR;				goto give_up;			}		}		else		{			mci->mci_flags |= MCIF_TEMP;			mci->mci_in = NULL;		}	}	/*	**  If we are in SMTP opening state, send initial protocol.	*/	if (clever && mci->mci_state != MCIS_CLOSED)	{		smtpinit(m, mci, e);	}	if (tTd(11, 1))	{		printf("openmailer: ");		mci_dump(mci, FALSE);	}	if (mci->mci_state != MCIS_OPEN)	{		/* couldn't open the mailer */		rcode = mci->mci_exitstat;		errno = mci->mci_errno;#if NAMED_BIND		h_errno = mci->mci_herrno;#endif		if (rcode == EX_OK)		{			/* shouldn't happen */			syserr("554 deliver: rcode=%d, mci_state=%d, sig=%s",				rcode, mci->mci_state, firstsig);			rcode = EX_SOFTWARE;		}		else if (rcode == EX_TEMPFAIL && curhost != NULL && *curhost != '\0')		{			/* try next MX site */			goto tryhost;		}	}	else if (!clever)	{		/*		**  Format and send message.		*/		putfromline(mci, e);		(*e->e_puthdr)(mci, e);		putline("\n", mci);		(*e->e_putbody)(mci, e, NULL);		/* get the exit status */		rcode = endmailer(mci, e, pv);	}	else#ifdef SMTP	{		/*		**  Send the MAIL FROM: protocol		*/		rcode = smtpmailfrom(m, mci, e);		if (rcode == EX_OK)		{			register char *t = tobuf;			register int i;			/* send the recipient list */			tobuf[0] = '\0';			for (to = tochain; to != NULL; to = to->q_tchain)			{				e->e_to = to->q_paddr;				if ((i = smtprcpt(to, m, mci, e)) != EX_OK)				{					markfailure(e, to, i);					giveresponse(i, m, mci, ctladdr, e);				}				else				{					*t++ = ',';					for (p = to->q_paddr; *p; *t++ = *p++)						continue;					*t = '\0';				}			}			/* now send the data */			if (tobuf[0] == '\0')			{				rcode = EX_OK;				e->e_to = NULL;				if (bitset(MCIF_CACHED, mci->mci_flags))					smtprset(m, mci, e);			}			else			{				e->e_to = tobuf + 1;				rcode = smtpdata(m, mci, e);			}			/* now close the connection */			if (!bitset(MCIF_CACHED, mci->mci_flags))				smtpquit(m, mci, e);		}		if (rcode != EX_OK && curhost != NULL && *curhost != '\0')		{			/* try next MX site */			goto tryhost;		}	}#else /* not SMTP */	{		syserr("554 deliver: need SMTP compiled to use clever mailer");		rcode = EX_CONFIG;		goto give_up;	}#endif /* SMTP */#if NAMED_BIND	if (ConfigLevel < 2)		_res.options |= RES_DEFNAMES | RES_DNSRCH;	/* XXX */#endif	/* arrange a return receipt if requested */	if (rcode == EX_OK && e->e_receiptto != NULL &&	    bitnset(M_LOCALMAILER, m->m_flags))	{		e->e_flags |= EF_SENDRECEIPT;		/* do we want to send back more info? */	}	/*	**  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.	*/  give_up:	if (tobuf[0] != '\0')		giveresponse(rcode, m, mci, ctladdr, e);	for (to = tochain; to != NULL; to = to->q_tchain)	{		if (rcode != EX_OK)			markfailure(e, to, rcode);		else		{			to->q_flags |= QSENT;			e->e_nsent++;			if (e->e_receiptto != NULL &&			    bitnset(M_LOCALMAILER, m->m_flags))			{				fprintf(e->e_xfp, "%s... Successfully delivered\n",					to->q_paddr);			}		}	}	/*	**  Restore state and return.	*/#ifdef XDEBUG	{		char wbuf[MAXLINE];		/* make absolutely certain 0, 1, and 2 are in use */		sprintf(wbuf, "%s... end of deliver(%s)",			e->e_to == NULL ? "NO-TO-LIST" : e->e_to,			m->m_name);		checkfd012(wbuf);	}#endif	errno = 0;	define('g', (char *) NULL, e);	return (rcode);}/***  MARKFAILURE -- mark a failure on a specific address.****	Parameters:**		e -- the envelope we are sending.**		q -- the address to mark.**		rcode -- the code signifying the particular failure.****	Returns:**		none.****	Side Effects:**		marks the address (and possibly the envelope) with the**			failure so that an error will be returned or**			the message will be queued, as appropriate.*/markfailure(e, q, rcode)	register ENVELOPE *e;	register ADDRESS *q;	int rcode;{	char buf[MAXLINE];	switch (rcode)	{	  case EX_OK:		break;	  case EX_TEMPFAIL:	  case EX_IOERR:	  case EX_OSERR:		q->q_flags |= QQUEUEUP;		break;	  default:		q->q_flags |= QBADADDR;		break;	}}/***  ENDMAILER -- Wait for mailer to terminate.****	We should never get fatal errors (e.g., segmentation**	violation), so we report those specially.  For other**	errors, we choose a status message (into statmsg),**	and if it represents an error, we print it.****	Parameters:**		pid -- pid of mailer.**		e -- the current envelope.**		pv -- the parameter vector that invoked the mailer**			(for error messages).****	Returns:**		exit code of mailer.****	Side Effects:**		none.*/endmailer(mci, e, pv)	register MCI *mci;	register ENVELOPE *e;	char **pv;{	int st;	/* close any connections */	if (mci->mci_in != NULL)		(void) xfclose(mci->mci_in, mci->mci_mailer->m_name, "mci_in");	if (mci->mci_out != NULL)		(void) xfclose(mci->mci_out, mci->mci_mailer->m_name, "mci_out");	mci->mci_in = mci->mci_out = NULL;	mci->mci_state = MCIS_CLOSED;	/* in the IPC case there is nothing to wait for */	if (mci->mci_pid == 0)		return (EX_OK);	/* wait for the mailer process to die and collect status */	st = waitfor(mci->mci_pid);	if (st == -1)	{		syserr("endmailer %s: wait", pv[0]);		return (EX_SOFTWARE);	}	if (WIFEXITED(st))	{		/* normal death -- return status */		return (WEXITSTATUS(st));	}	/* it died a horrid death */	syserr("451 mailer %s died with signal %o",		mci->mci_mailer->m_name, st);	/* log the arguments */	if (pv != NULL && e->e_xfp != NULL)	{		register char **av;		fprintf(e->e_xfp, "Arguments:");		for (av = pv; *av != NULL; av++)			fprintf(e->e_xfp, " %s", *av);		fprintf(e->e_xfp, "\n");	}	ExitStat = EX_TEMPFAIL;	return (EX_TEMPFAIL);}/***  GIVERESPONSE -- Interpret an error response from a mailer****	Parameters:**		stat -- the status code from the mailer (high byte**			only; core dumps must have been taken care of**			already).**		m -- the mailer info for this mailer.**		mci -- the mailer connection info -- can be NULL if the**			response is given before the connection is made.**		ctladdr -- the controlling address for the recipient**			address(es).**		e -- the current envelope.****	Returns:**		none.****	Side Effects:**		Errors may be incremented.**		ExitStat may be set.*/giveresponse(stat, m, mci, ctladdr, e)	int stat;	register MAILER *m;	register MCI *mci;	ADDRESS *ctladdr;	ENVELOPE *e;{	register const char *statmsg;	extern char *SysExMsg[];	register int i;	extern int N_SysEx;	char buf[MAXLINE];	/*	**  Compute status message from code.	*/	i = stat - EX__BASE;	if (stat == 0)	{		statmsg = "250 Sent";		if (e->e_statmsg != NULL)		{			(void) sprintf(buf, "%s (%s)", statmsg, e->e_statmsg);			statmsg = buf;		}	}	else if (i < 0 || i > N_SysEx)	{		(void) sprintf(buf, "554 unknown mailer error %d", stat);		stat = EX_UNAVAILABLE;		statmsg = buf;	}	else if (stat == EX_TEMPFAIL)	{		(void) strcpy(buf, SysExMsg[i] + 1);#if NAMED_BIND		if (h_errno == TRY_AGAIN)			statmsg = errstring(h_errno+E_DNSBASE);		else#endif		{			if (errno != 0)				statmsg = errstring(errno);			else			{#ifdef SMTP				statmsg = SmtpError;#else /* SMTP */				statmsg = NULL;#endif /* SMTP */			}		}		if (statmsg != NULL && statmsg[0] != '\0')		{			(void) strcat(buf, ": ");			(void) strcat(buf, statmsg);		}		statmsg = buf;	}#if NAMED_BIND	else if (stat == EX_NOHOST && h_errno != 0)	{		statmsg = errstring(h_errno + E_DNSBASE);		(void) sprintf(buf, "%s (%s)", SysExMsg[i], statmsg);		statmsg = buf;	}#endif	else	{		statmsg = SysExMsg[i];		if (*statmsg++ == ':')		{			(void) sprintf(buf, "%s: %s", statmsg, errstring(errno));			statmsg = buf;		}	}	/*	**  Print the message as appropriate	*/	if (stat == EX_OK || stat == EX_TEMPFAIL)	{		extern char MsgBuf[];		message("%s", &statmsg[4]);		if (stat == EX_TEMPFAIL && e->e_xfp != NULL)			fprintf(e->e_xfp, "%s\n", &MsgBuf[4]);	}	else	{		Errors++;		usrerr(statmsg, errstring(errno));	}	/*	**  Final cleanup.	**	Log a record of the transaction.  Compute the new	**	ExitStat -- if we already had an error, stick with	**	that.	*/	if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6))		logdelivery(m, mci, &statmsg[4], ctladdr, e);	if (tTd(11, 2))		printf("giveresponse: stat=%d, e->e_message=%s\n",			stat, e->e_message);	if (stat != EX_TEMPFAIL)		setstat(stat);	if (stat != EX_OK && (stat != EX_TEMPFAIL || e->e_message == NULL))	{		if (e->e_message != NULL)			free(e->e_message);		e->e_message = newstr(&statmsg[4]);	}	errno = 0;#if NAMED_BIND	h_errno = 0;#endif}/***  LOGDELIVERY -- log the delivery in the system log****	Care is taken to avoid logging lines that are too long, because**	some versions of syslog have an unfortunate proclivity for core**	dumping.  This is a hack, to be sure, that is at best empirical.****	Parameters:**		m -- the mailer info.  Can be NULL for initial queue.**		mci -- the mailer connection info -- can be NULL if the**			log is occuring when no connection is active.**		stat -- the message to print for the status.**		ctladdr -- the controlling address for the to list.**		e -- the current envelope.****	Returns:**		none****	Side Effects:**		none*/

⌨️ 快捷键说明

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