386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Sat, 11 May 1991 06:49:22 +0000 (22:49 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Sat, 11 May 1991 06:49:22 +0000 (22:49 -0800)
Work on file usr/src/usr.sbin/sendmail/src/version.c
Work on file usr/src/usr.sbin/sendmail/src/srvrsmtp.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/src/usr.sbin/sendmail/src/srvrsmtp.c [new file with mode: 0644]
usr/src/usr.sbin/sendmail/src/version.c [new file with mode: 0644]

diff --git a/usr/src/usr.sbin/sendmail/src/srvrsmtp.c b/usr/src/usr.sbin/sendmail/src/srvrsmtp.c
new file mode 100644 (file)
index 0000000..b33a1ef
--- /dev/null
@@ -0,0 +1,658 @@
+/*
+ * Copyright (c) 1983 Eric P. Allman
+ * Copyright (c) 1988 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.
+ */
+
+# include "sendmail.h"
+
+#ifndef lint
+#ifdef SMTP
+static char sccsid[] = "@(#)srvrsmtp.c 5.31 (Berkeley) 5/10/91 (with SMTP)";
+#else
+static char sccsid[] = "@(#)srvrsmtp.c 5.31 (Berkeley) 5/10/91 (without SMTP)";
+#endif
+#endif /* not lint */
+
+# include <errno.h>
+# include <signal.h>
+
+# ifdef SMTP
+
+/*
+**  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 CMDONEX       10      /* onex -- sending one transaction only */
+# define CMDVERB       11      /* verb -- go into verbose mode */
+/* debugging-only commands, only enabled if SMTPDEBUG is defined */
+# define CMDDBGQSHOW   12      /* showq -- show send queue */
+# define CMDDBGDEBUG   13      /* debug -- set debug mode */
+
+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,
+       /*
+        * remaining commands are here only
+        * to trap and log attempts to use them
+        */
+       "showq",        CMDDBGQSHOW,
+       "debug",        CMDDBGDEBUG,
+       NULL,           CMDERROR,
+};
+
+bool   InChild = FALSE;                /* true if running in a subprocess */
+bool   OneXact = FALSE;                /* one xaction only this run */
+
+#define EX_QUIT                22              /* special code for QUIT command */
+
+smtp()
+{
+       register char *p;
+       register struct cmd *c;
+       char *cmd;
+       static char *skipword();
+       bool hasmail;                   /* mail command received */
+       auto ADDRESS *vrfyqueue;
+       ADDRESS *a;
+       char *sendinghost;
+       char inp[MAXLINE];
+       char cmdbuf[100];
+       extern char Version[];
+       extern char *macvalue();
+       extern ADDRESS *recipient();
+       extern ENVELOPE BlankEnvelope;
+       extern ENVELOPE *newenvelope();
+
+       hasmail = 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";
+       sendinghost = NULL;
+       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 from %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 (!strcasecmp(c->cmdname, cmdbuf))
+                               break;
+               }
+
+               /* process command */
+               switch (c->cmdcode)
+               {
+                 case CMDHELO:         /* hello -- introduce yourself */
+                       SmtpPhase = "HELO";
+                       setproctitle("%s: %s", CurHostName, inp);
+                       if (!strcasecmp(p, MyHostName))
+                       {
+                               /*
+                                * didn't know about alias,
+                                * or connected to an echo server
+                                */
+                               message("553", "%s config error: mail loops back to myself",
+                                       MyHostName);
+                               break;
+                       }
+                       if (RealHostName != NULL && strcasecmp(p, RealHostName))
+                       {
+                               char hostbuf[MAXNAME];
+
+                               (void) sprintf(hostbuf, "%s (%s)", p, RealHostName);
+                               sendinghost = newstr(hostbuf);
+                       }
+                       else
+                               sendinghost = newstr(p);
+                       message("250", "%s Hello %s, pleased to meet you",
+                               MyHostName, sendinghost);
+                       break;
+
+                 case CMDMAIL:         /* mail -- designate sender */
+                       SmtpPhase = "MAIL";
+
+                       /* force a sending host even if no HELO given */
+                       if (RealHostName != NULL && macvalue('s', CurEnv) == NULL)
+                               sendinghost = RealHostName;
+
+                       /* check for validity of this command */
+                       if (hasmail)
+                       {
+                               message("503", "Sender already specified");
+                               break;
+                       }
+                       if (InChild)
+                       {
+                               errno = 0;
+                               syserr("Nested MAIL command");
+                               exit(0);
+                       }
+
+                       /* fork a subprocess to process this command */
+                       if (runinchild("SMTP-MAIL") > 0)
+                               break;
+                       define('s', sendinghost, CurEnv);
+                       define('r', "SMTP", CurEnv);
+                       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;
+                       a = recipient(a, &CurEnv->e_sendqueue);
+                       if (Errors != 0)
+                               break;
+
+                       /* no errors during parsing, but might be a duplicate */
+                       CurEnv->e_to = p;
+                       if (!bitset(QBADADDR, a->q_flags))
+                               message("250", "Recipient ok");
+                       else
+                       {
+                               /* punt -- should keep message in ADDRESS.... */
+                               message("550", "Addressee unknown");
+                       }
+                       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;
+
+                       /*
+                       **  Arrange to send to everyone.
+                       **      If sending to multiple people, mail back
+                       **              errors rather than reporting directly.
+                       **      In any case, don't mail back errors for
+                       **              anything that has happened up to
+                       **              now (the other end will do this).
+                       **      Truncate our transcript -- the mail has gotten
+                       **              to us successfully, and if we have
+                       **              to mail this back, it will be easier
+                       **              on the reader.
+                       **      Then send to everyone.
+                       **      Finally give a reply code.  If an error has
+                       **              already been given, don't mail a
+                       **              message back.
+                       **      We goose error returns by clearing error bit.
+                       */
+
+                       SmtpPhase = "delivery";
+                       if (CurEnv->e_nrcpts != 1)
+                       {
+                               HoldErrs = TRUE;
+                               ErrorMode = EM_MAIL;
+                       }
+                       CurEnv->e_flags &= ~EF_FATALERRS;
+                       CurEnv->e_xfp = freopen(queuename(CurEnv, 'x'), "w", CurEnv->e_xfp);
+
+                       /* send to all recipients */
+                       sendall(CurEnv, SM_DEFAULT);
+                       CurEnv->e_to = NULL;
+
+                       /* save statistics */
+                       markstats(CurEnv, (ADDRESS *) NULL);
+
+                       /* issue success if appropriate and reset */
+                       if (Errors == 0 || HoldErrs)
+                               message("250", "Ok");
+                       else
+                               CurEnv->e_flags &= ~EF_FATALERRS;
+
+                       /* if in a child, pop back to our parent */
+                       if (InChild)
+                               finis();
+
+                       /* clean up a bit */
+                       hasmail = 0;
+                       dropenvelope(CurEnv);
+                       CurEnv = newenvelope(CurEnv);
+                       CurEnv->e_flags = BlankEnvelope.e_flags;
+                       break;
+
+                 case CMDRSET:         /* rset -- reset state */
+                       message("250", "Reset state");
+                       if (InChild)
+                               finis();
+                       break;
+
+                 case CMDVRFY:         /* vrfy -- verify address */
+                       if (runinchild("SMTP-VRFY") > 0)
+                               break;
+                       setproctitle("%s: %s", CurHostName, inp);
+                       vrfyqueue = NULL;
+                       QuickAbort = TRUE;
+                       sendtolist(p, (ADDRESS *) NULL, &vrfyqueue);
+                       if (Errors != 0)
+                       {
+                               if (InChild)
+                                       finis();
+                               break;
+                       }
+                       while (vrfyqueue != NULL)
+                       {
+                               register ADDRESS *a = vrfyqueue->q_next;
+                               char *code;
+
+                               while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags))
+                                       a = a->q_next;
+
+                               if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags))
+                               {
+                                       if (a != NULL)
+                                               code = "250-";
+                                       else
+                                               code = "250";
+                                       if (vrfyqueue->q_fullname == NULL)
+                                               message(code, "<%s>", vrfyqueue->q_paddr);
+                                       else
+                                               message(code, "%s <%s>",
+                                                   vrfyqueue->q_fullname, vrfyqueue->q_paddr);
+                               }
+                               else if (a == NULL)
+                                       message("554", "Self destructive alias loop");
+                               vrfyqueue = a;
+                       }
+                       if (InChild)
+                               finis();
+                       break;
+
+                 case CMDHELP:         /* help -- give user info */
+                       help(p);
+                       break;
+
+                 case CMDNOOP:         /* noop -- do nothing */
+                       message("200", "OK");
+                       break;
+
+                 case CMDQUIT:         /* quit -- leave mail */
+                       message("221", "%s closing connection", MyHostName);
+                       if (InChild)
+                               ExitStat = EX_QUIT;
+                       finis();
+
+                 case CMDVERB:         /* set verbose mode */
+                       Verbose = TRUE;
+                       SendMode = SM_DELIVER;
+                       message("200", "Verbose mode");
+                       break;
+
+                 case CMDONEX:         /* doing one transaction only */
+                       OneXact = TRUE;
+                       message("200", "Only one transaction");
+                       break;
+
+# ifdef SMTPDEBUG
+                 case CMDDBGQSHOW:     /* show queues */
+                       printf("Send Queue=");
+                       printaddr(CurEnv->e_sendqueue, TRUE);
+                       break;
+
+                 case CMDDBGDEBUG:     /* set debug mode */
+                       tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
+                       tTflag(p);
+                       message("200", "Debug set");
+                       break;
+
+# else /* not SMTPDEBUG */
+
+                 case CMDDBGQSHOW:     /* show queues */
+                 case CMDDBGDEBUG:     /* set debug mode */
+# ifdef LOG
+                       if (RealHostName != NULL && LogLevel > 0)
+                               syslog(LOG_NOTICE,
+                                   "\"%s\" command from %s (%s)\n",
+                                   c->cmdname, RealHostName,
+                                   inet_ntoa(RealHostAddr.sin_addr));
+# endif
+                       /* FALL THROUGH */
+# endif /* SMTPDEBUG */
+
+                 case CMDERROR:        /* unknown command */
+                       message("500", "Command unrecognized");
+                       break;
+
+                 default:
+                       errno = 0;
+                       syserr("smtp: unknown code %d", c->cmdcode);
+                       break;
+               }
+       }
+}
+\f/*
+**  SKIPWORD -- skip a fixed word.
+**
+**     Parameters:
+**             p -- place to start looking.
+**             w -- word to skip.
+**
+**     Returns:
+**             p following w.
+**             NULL on error.
+**
+**     Side Effects:
+**             clobbers the p data area.
+*/
+
+static char *
+skipword(p, w)
+       register char *p;
+       char *w;
+{
+       register char *q;
+
+       /* find beginning of word */
+       while (isspace(*p))
+               p++;
+       q = p;
+
+       /* find end of word */
+       while (*p != '\0' && *p != ':' && !isspace(*p))
+               p++;
+       while (isspace(*p))
+               *p++ = '\0';
+       if (*p != ':')
+       {
+         syntax:
+               message("501", "Syntax error");
+               Errors++;
+               return (NULL);
+       }
+       *p++ = '\0';
+       while (isspace(*p))
+               p++;
+
+       /* see if the input word matches desired word */
+       if (strcasecmp(q, w))
+               goto syntax;
+
+       return (p);
+}
+\f/*
+**  HELP -- implement the HELP command.
+**
+**     Parameters:
+**             topic -- the topic we want help for.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             outputs the help file to message output.
+*/
+
+help(topic)
+       char *topic;
+{
+       register FILE *hf;
+       int len;
+       char buf[MAXLINE];
+       bool noinfo;
+
+       if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL)
+       {
+               /* no help */
+               errno = 0;
+               message("502", "HELP not implemented");
+               return;
+       }
+
+       if (topic == NULL || *topic == '\0')
+               topic = "smtp";
+       else
+               makelower(topic);
+
+       len = strlen(topic);
+       noinfo = TRUE;
+
+       while (fgets(buf, sizeof buf, hf) != NULL)
+       {
+               if (strncmp(buf, topic, len) == 0)
+               {
+                       register char *p;
+
+                       p = index(buf, '\t');
+                       if (p == NULL)
+                               p = buf;
+                       else
+                               p++;
+                       fixcrlf(p, TRUE);
+                       message("214-", p);
+                       noinfo = FALSE;
+               }
+       }
+
+       if (noinfo)
+               message("504", "HELP topic unknown");
+       else
+               message("214", "End of HELP info");
+       (void) fclose(hf);
+}
+\f/*
+**  RUNINCHILD -- return twice -- once in the child, then in the parent again
+**
+**     Parameters:
+**             label -- a string used in error messages
+**
+**     Returns:
+**             zero in the child
+**             one in the parent
+**
+**     Side Effects:
+**             none.
+*/
+
+runinchild(label)
+       char *label;
+{
+       int childpid;
+
+       if (!OneXact)
+       {
+               childpid = dofork();
+               if (childpid < 0)
+               {
+                       syserr("%s: cannot fork", label);
+                       return (1);
+               }
+               if (childpid > 0)
+               {
+                       auto int st;
+
+                       /* parent -- wait for child to complete */
+                       st = waitfor(childpid);
+                       if (st == -1)
+                               syserr("%s: lost child", label);
+
+                       /* if we exited on a QUIT command, complete the process */
+                       if (st == (EX_QUIT << 8))
+                               finis();
+
+                       return (1);
+               }
+               else
+               {
+                       /* child */
+                       InChild = TRUE;
+                       QuickAbort = FALSE;
+                       clearenvelope(CurEnv, FALSE);
+               }
+       }
+
+       /* open alias database */
+       initaliases(AliasFile, FALSE);
+
+       return (0);
+}
+
+# endif SMTP
diff --git a/usr/src/usr.sbin/sendmail/src/version.c b/usr/src/usr.sbin/sendmail/src/version.c
new file mode 100644 (file)
index 0000000..6896049
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1983 Eric P. Allman
+ * Copyright (c) 1988 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 lint
+static char sccsid[] = "@(#)version.c  5.67 (Berkeley) 5/10/91";
+#endif /* not lint */
+
+char   Version[] = "5.67";