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

📄 savemail.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1983 Eric P. Allman * Copyright (c) 1988, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)savemail.c	8.28 (Berkeley) 3/11/94";#endif /* not lint */# include "sendmail.h"# include <pwd.h>/***  SAVEMAIL -- Save mail on error****	If mailing back errors, mail it back to the originator**	together with an error message; otherwise, just put it in**	dead.letter in the user's home directory (if he exists on**	this machine).****	Parameters:**		e -- the envelope containing the message in error.****	Returns:**		none****	Side Effects:**		Saves the letter, by writing or mailing it back to the**		sender, or by putting it in dead.letter in her home**		directory.*//* defines for state machine */# define ESM_REPORT	0	/* report to sender's terminal */# define ESM_MAIL	1	/* mail back to sender */# define ESM_QUIET	2	/* messages have already been returned */# define ESM_DEADLETTER	3	/* save in ~/dead.letter */# define ESM_POSTMASTER	4	/* return to postmaster */# define ESM_USRTMP	5	/* save in /usr/tmp/dead.letter */# define ESM_PANIC	6	/* leave the locked queue/transcript files */# define ESM_DONE	7	/* the message is successfully delivered */# ifndef _PATH_VARTMP#  define _PATH_VARTMP	"/usr/tmp/"# endifsavemail(e)	register ENVELOPE *e;{	register struct passwd *pw;	register FILE *fp;	int state;	auto ADDRESS *q = NULL;	register char *p;	MCI mcibuf;	char buf[MAXLINE+1];	extern struct passwd *getpwnam();	extern char *ttypath();	typedef int (*fnptr)();	extern bool writable();	if (tTd(6, 1))	{		printf("\nsavemail, errormode = %c, id = %s, ExitStat = %d\n  e_from=",			e->e_errormode, e->e_id == NULL ? "NONE" : e->e_id,			ExitStat);		printaddr(&e->e_from, FALSE);	}	if (e->e_id == NULL)	{		/* can't return a message with no id */		return;	}	/*	**  In the unhappy event we don't know who to return the mail	**  to, make someone up.	*/	if (e->e_from.q_paddr == NULL)	{		e->e_sender = "Postmaster";		if (parseaddr(e->e_sender, &e->e_from,			      RF_COPYPARSE|RF_SENDERADDR, '\0', NULL, e) == NULL)		{			syserr("553 Cannot parse Postmaster!");			ExitStat = EX_SOFTWARE;			finis();		}	}	e->e_to = NULL;	/*	**  Basic state machine.	**	**	This machine runs through the following states:	**	**	ESM_QUIET	Errors have already been printed iff the	**			sender is local.	**	ESM_REPORT	Report directly to the sender's terminal.	**	ESM_MAIL	Mail response to the sender.	**	ESM_DEADLETTER	Save response in ~/dead.letter.	**	ESM_POSTMASTER	Mail response to the postmaster.	**	ESM_PANIC	Save response anywhere possible.	*/	/* determine starting state */	switch (e->e_errormode)	{	  case EM_WRITE:		state = ESM_REPORT;		break;	  case EM_BERKNET:		/* mail back, but return o.k. exit status */		ExitStat = EX_OK;		/* fall through.... */	  case EM_MAIL:		state = ESM_MAIL;		break;	  case EM_PRINT:	  case '\0':		state = ESM_QUIET;		break;	  case EM_QUIET:		/* no need to return anything at all */		return;	  default:		syserr("554 savemail: bogus errormode x%x\n", e->e_errormode);		state = ESM_MAIL;		break;	}	/* if this is already an error response, send to postmaster */	if (bitset(EF_RESPONSE, e->e_flags))	{		if (e->e_parent != NULL &&		    bitset(EF_RESPONSE, e->e_parent->e_flags))		{			/* got an error sending a response -- can it */			return;		}		state = ESM_POSTMASTER;	}	while (state != ESM_DONE)	{		if (tTd(6, 5))			printf("  state %d\n", state);		switch (state)		{		  case ESM_QUIET:			if (e->e_from.q_mailer == LocalMailer)				state = ESM_DEADLETTER;			else				state = ESM_MAIL;			break;		  case ESM_REPORT:			/*			**  If the user is still logged in on the same terminal,			**  then write the error messages back to hir (sic).			*/			p = ttypath();			if (p == NULL || freopen(p, "w", stdout) == NULL)			{				state = ESM_MAIL;				break;			}			expand("\201n", buf, &buf[sizeof buf - 1], e);			printf("\r\nMessage from %s...\r\n", buf);			printf("Errors occurred while sending mail.\r\n");			if (e->e_xfp != NULL)			{				(void) fflush(e->e_xfp);				fp = fopen(queuename(e, 'x'), "r");			}			else				fp = NULL;			if (fp == NULL)			{				syserr("Cannot open %s", queuename(e, 'x'));				printf("Transcript of session is unavailable.\r\n");			}			else			{				printf("Transcript follows:\r\n");				while (fgets(buf, sizeof buf, fp) != NULL &&				       !ferror(stdout))					fputs(buf, stdout);				(void) xfclose(fp, "savemail transcript", e->e_id);			}			printf("Original message will be saved in dead.letter.\r\n");			state = ESM_DEADLETTER;			break;		  case ESM_MAIL:			/*			**  If mailing back, do it.			**	Throw away all further output.  Don't alias,			**	since this could cause loops, e.g., if joe			**	mails to joe@x, and for some reason the network			**	for @x is down, then the response gets sent to			**	joe@x, which gives a response, etc.  Also force			**	the mail to be delivered even if a version of			**	it has already been sent to the sender.			**			**  If this is a configuration or local software			**	error, send to the local postmaster as well,			**	since the originator can't do anything			**	about it anyway.  Note that this is a full			**	copy of the message (intentionally) so that			**	the Postmaster can forward things along.			*/			if (ExitStat == EX_CONFIG || ExitStat == EX_SOFTWARE)			{				(void) sendtolist("postmaster",					  NULLADDR, &e->e_errorqueue, e);			}			if (strcmp(e->e_from.q_paddr, "<>") != 0)			{				(void) sendtolist(e->e_from.q_paddr,					  NULLADDR, &e->e_errorqueue, e);			}			/*			**  Deliver a non-delivery report to the			**  Postmaster-designate (not necessarily			**  Postmaster).  This does not include the			**  body of the message, for privacy reasons.			**  You really shouldn't need this.			*/			e->e_flags |= EF_PM_NOTIFY;			/* check to see if there are any good addresses */			for (q = e->e_errorqueue; q != NULL; q = q->q_next)				if (!bitset(QBADADDR|QDONTSEND, q->q_flags))					break;			if (q == NULL)			{				/* this is an error-error */				state = ESM_POSTMASTER;				break;			}			if (returntosender(e->e_message, e->e_errorqueue,					   (e->e_class >= 0), e) == 0)			{				state = ESM_DONE;				break;			}			/* didn't work -- return to postmaster */			state = ESM_POSTMASTER;			break;		  case ESM_POSTMASTER:			/*			**  Similar to previous case, but to system postmaster.			*/			q = NULL;			if (sendtolist("postmaster", NULL, &q, e) <= 0)			{				syserr("553 cannot parse postmaster!");				ExitStat = EX_SOFTWARE;				state = ESM_USRTMP;				break;			}			if (returntosender(e->e_message,					   q, (e->e_class >= 0), e) == 0)			{				state = ESM_DONE;				break;			}			/* didn't work -- last resort */			state = ESM_USRTMP;			break;		  case ESM_DEADLETTER:			/*			**  Save the message in dead.letter.			**	If we weren't mailing back, and the user is			**	local, we should save the message in			**	~/dead.letter so that the poor person doesn't			**	have to type it over again -- and we all know			**	what poor typists UNIX users are.			*/			p = NULL;			if (e->e_from.q_mailer == LocalMailer)			{				if (e->e_from.q_home != NULL)					p = e->e_from.q_home;				else if ((pw = getpwnam(e->e_from.q_user)) != NULL)					p = pw->pw_dir;			}			if (p == NULL)			{				/* no local directory */				state = ESM_MAIL;				break;			}			if (e->e_dfp != NULL)			{				bool oldverb = Verbose;				/* we have a home directory; open dead.letter */				define('z', p, e);				expand("\201z/dead.letter", buf, &buf[sizeof buf - 1], e);				Verbose = TRUE;				message("Saving message in %s", buf);				Verbose = oldverb;				e->e_to = buf;				q = NULL;				(void) sendtolist(buf, &e->e_from, &q, e);				if (q != NULL &&				    !bitset(QBADADDR, q->q_flags) &&				    deliver(e, q) == 0)					state = ESM_DONE;				else					state = ESM_MAIL;			}			else			{				/* no data file -- try mailing back */				state = ESM_MAIL;			}			break;		  case ESM_USRTMP:			/*			**  Log the mail in /usr/tmp/dead.letter.			*/			if (e->e_class < 0)			{				state = ESM_DONE;				break;			}			strcpy(buf, _PATH_VARTMP);			strcat(buf, "dead.letter");			if (!writable(buf, NULLADDR, SFF_NOSLINK))			{				state = ESM_PANIC;				break;			}			fp = dfopen(buf, O_WRONLY|O_CREAT|O_APPEND, FileMode);			if (fp == NULL)			{				state = ESM_PANIC;				break;			}			bzero(&mcibuf, sizeof mcibuf);			mcibuf.mci_out = fp;			mcibuf.mci_mailer = FileMailer;			if (bitnset(M_7BITS, FileMailer->m_flags))				mcibuf.mci_flags |= MCIF_7BIT;			putfromline(&mcibuf, e);			(*e->e_puthdr)(&mcibuf, e);			putline("\n", &mcibuf);			(*e->e_putbody)(&mcibuf, e, NULL);			putline("\n", &mcibuf);			(void) fflush(fp);			state = ferror(fp) ? ESM_PANIC : ESM_DONE;			(void) xfclose(fp, "savemail", "/usr/tmp/dead.letter");			break;		  default:			syserr("554 savemail: unknown state %d", state);			/* fall through ... */

⌨️ 快捷键说明

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