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

📄 deliver.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
**	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:**		If exit status is -1, ExitStat and errno are set as from**		openmailer().*/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 (EX_TEMPFAIL);	/*	**  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.*/char *enderr[] = {	"Zero",	"Hangup",	"Interrupt",	"Quit",	"Illegal instruction",	"Trace",	"IOT",	"EMT",	"Floating point exception",	"Kill",	"Bus error",	"Segmentation violation",	"Bad argument to system call",	"Broken pipe",	"Alarm clock",	"Software termination",	"Urgent",	"Stop",	"Stop from keyboard",	"Continue",	"Child status",	"Background read",	"Background write",	"I/O",	"CPU time limit exceeded",	"File size limit exceeded",	"Virtual time alarm",	"Profiling timer alarm",	"Window change"} ;#define MAXENDERR	(sizeof(enderr)/sizeof(enderr[0]))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);	if (tTd(38, 1))		syslog(LOG_INFO, "Before the wait on pid %d\n", pid);	/* wait for the mailer process to die and collect status */	st = waitfor(pid);	if (tTd(38, 1))		syslog(LOG_INFO, "After the wait on pid %d\n", pid);	if (st == -1)	{		syserr("endmailer %s: wait", name);		return (EX_SOFTWARE);	}	/* see if it died a horrid death */	if ((st & 0377) != 0)	{		if (st < 0 || st >= MAXENDERR)		    message(Arpa_Info,			"%s delivery program died with signal %d", name, st);		else		    message(Arpa_Info,			"%s delivery program died with %s signal", name, 				enderr[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, with errno set appropriately.**		zero on an IPC connection.****	Side Effects:**		creates a mailer in a subprocess.**		Sets errno if it returns -1.*/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();	extern int DtableSize;		/* main.c -- from getdtablesize() */# ifdef DEBUG	if (tTd(11, 1))	{		printf("openmailer:");		printav(pvp);	}# endif DEBUG	errno = 0;	/*	**  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 ||	    strcmp(m->m_mailer, "[TCP]") == 0)	{#ifdef DAEMON		register int i, j;		register u_short port;		CurHostName = pvp[1];		if (!clever || mx == NULL)			syserr("non-clever TCP");		if (pvp[2] != NULL)			port = atoi(pvp[2]);		else			port = 0; 		for (j = 0; j < mx->mx_number; j++)		{			CurHostName = mx->mx_hosts[j];			if (Verbose && !sameword(CurHostName, pvp[1]))				printf("mail exchanger is %s\n", CurHostName);			i = makeconnection(CurHostName, port, pmfile, prfile);			if (i == EX_OK)				return(0);		}		/* Note that errno is set for this case */		ExitStat = i;		return (-1);#else DAEMON		syserr("openmailer: no TCP");		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;		/* 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		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.	*/	if (tTd(38, 1))		syslog(LOG_INFO, "Fork with pid %d\n", pid);	(void) close(mpvect[0]);	mfile = fdopen(mpvect[1], "w");	if (clever)	{		(void) close(rpvect[1]);		rfile = fdopen(rpvect[0], "r");	} else		rfile = NULL;	*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)	{		(void) sprintf(buf, "554 unknown mailer error %d", stat);		stat = EX_UNAVAILABLE;		statmsg = buf;	}	else if (stat == EX_TEMPFAIL)	{		extern char SmtpError[];		if (AlreadyKnown)			(void) strcpy(buf, "250 Skipped");		else 			(void) strcpy(buf, SysExMsg[i]);		if (SmtpError[0] != '\0' && 			(errno == 0 || errno == ECONNRESET) )		{				(void) strcat(buf, ": ");				(void) strcat(buf, SmtpError);		}		else if (errno)		{			extern char *errstring();			(void) strcat(buf, ": ");			(void) strcat(buf, errstring(errno));		}		statmsg = buf;	}	else	{		statmsg = SysExMsg[i];	}	/*	**  Print the message as appropriate	** Note the "%s" is needed to prevent percent signs in recipient	** names from being treated as formatting commands.	*/	if (stat == EX_OK || stat == EX_TEMPFAIL)		message(Arpa_Info, "%s", &statmsg[4]);	else	{		Errors++;

⌨️ 快捷键说明

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