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

📄 deliver.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
	{		(void) sprintf(buf, "554 unknown mailer error %d", stat);		stat = EX_UNAVAILABLE;		statmsg = buf;	}	else if (stat == EX_TEMPFAIL)	{		(void) strcpy(buf, SysExMsg[i]);		if (h_errno == TRY_AGAIN)		{			extern char *errstring();			statmsg = errstring(h_errno+MAX_ERRNO);		}		else		{			if (errno != 0)			{				extern char *errstring();				statmsg = errstring(errno);			}			else			{#ifdef SMTP				extern char SmtpError[];				statmsg = SmtpError;#else SMTP				statmsg = NULL;#endif SMTP			}		}		if (statmsg != NULL && statmsg[0] != '\0')		{			(void) strcat(buf, ": ");			(void) strcat(buf, statmsg);		}		statmsg = buf;	}	else	{		statmsg = SysExMsg[i];	}	/*	**  Print the message as appropriate	*/	if (stat == EX_OK || stat == EX_TEMPFAIL)		message(Arpa_Info, &statmsg[4]);	else	{		Errors++;		usrerr(statmsg);	}	/*	**  Final cleanup.	**	Log a record of the transaction.  Compute the new	**	ExitStat -- if we already had an error, stick with	**	that.	*/	if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2))		logdelivery(&statmsg[4]);	if (stat != EX_TEMPFAIL)		setstat(stat);	if (stat != EX_OK)	{		if (e->e_message != NULL)			free(e->e_message);		e->e_message = newstr(&statmsg[4]);	}	errno = 0;	h_errno = 0;}/***  LOGDELIVERY -- log the delivery in the system log****	Parameters:**		stat -- the message to print for the status****	Returns:**		none****	Side Effects:**		none*/#define LOG_MAXTO 100logdelivery(stat)	char *stat;{# ifdef LOG	extern char *pintvl();	char *tp;	char *delay;	int len;	/*	 * imcd/jch - fix to long log lines	 *	 * The syslog V2.4 facility is brain dead.  It only handles	 * 5 arguments to sprintf!  It core dumps if the message is	 * longer that 1000 bytes...  The daemon corrupts its time counter...	 *	 * Thus this code:	 */	delay = pintvl(curtime() - CurEnv->e_ctime, TRUE);	len=strlen(CurEnv->e_to);	if (len <= LOG_MAXTO)		return(syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s",			CurEnv->e_id, CurEnv->e_to, delay, stat));	for (tp=CurEnv->e_to; len>0; len -= LOG_MAXTO, tp += LOG_MAXTO)		syslog(LOG_INFO, "%s: to=%s%.*s", CurEnv->e_id,			(tp==CurEnv->e_to)?"":"(cont) ", LOG_MAXTO, tp);	syslog(LOG_INFO, "%s: delay=%s, stat=%s", CurEnv->e_id, delay, stat);# endif LOG}/***  PUTFROMLINE -- output a UNIX-style from line (or whatever)****	This can be made an arbitrary message separator by changing $l****	One of the ugliest hacks seen by human eyes is contained herein:**	UUCP wants those stupid "remote from <host>" lines.  Why oh why**	does a well-meaning programmer such as myself have to deal with**	this kind of antique garbage????****	Parameters:**		fp -- the file to output to.**		m -- the mailer describing this entry.****	Returns:**		none****	Side Effects:**		outputs some text to fp.*/putfromline(fp, m)	register FILE *fp;	register MAILER *m;{	char *template = "\001l\n";	char buf[MAXLINE];	if (bitnset(M_NHDR, m->m_flags))		return;# ifdef UGLYUUCP	if (bitnset(M_UGLYUUCP, m->m_flags))	{		char *bang;		char xbuf[MAXLINE];		expand("\001g", buf, &buf[sizeof buf - 1], CurEnv);		bang = index(buf, '!');		if (bang == NULL)			syserr("No ! in UUCP! (%s)", buf);		else		{			*bang++ = '\0';			(void) sprintf(xbuf, "From %s  \001d remote from %s\n", bang, buf);			template = xbuf;		}	}# endif UGLYUUCP	expand(template, buf, &buf[sizeof buf - 1], CurEnv);	putline(buf, fp, m);}/***  PUTBODY -- put the body of a message.****	Parameters:**		fp -- file to output onto.**		m -- a mailer descriptor to control output format.**		e -- the envelope to put out.****	Returns:**		none.****	Side Effects:**		The message is written onto fp.*/putbody(fp, m, e)	FILE *fp;	MAILER *m;	register ENVELOPE *e;{	char buf[MAXLINE];	/*	**  Output the body of the message	*/	if (e->e_dfp == NULL)	{		if (e->e_df != NULL)		{			e->e_dfp = fopen(e->e_df, "r");			if (e->e_dfp == NULL)				syserr("Cannot open %s", e->e_df);		}		else			putline("<<< No Message Collected >>>", fp, m);	}	if (e->e_dfp != NULL)	{		rewind(e->e_dfp);		while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL)		{			if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) &&			    strncmp(buf, "From", 4) == 0)				(void) putc('>', fp);			putline(buf, fp, m);		}		if (ferror(e->e_dfp))		{			syserr("putbody: read error");			ExitStat = EX_IOERR;		}	}	(void) fflush(fp);	if (ferror(fp) && errno != EPIPE)	{		syserr("putbody: write error");		ExitStat = EX_IOERR;	}	errno = 0;}/***  MAILFILE -- Send a message to a file.****	If the file has the setuid/setgid bits set, but NO execute**	bits, sendmail will try to become the owner of that file**	rather than the real user.  Obviously, this only works if**	sendmail runs as root.****	This could be done as a subordinate mailer, except that it**	is used implicitly to save messages in ~/dead.letter.  We**	view this as being sufficiently important as to include it**	here.  For example, if the system is dying, we shouldn't have**	to create another process plus some pipes to save the message.****	Parameters:**		filename -- the name of the file to send to.**		ctladdr -- the controlling address header -- includes**			the userid/groupid to be when sending.****	Returns:**		The exit code associated with the operation.****	Side Effects:**		none.*/mailfile(filename, ctladdr)	char *filename;	ADDRESS *ctladdr;{	register FILE *f;	register int pid;	/*	**  Fork so we can change permissions here.	**	Note that we MUST use fork, not vfork, because of	**	the complications of calling subroutines, etc.	*/	DOFORK(fork);	if (pid < 0)		return (EX_OSERR);	else if (pid == 0)	{		/* child -- actually write to file */		struct stat stb;		(void) signal(SIGINT, SIG_DFL);		(void) signal(SIGHUP, SIG_DFL);		(void) signal(SIGTERM, SIG_DFL);		(void) umask(OldUmask);		if (stat(filename, &stb) < 0)		{			errno = 0;			stb.st_mode = 0666;		}		if (bitset(0111, stb.st_mode))			exit(EX_CANTCREAT);		if (ctladdr == NULL)			ctladdr = &CurEnv->e_from;		if (!bitset(S_ISGID, stb.st_mode) || setgid(stb.st_gid) < 0)		{			if (ctladdr->q_uid == 0) {				(void) setgid(DefGid);				(void) initgroups(DefUser, DefGid);			} else {				(void) setgid(ctladdr->q_gid);				(void) initgroups(ctladdr->q_ruser ?					ctladdr->q_ruser : ctladdr->q_user,					ctladdr->q_gid);			}		}		if (!bitset(S_ISUID, stb.st_mode) || setuid(stb.st_uid) < 0)		{			if (ctladdr->q_uid == 0)				(void) setuid(DefUid);			else				(void) setuid(ctladdr->q_uid);		}		f = dfopen(filename, "a");		if (f == NULL)			exit(EX_CANTCREAT);		putfromline(f, ProgMailer);		(*CurEnv->e_puthdr)(f, ProgMailer, CurEnv);		putline("\n", f, ProgMailer);		(*CurEnv->e_putbody)(f, ProgMailer, CurEnv);		putline("\n", f, ProgMailer);		(void) fclose(f);		(void) fflush(stdout);		/* reset ISUID & ISGID bits for paranoid systems */		(void) chmod(filename, (int) stb.st_mode);		exit(EX_OK);		/*NOTREACHED*/	}	else	{		/* parent -- wait for exit status */		int st;		st = waitfor(pid);		if ((st & 0377) != 0)			return (EX_UNAVAILABLE);		else			return ((st >> 8) & 0377);	}}/***  SENDALL -- actually send all the messages.****	Parameters:**		e -- the envelope to send.**		mode -- the delivery mode to use.  If SM_DEFAULT, use**			the current SendMode.****	Returns:**		none.****	Side Effects:**		Scans the send lists and sends everything it finds.**		Delivers any appropriate error messages.**		If we are running in a non-interactive mode, takes the**			appropriate action.*/sendall(e, mode)	ENVELOPE *e;	char mode;{	register ADDRESS *q;	bool oldverbose;	int pid;	/* determine actual delivery mode */	if (mode == SM_DEFAULT)	{		extern bool shouldqueue();		if (shouldqueue(e->e_msgpriority))			mode = SM_QUEUE;		else			mode = SendMode;	}#ifdef DEBUG	if (tTd(13, 1))	{		printf("\nSENDALL: mode %c, sendqueue:\n", mode);		printaddr(e->e_sendqueue, TRUE);	}#endif DEBUG	/*	**  Do any preprocessing necessary for the mode we are running.	**	Check to make sure the hop count is reasonable.	**	Delete sends to the sender in mailing lists.	*/	CurEnv = e;	if (e->e_hopcount > MAXHOP)	{		syserr("sendall: too many hops (%d max)", MAXHOP);		return;	}	if (!MeToo)	{		extern ADDRESS *recipient();		e->e_from.q_flags |= QDONTSEND;		(void) recipient(&e->e_from, &e->e_sendqueue);	}# ifdef QUEUE	if ((mode == SM_QUEUE || mode == SM_FORK ||	     (mode != SM_VERIFY && SuperSafe)) &&	    !bitset(EF_INQUEUE, e->e_flags))		queueup(e, TRUE, mode == SM_QUEUE);#endif QUEUE	oldverbose = Verbose;	switch (mode)	{	  case SM_VERIFY:		Verbose = TRUE;		break;	  case SM_QUEUE:		e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE;		return;	  case SM_FORK:		if (e->e_xfp != NULL)			(void) fflush(e->e_xfp);		pid = fork();		if (pid < 0)		{			mode = SM_DELIVER;			break;		}		else if (pid > 0)		{			/* be sure we leave the temp files to our child */			e->e_id = e->e_df = NULL;			return;		}		/* double fork to avoid zombies */		if (fork() > 0)			exit(EX_OK);		/* be sure we are immune from the terminal */		disconnect(FALSE);		break;	}	/*	**  Run through the list and send everything.	*/	for (q = e->e_sendqueue; q != NULL; q = q->q_next)	{		if (mode == SM_VERIFY)		{			e->e_to = q->q_paddr;			if (!bitset(QDONTSEND|QBADADDR, q->q_flags))				message(Arpa_Info, "deliverable");		}		else			(void) deliver(e, q);	}	Verbose = oldverbose;	/*	**  Now run through and check for errors.	*/	if (mode == SM_VERIFY)		return;	for (q = e->e_sendqueue; q != NULL; q = q->q_next)	{		register ADDRESS *qq;# ifdef DEBUG		if (tTd(13, 3))		{			printf("Checking ");			printaddr(q, FALSE);		}# endif DEBUG		/* only send errors if the message failed */		if (!bitset(QBADADDR, q->q_flags))			continue;		/* we have an address that failed -- find the parent */		for (qq = q; qq != NULL; qq = qq->q_alias)		{			char obuf[MAXNAME + 6];			extern char *aliaslookup();			/* we can only have owners for local addresses */			if (!bitnset(M_LOCAL, qq->q_mailer->m_flags))				continue;			/* see if the owner list exists */			(void) strcpy(obuf, "owner-");			if (strncmp(qq->q_user, "owner-", 6) == 0)				(void) strcat(obuf, "owner");			else				(void) strcat(obuf, qq->q_user);			if (aliaslookup(obuf) == NULL)				continue;# ifdef DEBUG			if (tTd(13, 4))				printf("Errors to %s\n", obuf);# endif DEBUG			/* owner list exists -- add it to the error queue */			sendtolist(obuf, (ADDRESS *) NULL, &e->e_errorqueue);			ErrorMode = EM_MAIL;			break;		}		/* if we did not find an owner, send to the sender */		if (qq == NULL && bitset(QBADADDR, q->q_flags))			sendtolist(e->e_from.q_paddr, qq, &e->e_errorqueue);	}	if (mode == SM_FORK)		finis();}

⌨️ 快捷键说明

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