srvrsmtp.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 743 行 · 第 1/2 页

C
743
字号
#ifndef lintstatic	char	*sccsid = "@(#)srvrsmtp.c	4.1	(ULTRIX)	7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1987 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************/# include <errno.h># include "sendmail.h"# include <signal.h># ifndef SMTP# ifndef lintstatic char	SccsId[] = "@(#)srvrsmtp.c @(#)srvrsmtp.c	1.1 (ULTRIX) 7/17/87 (no SMTP)";# endif not lint# else SMTP# ifndef lintstatic char	SccsId[] = "@(#)srvrsmtp.c @(#)srvrsmtp.c	1.1 (ULTRIX) 7/17/87 (with SMTP)";# endif not lint/***  SMTP -- run the SMTP protocol.****	Parameters:**		none.****	Returns:**		never.****	Side Effects:**		Reads commands from the input channel and processes**			them.*/struct cmd{	char	*cmdname;	/* command name */	int	cmdcode;	/* internal code, see below */};/* values for cmdcode */# define CMDERROR	0	/* bad command */# define CMDMAIL	1	/* mail -- designate sender */# define CMDRCPT	2	/* rcpt -- designate recipient */# define CMDDATA	3	/* data -- send message text */# define CMDRSET	4	/* rset -- reset state */# define CMDVRFY	5	/* vrfy -- verify address */# define CMDHELP	6	/* help -- give usage info */# define CMDNOOP	7	/* noop -- do nothing */# define CMDQUIT	8	/* quit -- close connection and die */# define CMDHELO	9	/* helo -- be polite */# define CMDDBGQSHOW	10	/* showq -- show send queue (DEBUG) */# define CMDDBGDEBUG	11	/* debug -- set debug mode */# define CMDVERB	12	/* verb -- go into verbose mode */# define CMDDBGKILL	13	/* kill -- kill sendmail */# define CMDDBGWIZ	14	/* wiz -- become a wizard */# define CMDONEX	15	/* onex -- sending one transaction only */static struct cmd	CmdTab[] ={	"mail",		CMDMAIL,	"rcpt",		CMDRCPT,	"data",		CMDDATA,	"rset",		CMDRSET,	"vrfy",		CMDVRFY,	"expn",		CMDVRFY,	"help",		CMDHELP,	"noop",		CMDNOOP,	"quit",		CMDQUIT,	"helo",		CMDHELO,	"verb",		CMDVERB,	"onex",		CMDONEX,# ifdef DEBUG	"showq",	CMDDBGQSHOW,# ifdef notdef	/* We don't want this debug switch accessable via SMTP */	"debug",	CMDDBGDEBUG,# endif# endif DEBUG# ifdef WIZ	"kill",		CMDDBGKILL,# endif WIZ	"wiz",		CMDDBGWIZ,	NULL,		CMDERROR,};# ifdef WIZbool	IsWiz = FALSE;			/* set if we are a wizard */# endif WIZchar	*WizWord;			/* the wizard word to compare against */bool	InChild = FALSE;		/* true if running in a subprocess */bool	OneXact = FALSE;		/* one xaction only this run */bool	InRCPT = FALSE;			/* are we in RCPT To: command? */#define EX_QUIT		22		/* special code for QUIT command */smtp(){	register char *p;	register struct cmd *c;	char *cmd;	extern char *skipword();	extern bool sameword();	bool hasmail;			/* mail command received */	bool aliaserror;		/* bad address in the alias file? */	auto ADDRESS *vrfyqueue;	ADDRESS *a;	char inp[MAXLINE];	char cmdbuf[100];	extern char Version[];	extern tick();	extern bool iswiz();	extern char *arpadate();	extern char *macvalue();	extern char *aliaslookup();	extern ADDRESS *recipient();	extern ENVELOPE BlankEnvelope;	extern ENVELOPE *newenvelope();	hasmail = aliaserror = FALSE;	if (OutChannel != stdout)	{		/* arrange for debugging output to go to remote host */		(void) close(1);		(void) dup(fileno(OutChannel));	}	settime();	if (RealHostName != NULL)	{		CurHostName = RealHostName;		setproctitle("srvrsmtp %s", CurHostName);	}	else	{		/* this must be us!! */		CurHostName = MyHostName;	}	expand("\001e", inp, &inp[sizeof inp], CurEnv);	message("220", inp);	SmtpPhase = "startup";	for (;;)	{		/* arrange for backout */		if (setjmp(TopFrame) > 0 && InChild)			finis();		QuickAbort = FALSE;		HoldErrs = FALSE;		/* setup for the read */		CurEnv->e_to = NULL;		Errors = 0;		(void) fflush(stdout);		/* read the input line */		p = sfgets(inp, sizeof inp, InChannel);		/* handle errors */		if (p == NULL)		{			/* end of file, just die */			message("421", "%s Lost input channel to %s",				MyHostName, CurHostName);			finis();		}		/* clean up end of line */		fixcrlf(inp, TRUE);		/* echo command to transcript */		if (CurEnv->e_xfp != NULL)			fprintf(CurEnv->e_xfp, "<<< %s\n", inp);		/* break off command */		for (p = inp; isspace(*p); p++)			continue;		cmd = p;		for (cmd = cmdbuf; *p != '\0' && !isspace(*p); )			*cmd++ = *p++;		*cmd = '\0';		/* throw away leading whitespace */		while (isspace(*p))			p++;		/* decode command */		for (c = CmdTab; c->cmdname != NULL; c++)		{			if (sameword(c->cmdname, cmdbuf))				break;		}		/* process command */		switch (c->cmdcode)		{		  case CMDHELO:		/* hello -- introduce yourself */			SmtpPhase = "HELO";			setproctitle("%s: %s", CurHostName, inp);			if (sameword(p, MyHostName))			{				/* connected to an echo server */				message("553", "%s I refuse to talk to myself",					MyHostName);				break;			}			if (RealHostName != NULL && !sameword(p, RealHostName))			{				char hostbuf[MAXNAME];				(void) sprintf(hostbuf, "%s (%s)", p, RealHostName);				define('s', newstr(hostbuf), CurEnv);			}			else				define('s', newstr(p), CurEnv);			message("250", "%s Hello %s, pleased to meet you",				MyHostName, p);			break;		  case CMDMAIL:		/* mail -- designate sender */			SmtpPhase = "MAIL";			/* force a sending host even if no HELO given */			if (RealHostName != NULL && macvalue('s', CurEnv) == NULL)				define('s', RealHostName, CurEnv);			/* check for validity of this command */			if (hasmail)			{				message("503", "Sender already specified");				break;			}			if (InChild)			{				syserr("Nested MAIL command");				exit(0);			}			/* fork a subprocess to process this command */			if (runinchild("SMTP-MAIL") > 0)				break;			initsys();			setproctitle("%s %s: %s", CurEnv->e_id,				CurHostName, inp);			/* child -- go do the processing */			p = skipword(p, "from");			if (p == NULL)				break;			setsender(p);			if (Errors == 0)			{				message("250", "Sender ok");				hasmail = TRUE;			}			else if (InChild)				finis();			break;		  case CMDRCPT:		/* rcpt -- designate recipient */			SmtpPhase = "RCPT";			setproctitle("%s %s: %s", CurEnv->e_id,				CurHostName, inp);			if (setjmp(TopFrame) > 0)			{				CurEnv->e_flags &= ~EF_FATALERRS;				break;			}			QuickAbort = TRUE;			p = skipword(p, "to");			if (p == NULL)				break;			a = parseaddr(p, (ADDRESS *) NULL, 1, '\0');			if (a == NULL)				break;			a->q_flags |= QPRIMARY;			InRCPT = TRUE;			a = recipient(a, &CurEnv->e_sendqueue);			InRCPT = FALSE;			/*			 * The gratuitous twiddling of the fatal error			 * bit below is to detect bad addresses in the alias			 * file and to notify local owner- addresses while			 * trying not to send the remote user a (duplicate)			 * error if his mailer is capable of that.			 */			CurEnv->e_to = p;			if (aliaslookup(a->q_user))			{				/*				 * If the rcpt to: line is in the alias file				 * tell the sender it's ok.  It may expand to				 * an invalid address, but we lie to the sender				 * and say it's ok.  This permits us to honor				 * the owner- alias and to deliver to valid				 * addressees on the alias list, if any.				 *				 * If there was an error, remember it				 * since the error bit can get cleared				 * on the next rcpt to: and since we				 * want to report the error later on.				 */				message("250", "Recipient ok");				if (bitset(EF_FATALERRS, CurEnv->e_flags))					aliaserror = TRUE;			}			else			{				if (!bitset(QBADADDR, a->q_flags))					message("250", "Recipient ok");				else				{					/*					 * This will cause the sending mailer					 * to notify the user.  We clear the					 * error bit so we don't notify him.					 */					message("550", "Addressee unknown");					CurEnv->e_flags &= ~EF_FATALERRS;				}			}			CurEnv->e_to = NULL;			break;		  case CMDDATA:		/* data -- text of mail */			SmtpPhase = "DATA";			if (!hasmail)			{				message("503", "Need MAIL command");				break;			}			else if (CurEnv->e_nrcpts <= 0)			{				message("503", "Need RCPT (recipient)");				break;			}			/* collect the text of the message */			SmtpPhase = "collect";			setproctitle("%s %s: %s", CurEnv->e_id,				CurHostName, inp);			collect(TRUE);			if (Errors != 0)				break;			/*

⌨️ 快捷键说明

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