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

📄 deliver.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
**		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;{	if (rcode == EX_OK)		return;	else if (rcode != EX_TEMPFAIL)		q->q_flags |= QBADADDR;	else if (curtime() > e->e_ctime + TimeOut)	{		extern char *pintvl();		char buf[MAXLINE];		if (!bitset(EF_TIMEOUT, e->e_flags))		{			(void) sprintf(buf, "Cannot send message for %s",				pintvl(TimeOut, FALSE));			if (e->e_message != NULL)				free(e->e_message);			e->e_message = newstr(buf);			message(Arpa_Info, buf);		}		q->q_flags |= QBADADDR;		e->e_flags |= EF_TIMEOUT;	}	else		q->q_flags |= QQUEUEUP;}/***  DOFORK -- do a fork, retrying a couple of times on failure.****	This MUST be a macro, since after a vfork we are running**	two processes on the same stack!!!****	Parameters:**		none.****	Returns:**		From a macro???  You've got to be kidding!****	Side Effects:**		Modifies the ==> LOCAL <== variable 'pid', leaving:**			pid of child in parent, zero in child.**			-1 on unrecoverable error.****	Notes:**		I'm awfully sorry this looks so awful.  That's**		vfork for you.....*/# define NFORKTRIES	5# ifdef VMUNIX# define XFORK	vfork# else VMUNIX# define XFORK	fork# endif VMUNIX# define DOFORK(fORKfN) \{\	register int i;\\	for (i = NFORKTRIES; --i >= 0; )\	{\		pid = fORKfN();\		if (pid >= 0)\			break;\		if (i > 0)\			sleep((unsigned) NFORKTRIES - i);\	}\}/***  DOFORK -- simple fork interface to DOFORK.****	Parameters:**		none.****	Returns:**		pid of child in parent.**		zero in child.**		-1 on error.****	Side Effects:**		returns twice, once in parent and once in child.*/dofork(){	register int pid;	DOFORK(fork);	return (pid);}/***  SENDOFF -- send off call to mailer & collect response.****	Parameters:**		e -- the envelope to mail.**		m -- mailer descriptor.**		pvp -- parameter vector to send to it.**		ctladdr -- an address pointer controlling the**			user/groupid etc. of the mailer.****	Returns:**		exit status of mailer.****	Side Effects:**		none.*/sendoff(e, m, pvp, ctladdr)	register ENVELOPE *e;	MAILER *m;	char **pvp;	ADDRESS *ctladdr;{	auto FILE *mfile;	auto FILE *rfile;	register int i;	int pid;	/*	**  Create connection to mailer.	*/	pid = openmailer(m, pvp, ctladdr, FALSE, &mfile, &rfile);	if (pid < 0)		return (-1);	/*	**  Format and send message.	*/	putfromline(mfile, m);	(*e->e_puthdr)(mfile, m, e);	putline("\n", mfile, m);	(*e->e_putbody)(mfile, m, e);	(void) fclose(mfile);	i = endmailer(pid, pvp[0]);	/* arrange a return receipt if requested */	if (e->e_receiptto != NULL && bitnset(M_LOCAL, m->m_flags))	{		e->e_flags |= EF_SENDRECEIPT;		/* do we want to send back more info? */	}	return (i);}/***  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.**		name -- name of mailer (for error messages).****	Returns:**		exit code of mailer.****	Side Effects:**		none.*/endmailer(pid, name)	int pid;	char *name;{	int st;	/* in the IPC case there is nothing to wait for */	if (pid == 0)		return (EX_OK);	/* wait for the mailer process to die and collect status */	st = waitfor(pid);	if (st == -1)	{		syserr("endmailer %s: wait", name);		return (EX_SOFTWARE);	}	/* see if it died a horrid death */	if ((st & 0377) != 0)	{		syserr("mailer %s died with signal %o", name, st);		ExitStat = EX_TEMPFAIL;		return (EX_TEMPFAIL);	}	/* normal death -- return status */	st = (st >> 8) & 0377;	return (st);}/***  OPENMAILER -- open connection to mailer.****	Parameters:**		m -- mailer descriptor.**		pvp -- parameter vector to pass to mailer.**		ctladdr -- controlling address for user.**		clever -- create a full duplex connection.**		pmfile -- pointer to mfile (to mailer) connection.**		prfile -- pointer to rfile (from mailer) connection.****	Returns:**		pid of mailer ( > 0 ).**		-1 on error.**		zero on an IPC connection.****	Side Effects:**		creates a mailer in a subprocess.*/openmailer(m, pvp, ctladdr, clever, pmfile, prfile)	MAILER *m;	char **pvp;	ADDRESS *ctladdr;	bool clever;	FILE **pmfile;	FILE **prfile;{	int pid;	int mpvect[2];	int rpvect[2];	FILE *mfile;	FILE *rfile;	extern FILE *fdopen();# ifdef DEBUG	if (tTd(11, 1))	{		printf("openmailer:");		printav(pvp);	}# endif DEBUG	errno = 0;	CurHostName = m->m_mailer;	/*	**  Deal with the special case of mail handled through an IPC	**  connection.	**	In this case we don't actually fork.  We must be	**	running SMTP for this to work.  We will return a	**	zero pid to indicate that we are running IPC.	**  We also handle a debug version that just talks to stdin/out.	*/#ifdef DEBUG	/* check for Local Person Communication -- not for mortals!!! */	if (strcmp(m->m_mailer, "[LPC]") == 0)	{		*pmfile = stdout;		*prfile = stdin;		return (0);	}#endif DEBUG	if (strcmp(m->m_mailer, "[IPC]") == 0)	{#ifdef HOSTINFO		register STAB *st;		extern STAB *stab();#endif HOSTINFO#ifdef DAEMON		register int i, j;		register u_short port;		CurHostName = pvp[1];		if (!clever)			syserr("non-clever IPC");		if (pvp[2] != NULL)			port = atoi(pvp[2]);		else			port = 0;		for (j = 0; j < nmx; j++)		{			CurHostName = mxhosts[j];#ifdef HOSTINFO		/* see if we have already determined that this host is fried */			st = stab(mxhosts[j], ST_HOST, ST_FIND);			if (st == NULL || st->s_host.ho_exitstat == EX_OK)				i = makeconnection(mxhosts[j], port, pmfile, prfile);			else			{				i = st->s_host.ho_exitstat;				errno = st->s_host.ho_errno;			}#else HOSTINFO			i = makeconnection(mxhosts[j], port, pmfile, prfile);#endif HOSTINFO			if (i != EX_OK)			{				/*				 * Consider the case of multiple MX entries				 * for a given host where the last entry refers				 * to non-existent host.  On occasions when				 * none of the hosts are reachable, the mail				 * will bounce if the last ExitStat is				 * EX_NOHOST.  Handle this by resetting i to				 * EX_TEMPFAIL if it's not the primary MX entry				 * and it's the last MX entry.  -pbp				 */#ifdef LOG				if (i == EX_NOHOST)					syslog(LOG_WARNING, "Found non-existent host %s in MX records for %s", CurHostName, pvp[1]);#endif LOG				if (j != 0 && j == (nmx - 1))					i = EX_TEMPFAIL;#ifdef HOSTINFO				/* enter status of this host */				if (st == NULL)					st = stab(mxhosts[j], ST_HOST, ST_ENTER);				st->s_host.ho_exitstat = i;				st->s_host.ho_errno = errno;#endif HOSTINFO				ExitStat = i;				continue;			}			else				return (0);		}		return (-1);#else DAEMON		syserr("openmailer: no IPC");		return (-1);#endif DAEMON	}	/* create a pipe to shove the mail through */	if (pipe(mpvect) < 0)	{		syserr("openmailer: pipe (to mailer)");		return (-1);	}#ifdef SMTP	/* if this mailer speaks smtp, create a return pipe */	if (clever && pipe(rpvect) < 0)	{		syserr("openmailer: pipe (from mailer)");		(void) close(mpvect[0]);		(void) close(mpvect[1]);		return (-1);	}#endif SMTP	/*	**  Actually fork the mailer process.	**	DOFORK is clever about retrying.	**	**	Dispose of SIGCHLD signal catchers that may be laying	**	around so that endmail will get it.	*/	if (CurEnv->e_xfp != NULL)		(void) fflush(CurEnv->e_xfp);		/* for debugging */	(void) fflush(stdout);# ifdef SIGCHLD	(void) signal(SIGCHLD, SIG_DFL);# endif SIGCHLD	DOFORK(XFORK);	/* pid is set by DOFORK */	if (pid < 0)	{		/* failure */		syserr("openmailer: cannot fork");		(void) close(mpvect[0]);		(void) close(mpvect[1]);#ifdef SMTP		if (clever)		{			(void) close(rpvect[0]);			(void) close(rpvect[1]);		}#endif SMTP		return (-1);	}	else if (pid == 0)	{		int i;		extern int DtableSize;		/* child -- set up input & exec mailer */		/* make diagnostic output be standard output */		(void) signal(SIGINT, SIG_IGN);		(void) signal(SIGHUP, SIG_IGN);		(void) signal(SIGTERM, SIG_DFL);		/* arrange to filter standard & diag output of command */		if (clever)		{			(void) close(rpvect[0]);			(void) close(1);			(void) dup(rpvect[1]);			(void) close(rpvect[1]);		}		else if (OpMode == MD_SMTP || HoldErrs)		{			/* put mailer output in transcript */			(void) close(1);			(void) dup(fileno(CurEnv->e_xfp));		}		(void) close(2);		(void) dup(1);		/* arrange to get standard input */		(void) close(mpvect[1]);		(void) close(0);		if (dup(mpvect[0]) < 0)		{			syserr("Cannot dup to zero!");			_exit(EX_OSERR);		}		(void) close(mpvect[0]);		if (!bitnset(M_RESTR, m->m_flags))		{			if (ctladdr == NULL || ctladdr->q_uid == 0)			{				(void) setgid(DefGid);				(void) initgroups(DefUser, DefGid);				(void) setuid(DefUid);			}			else			{				(void) setgid(ctladdr->q_gid);				(void) initgroups(ctladdr->q_ruser ?					ctladdr->q_ruser : ctladdr->q_user,					ctladdr->q_gid);				(void) setuid(ctladdr->q_uid);			}		}		/* arrange for all the files to be closed */		for (i = 3; i < DtableSize; i++)#ifdef FIOCLEX			(void) ioctl(i, FIOCLEX, 0);#else FIOCLEX			(void) close(i);#endif FIOCLEX		/* try to execute the mailer */		execve(m->m_mailer, pvp, UserEnviron);#ifdef FIOCLEX		if (errno == ENOENT) {			printf("554 Cannot exec %s\n", m->m_mailer);			fflush(stdout);			_exit(EX_UNAVAILABLE);		}		syserr("Cannot exec %s", m->m_mailer);#else FIOCLEX		printf("Cannot exec '%s' errno=%d\n", m->m_mailer, errno);		(void) fflush(stdout);#endif FIOCLEX		if (m == LocalMailer || errno == EIO || errno == EAGAIN ||		    errno == ENOMEM || errno == EPROCLIM)			_exit(EX_TEMPFAIL);		else			_exit(EX_UNAVAILABLE);	}	/*	**  Set up return value.	*/	(void) close(mpvect[0]);	mfile = fdopen(mpvect[1], "w");	if (clever)	{		(void) close(rpvect[1]);		rfile = fdopen(rpvect[0], "r");	}	*pmfile = mfile;	*prfile = rfile;	return (pid);}/***  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 descriptor for this mailer.****	Returns:**		none.****	Side Effects:**		Errors may be incremented.**		ExitStat may be set.*/giveresponse(stat, m, e)	int stat;	register MAILER *m;	ENVELOPE *e;{	register char *statmsg;	extern char *SysExMsg[];	register int i;	extern int N_SysEx;	char buf[MAXLINE];#ifdef lint	if (m == NULL)		return;#endif lint	/*	**  Compute status message from code.	*/	i = stat - EX__BASE;	if (stat == 0)		statmsg = "250 Sent";	else if (i < 0 || i > N_SysEx)

⌨️ 快捷键说明

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