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 + -
显示快捷键?