integrate user SMTP into sendmail itself. If there is no $u arg
authorEric Allman <eric@ucbvax.Berkeley.EDU>
Thu, 12 Nov 1981 12:24:17 +0000 (04:24 -0800)
committerEric Allman <eric@ucbvax.Berkeley.EDU>
Thu, 12 Nov 1981 12:24:17 +0000 (04:24 -0800)
in the mailer argument list, SMTP is run.  This can be used directly
over the Ethernet or to any clever mailer.  We still need to edit
spooled control files to remove recipients that have been successfully
sent during queue processing.

SCCS-vsn: usr.sbin/sendmail/src/deliver.c 3.53
SCCS-vsn: usr.sbin/sendmail/src/savemail.c 3.23
SCCS-vsn: usr.sbin/sendmail/src/version.c 3.63
SCCS-vsn: usr.sbin/sendmail/src/usersmtp.c 3.4

usr/src/usr.sbin/sendmail/src/deliver.c
usr/src/usr.sbin/sendmail/src/savemail.c
usr/src/usr.sbin/sendmail/src/usersmtp.c
usr/src/usr.sbin/sendmail/src/version.c

index a49b228..e1930fc 100644 (file)
@@ -6,7 +6,7 @@
 # include <syslog.h>
 # endif LOG
 
 # include <syslog.h>
 # endif LOG
 
-static char SccsId[] = "@(#)deliver.c  3.52    %G%";
+static char SccsId[] = "@(#)deliver.c  3.53    %G%";
 
 /*
 **  DELIVER -- Deliver a message to a list of addresses.
 
 /*
 **  DELIVER -- Deliver a message to a list of addresses.
@@ -53,6 +53,8 @@ deliver(firstto, editfcn)
        char tfrombuf[MAXNAME];         /* translated from person */
        extern char **prescan();
        register ADDRESS *to = firstto;
        char tfrombuf[MAXNAME];         /* translated from person */
        extern char **prescan();
        register ADDRESS *to = firstto;
+       bool clever = FALSE;            /* running user smtp to this mailer */
+       bool tempfail = FALSE;
 
        errno = 0;
        if (!ForceMail && bitset(QDONTSEND, to->q_flags))
 
        errno = 0;
        if (!ForceMail && bitset(QDONTSEND, to->q_flags))
@@ -128,8 +130,20 @@ deliver(firstto, editfcn)
                        return (-1);
                }
        }
                        return (-1);
                }
        }
+
        if (*mvp == NULL)
        if (*mvp == NULL)
-               syserr("No $u in mailer argv for %s", pv[0]);
+       {
+               /* running SMTP */
+               clever = TRUE;
+               *pvp = NULL;
+               i = smtpinit(m, pv, (ADDRESS *) NULL);
+               giveresponse(i, TRUE, m);
+               if (i == EX_TEMPFAIL)
+               {
+                       QueueUp = TRUE;
+                       tempfail = TRUE;
+               }
+       }
 
        /*
        **  At this point *mvp points to the argument with $u.  We
 
        /*
        **  At this point *mvp points to the argument with $u.  We
@@ -159,6 +173,8 @@ deliver(firstto, editfcn)
                user = to->q_user;
                To = to->q_paddr;
                to->q_flags |= QDONTSEND;
                user = to->q_user;
                To = to->q_paddr;
                to->q_flags |= QDONTSEND;
+               if (tempfail)
+                       to->q_flags |= QQUEUEUP;
 # ifdef DEBUG
                if (Debug)
                        printf("   send to `%s'\n", user);
 # ifdef DEBUG
                if (Debug)
                        printf("   send to `%s'\n", user);
@@ -239,19 +255,44 @@ deliver(firstto, editfcn)
                define('u', user);              /* to user */
                define('z', to->q_home);        /* user's home */
 
                define('u', user);              /* to user */
                define('z', to->q_home);        /* user's home */
 
-               /* expand out this user */
-               (void) expand(*mvp, buf, &buf[sizeof buf - 1]);
-               *pvp++ = newstr(buf);
-               if (pvp >= &pv[MAXPV - 2])
+               /*
+               **  Expand out this user into argument list or
+               **  send it to our SMTP server.
+               */
+
+               if (clever)
                {
                {
-                       /* allow some space for trailing parms */
-                       break;
+                       i = smtpmrcp(to);
+                       if (i == EX_TEMPFAIL)
+                       {
+                               QueueUp = TRUE;
+                               to->q_flags |= QQUEUEUP;
+                       }
+                       else if (i != EX_OK)
+                       {
+                               to->q_flags |= QBADADDR;
+                               giveresponse(i, TRUE, m);
+                       }
+               }
+               else
+               {
+                       (void) expand(*mvp, buf, &buf[sizeof buf - 1]);
+                       *pvp++ = newstr(buf);
+                       if (pvp >= &pv[MAXPV - 2])
+                       {
+                               /* allow some space for trailing parms */
+                               break;
+                       }
                }
        }
 
        /* see if any addresses still exist */
        if (tobuf[0] == '\0')
                }
        }
 
        /* see if any addresses still exist */
        if (tobuf[0] == '\0')
+       {
+               if (clever)
+                       smtpquit(pv[0]);
                return (0);
                return (0);
+       }
 
        /* print out messages as full list */
        To = tobuf;
 
        /* print out messages as full list */
        To = tobuf;
@@ -260,7 +301,7 @@ deliver(firstto, editfcn)
        **  Fill out any parameters after the $u parameter.
        */
 
        **  Fill out any parameters after the $u parameter.
        */
 
-       while (*++mvp != NULL)
+       while (!clever && *++mvp != NULL)
        {
                (void) expand(*mvp, buf, &buf[sizeof buf - 1]);
                *pvp++ = newstr(buf);
        {
                (void) expand(*mvp, buf, &buf[sizeof buf - 1]);
                *pvp++ = newstr(buf);
@@ -274,13 +315,20 @@ deliver(firstto, editfcn)
        **      The argument vector gets built, pipes
        **      are created as necessary, and we fork & exec as
        **      appropriate.
        **      The argument vector gets built, pipes
        **      are created as necessary, and we fork & exec as
        **      appropriate.
+       **      If we are running SMTP, we just need to clean up.
        */
 
        if (editfcn == NULL)
                editfcn = putmessage;
        if (ctladdr == NULL)
                ctladdr = &From;
        */
 
        if (editfcn == NULL)
                editfcn = putmessage;
        if (ctladdr == NULL)
                ctladdr = &From;
-       i = sendoff(m, pv, editfcn, ctladdr);
+       if (clever)
+       {
+               i = smtpfinish(m, editfcn);
+               smtpquit(pv[0]);
+       }
+       else
+               i = sendoff(m, pv, editfcn, ctladdr);
 
        /*
        **  If we got a temporary failure, arrange to queue the
 
        /*
        **  If we got a temporary failure, arrange to queue the
@@ -387,18 +435,115 @@ sendoff(m, pvp, editfcn, ctladdr)
        int (*editfcn)();
        ADDRESS *ctladdr;
 {
        int (*editfcn)();
        ADDRESS *ctladdr;
 {
-       auto int st;
+       auto FILE *mfile;
+       auto FILE *rfile;
        register int i;
        register int i;
+       extern putmessage();
+       int pid;
+
+       /*
+       **  Create connection to mailer.
+       */
+
+       pid = openmailer(m, pvp, ctladdr, FALSE, &mfile, &rfile);
+       if (pid < 0)
+               return (-1);
+
+       /*
+       **  Format and send message.
+       */
+
+       (void) signal(SIGPIPE, SIG_IGN);
+       if (editfcn == NULL)
+               editfcn = putmessage;
+       
+       (*editfcn)(mfile, m, FALSE);
+       (void) fclose(mfile);
+
+       i = endmailer(pid, pvp[0]);
+       giveresponse(i, TRUE, m);
+       return (i);
+}
+\f/*
+**  ENDMAILER -- Wait for mailer to terminate.
+**
+**     We should never get fatal errors (e.g., segmentation
+**     violation), so we report those specially.  For other
+**     errors, we choose a status message (into statmsg),
+**     and if it represents an error, we print it.
+**
+**     Parameters:
+**             pid -- pid of mailer.
+**             name -- name of mailer (for error messages).
+**
+**     Returns:
+**             exit code of mailer.
+**
+**     Side Effects:
+**             none.
+*/
+
+endmailer(pid, name)
+       int pid;
+       char *name;
+{
+       register int i;
+       auto int st;
+
+       while ((i = wait(&st)) > 0 && i != pid)
+               continue;
+       if (i < 0)
+       {
+               syserr("wait");
+               return (-1);
+       }
+       if ((st & 0377) != 0)
+       {
+               syserr("%s: stat %o", name, st);
+               ExitStat = EX_UNAVAILABLE;
+               return (-1);
+       }
+       i = (st >> 8) & 0377;
+       return (i);
+}
+\f/*
+**  OPENMAILER -- open connection to mailer.
+**
+**     Parameters:
+**             m -- mailer descriptor.
+**             pvp -- parameter vector to pass to mailer.
+**             ctladdr -- controlling address for user.
+**             clever -- create a full duplex connection.
+**             pmfile -- pointer to mfile (to mailer) connection.
+**             prfile -- pointer to rfile (from mailer) connection.
+**
+**     Returns:
+**             pid of mailer.
+**             -1 on error.
+**
+**     Side Effects:
+**             creates a mailer in a subprocess.
+*/
+
+openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
+       struct mailer *m;
+       char **pvp;
+       ADDRESS *ctladdr;
+       bool clever;
+       FILE **pmfile;
+       FILE **prfile;
+{
        int pid;
        int mpvect[2];
        int pid;
        int mpvect[2];
+       int rpvect[2];
        FILE *mfile;
        FILE *mfile;
-       extern putmessage();
+       FILE *rfile;
        extern FILE *fdopen();
 
 # ifdef DEBUG
        if (Debug)
        {
        extern FILE *fdopen();
 
 # ifdef DEBUG
        if (Debug)
        {
-               printf("Sendoff:\n");
+               printf("openmailer:\n");
                printav(pvp);
        }
 # endif DEBUG
                printav(pvp);
        }
 # endif DEBUG
@@ -407,9 +552,19 @@ sendoff(m, pvp, editfcn, ctladdr)
        /* create a pipe to shove the mail through */
        if (pipe(mpvect) < 0)
        {
        /* create a pipe to shove the mail through */
        if (pipe(mpvect) < 0)
        {
-               syserr("pipe");
+               syserr("pipe (to mailer)");
+               return (-1);
+       }
+
+       /* if this mailer speaks smtp, create a return pipe */
+       if (clever && pipe(rpvect) < 0)
+       {
+               syserr("pipe (from mailer)");
+               (void) close(mpvect[0]);
+               (void) close(mpvect[1]);
                return (-1);
        }
                return (-1);
        }
+
        DOFORK(XFORK);
        /* pid is set by DOFORK */
        if (pid < 0)
        DOFORK(XFORK);
        /* pid is set by DOFORK */
        if (pid < 0)
@@ -417,6 +572,11 @@ sendoff(m, pvp, editfcn, ctladdr)
                syserr("Cannot fork");
                (void) close(mpvect[0]);
                (void) close(mpvect[1]);
                syserr("Cannot fork");
                (void) close(mpvect[0]);
                (void) close(mpvect[1]);
+               if (clever)
+               {
+                       (void) close(rpvect[0]);
+                       (void) close(rpvect[1]);
+               }
                return (-1);
        }
        else if (pid == 0)
                return (-1);
        }
        else if (pid == 0)
@@ -428,7 +588,14 @@ sendoff(m, pvp, editfcn, ctladdr)
                (void) signal(SIGTERM, SIG_DFL);
 
                /* arrange to filter standard & diag output of command */
                (void) signal(SIGTERM, SIG_DFL);
 
                /* arrange to filter standard & diag output of command */
-               if (OutChannel != stdout)
+               if (clever)
+               {
+                       (void) close(rpvect[0]);
+                       (void) close(1);
+                       (void) dup(rpvect[1]);
+                       (void) close(rpvect[1]);
+               }
+               else if (OutChannel != stdout)
                {
                        (void) close(1);
                        (void) dup(fileno(OutChannel));
                {
                        (void) close(1);
                        (void) dup(fileno(OutChannel));
@@ -492,41 +659,21 @@ sendoff(m, pvp, editfcn, ctladdr)
        }
 
        /*
        }
 
        /*
-       **  Format and write message to mailer.
+       **  Set up return value.
        */
 
        (void) close(mpvect[0]);
        */
 
        (void) close(mpvect[0]);
-       (void) signal(SIGPIPE, SIG_IGN);
        mfile = fdopen(mpvect[1], "w");
        mfile = fdopen(mpvect[1], "w");
-       if (editfcn == NULL)
-               editfcn = putmessage;
-       (*editfcn)(mfile, m);
-       (void) fclose(mfile);
-
-       /*
-       **  Wait for child to die and report status.
-       **      We should never get fatal errors (e.g., segmentation
-       **      violation), so we report those specially.  For other
-       **      errors, we choose a status message (into statmsg),
-       **      and if it represents an error, we print it.
-       */
-
-       while ((i = wait(&st)) > 0 && i != pid)
-               continue;
-       if (i < 0)
-       {
-               syserr("wait");
-               return (-1);
-       }
-       if ((st & 0377) != 0)
+       if (clever)
        {
        {
-               syserr("%s: stat %o", pvp[0], st);
-               ExitStat = EX_UNAVAILABLE;
-               return (-1);
+               (void) close(rpvect[1]);
+               rfile = fdopen(rpvect[0], "r");
        }
        }
-       i = (st >> 8) & 0377;
-       giveresponse(i, TRUE, m);
-       return (i);
+
+       *pmfile = mfile;
+       *prfile = rfile;
+
+       return (pid);
 }
 \f/*
 **  GIVERESPONSE -- Interpret an error response from a mailer
 }
 \f/*
 **  GIVERESPONSE -- Interpret an error response from a mailer
@@ -631,6 +778,7 @@ giveresponse(stat, force, m)
 **     Parameters:
 **             fp -- file to output onto.
 **             m -- a mailer descriptor.
 **     Parameters:
 **             fp -- file to output onto.
 **             m -- a mailer descriptor.
+**             xdot -- if set, hide lines beginning with dot.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -639,12 +787,12 @@ giveresponse(stat, force, m)
 **             The message is written onto fp.
 */
 
 **             The message is written onto fp.
 */
 
-putmessage(fp, m)
+putmessage(fp, m, xdot)
        FILE *fp;
        struct mailer *m;
        FILE *fp;
        struct mailer *m;
+       bool xdot;
 {
        char buf[BUFSIZ];
 {
        char buf[BUFSIZ];
-       register int i;
        register HDR *h;
        extern char *arpadate();
        bool anyheader = FALSE;
        register HDR *h;
        extern char *arpadate();
        bool anyheader = FALSE;
@@ -736,8 +884,8 @@ putmessage(fp, m)
        if (TempFile != NULL)
        {
                rewind(TempFile);
        if (TempFile != NULL)
        {
                rewind(TempFile);
-               while (!ferror(fp) && (i = fread(buf, 1, BUFSIZ, TempFile)) > 0)
-                       (void) fwrite(buf, 1, i, fp);
+               while (!ferror(fp) && fgets(buf, sizeof buf, TempFile) != NULL)
+                       fprintf(fp, "%s%s", xdot && buf[0] == '.' ? "." : "", buf);
 
                if (ferror(TempFile))
                {
 
                if (ferror(TempFile))
                {
@@ -879,7 +1027,7 @@ mailfile(filename, ctladdr)
                if (f == NULL)
                        exit(EX_CANTCREAT);
 
                if (f == NULL)
                        exit(EX_CANTCREAT);
 
-               putmessage(f, Mailer[1]);
+               putmessage(f, Mailer[1], FALSE);
                fputs("\n", f);
                (void) fclose(f);
                (void) fflush(stdout);
                fputs("\n", f);
                (void) fclose(f);
                (void) fflush(stdout);
index 5a7ff75..43f9d3a 100644 (file)
@@ -1,7 +1,7 @@
 # include <pwd.h>
 # include "sendmail.h"
 
 # include <pwd.h>
 # include "sendmail.h"
 
-static char    SccsId[] = "@(#)savemail.c      3.22    %G%";
+static char    SccsId[] = "@(#)savemail.c      3.23    %G%";
 
 /*
 **  SAVEMAIL -- Save mail on error
 
 /*
 **  SAVEMAIL -- Save mail on error
@@ -215,6 +215,7 @@ returntosender(msg)
 **     Parameters:
 **             xfile -- the transcript file.
 **             fp -- the output file.
 **     Parameters:
 **             xfile -- the transcript file.
 **             fp -- the output file.
+**             xdot -- if set, use smtp hidden dot algorithm.
 **
 **     Returns:
 **             none
 **
 **     Returns:
 **             none
@@ -224,9 +225,10 @@ returntosender(msg)
 **             error header.
 */
 
 **             error header.
 */
 
-errhdr(fp, m)
+errhdr(fp, m, xdot)
        register FILE *fp;
        register struct mailer *m;
        register FILE *fp;
        register struct mailer *m;
+       bool xdot;
 {
        char buf[MAXLINE];
        register FILE *xfile;
 {
        char buf[MAXLINE];
        register FILE *xfile;
@@ -298,7 +300,7 @@ errhdr(fp, m)
        {
                fprintf(fp, "\n   ----- Unsent message follows -----\n");
                (void) fflush(fp);
        {
                fprintf(fp, "\n   ----- Unsent message follows -----\n");
                (void) fflush(fp);
-               putmessage(fp, Mailer[1]);
+               putmessage(fp, Mailer[1], xdot);
        }
        else
                fprintf(fp, "\n  ----- No message was collected -----\n\n");
        }
        else
                fprintf(fp, "\n  ----- No message was collected -----\n\n");
index f98dd1a..2d0522d 100644 (file)
 # include <ctype.h>
 # include <wellknown.h>
 # include <sysexits.h>
 # include <ctype.h>
 # include <wellknown.h>
 # include <sysexits.h>
-# include <stdio.h>
-# include <useful.h>
+# include "sendmail.h"
 
 
-static char    SccsId[] =      "@(#)usersmtp.c 3.3     %G%";
+static char    SccsId[] =      "@(#)usersmtp.c 3.4     %G%";
 
 /*
 
 /*
-**  TCP -- TCP/Ethernet/ARPAnet mailer
+**  SMTPINIT -- initialize SMTP.
 **
 **
-**     This arranges to send a message over the TCP connection.
-*/
-
-# define MAXLINE       200
-
-char   *MailCommand =  "/usr/lib/sendmail";
-char   *MailUser =     "network";
-char   *MailPassword = "mailhack";
-FILE   *InConnection;
-FILE   *OutConnection;
-bool   Verbose;
-bool   Debug;
-int    Status;                 /* exit status */
-
-main(argc, argv)
-       int argc;
-       char **argv;
-{
-       while (argc > 1 && argv[1][0] == '-')
-       {
-               register char *p = *++argv;
-
-               argc--;
-               switch (p[1])
-               {
-                 case 'v':
-                       Verbose = TRUE;
-                       break;
-
-                 case 'd':
-                       Debug = TRUE;
-                       break;
-               }
-       }
-
-       if (argc < 4)
-       {
-               if (Debug)
-                       printf("Usage\n");
-               exit(EX_USAGE);
-       }
-
-       if (openconnection(argv[2]) < 0)
-               exit(Status);
-
-       Status = runsmtp(argv[1], &argv[3]);
-
-       closeconnection();
-
-       if (Debug)
-               printf("Finishing with stat %d\n", Status);
-
-       exit(Status);
-}
-\f/*
-**  OPENCONNECTION -- open connection to SMTP socket
+**     Opens the connection and sends the initial protocol.
 **
 **     Parameters:
 **
 **     Parameters:
-**             host -- the name of the host to connect to.  This
-**                     will be replaced by the canonical name of
-**                     the host.
+**             m -- mailer to create connection to.
+**             pvp -- pointer to parameter vector to pass to
+**                     the mailer.
+**             ctladdr -- controlling address for this mailer.
 **
 **     Returns:
 **
 **     Returns:
-**             File descriptor of connection.
-**             -1 on error.
+**             appropriate exit status -- EX_OK on success.
 **
 **     Side Effects:
 **
 **     Side Effects:
-**             sets 'Status' to represent the problem on error.
+**             creates connection and sends initial protocol.
 */
 
 */
 
-openconnection(host)
-       char *host;
+# define REPLYTYPE(r)  ((r) / 100)
+
+static FILE    *SmtpOut;       /* output file */
+static FILE    *SmtpIn;        /* input file */
+static int     SmtpPid;        /* pid of mailer */
+
+smtpinit(m, pvp, ctladdr)
+       struct mailer *m;
+       char **pvp;
+       ADDRESS *ctladdr;
 {
 {
-       char cmdbuf[100];
-       register int fd;
+       register int r;
+       char buf[MAXNAME];
 
 
-       /* create the command name */
-       sprintf(cmdbuf, "%s -as%s%s", MailCommand,
-                                       Verbose ? " -v" : "",
-                                       Debug ? " -d" : "");
+       /*
+       **  Open the connection to the mailer.
+       */
 
 
-       if (Debug)
-               printf("Creating connection to \"%s\" on %s\n", cmdbuf, host);
+       SmtpPid = openmailer(m, pvp, ctladdr, TRUE, &SmtpOut, &SmtpIn);
 
 
-       /* verify host name */
-       if (rhost(&host) < 0)
-       {
-               if (Debug)
-                       printf("Unknown host %s\n", host);
-               Status = EX_NOHOST;
-               return (-1);
-       }
+       /*
+       **  Get the greeting message.
+       **      This should appear spontaneously.
+       */
 
 
-       /* create connection (we hope) */
-       fd = rexec(&host, SHELLSERVER, cmdbuf, MailUser, MailPassword);
-       if (fd < 0)
-       {
-               Status = EX_TEMPFAIL;
-               return (-1);
-       }
-       InConnection = fdopen(fd, "r");
-       OutConnection = fdopen(fd, "w");
-       if (InConnection == NULL || OutConnection == NULL)
-       {
-               Status = EX_SOFTWARE;
-               return (-1);
-       }
+       r = reply();
+       if (REPLYTYPE(r) != 2)
+               return (EX_TEMPFAIL);
 
 
-       if (Debug)
-               printf("Connection open to %s\n", host);
+       /*
+       **  Send the MAIL command.
+       **      Designates the sender.
+       */
 
 
-       return (0);
+       (void) expand("$g", buf, &buf[sizeof buf - 1]);
+       smtpmessage("MAIL From:<%s>", buf);
+       r = reply();
+       if (REPLYTYPE(r) == 4)
+               return (EX_TEMPFAIL);
+       if (r != 250)
+               return (EX_SOFTWARE);
+       return (EX_OK);
 }
 \f/*
 }
 \f/*
-**     CLOSECONNECTION -- close the connection to the SMTP server.
-**
-**     This routine also sends a handshake.
+**  SMTPMRCP -- designate recipient.
 **
 **     Parameters:
 **
 **     Parameters:
-**             none.
+**             to -- address of recipient.
 **
 **     Returns:
 **
 **     Returns:
-**             none.
+**             exit status corresponding to recipient status.
 **
 **     Side Effects:
 **
 **     Side Effects:
-**             Closes the connection.
+**             Sends the mail via SMTP.
 */
 
 */
 
-closeconnection()
+smtpmrcp(to)
+       ADDRESS *to;
 {
        register int r;
 
 {
        register int r;
 
-       message("QUIT");
+       smtpmessage("MRCP To:<%s>", to->q_user);
+
        r = reply();
        r = reply();
+       if (REPLYTYPE(r) == 4)
+               return (EX_TEMPFAIL);
+       if (r != 250)
+               return (EX_NOUSER);
 
 
-       if (Debug)
-               printf("Closing connection, reply = %d\n", r);
+       return (EX_OK);
 }
 \f/*
 }
 \f/*
-**  RUNSMTP -- run the SMTP protocol over connection.
+**  SMTPFINISH -- finish up sending all the SMTP protocol.
 **
 **     Parameters:
 **
 **     Parameters:
-**             fr -- from person.
-**             tolist -- list of recipients.
+**             m -- mailer being sent to.
+**             editfcn -- a function to call to output the
+**                     text of the message with.
 **
 **     Returns:
 **
 **     Returns:
-**             none.
+**             exit status corresponding to DOIT command.
 **
 **     Side Effects:
 **
 **     Side Effects:
-**             Sends the mail via SMTP.
+**             none.
 */
 
 */
 
-# define REPLYTYPE(r)  ((r) / 100)
-
-runsmtp(fr, tolist)
-       char *fr;
-       char **tolist;
+smtpfinish(m, editfcn)
+       struct mailer *m;
+       int (*editfcn)();
 {
        register int r;
 {
        register int r;
-       register char **t;
-       char buf[MAXLINE];
-
-       /*
-       **  Get the greeting message.
-       **      This should appear spontaneously.
-       */
-
-       r = reply();
-       if (REPLYTYPE(r) != 2)
-               return (EX_TEMPFAIL);
-
-       /*
-       **  Send the MAIL command.
-       **      Designates the sender.
-       */
-
-       message("MAIL From:<%s>", fr);
-       r = reply();
-       if (REPLYTYPE(r) == 4)
-               return (EX_TEMPFAIL);
-       if (r != 250)
-               return (EX_SOFTWARE);
-
-       /*
-       **  Send the recipients.
-       */
-
-       for (t = tolist; *t != NULL; t++)
-       {
-               message("MRCP To:<%s>", *t);
-               r = reply();
-               if (REPLYTYPE(r) == 4)
-                       return (EX_TEMPFAIL);
-               if (r != 250)
-                       return (EX_NOUSER);
-       }
 
        /*
        **  Send the data.
        **      Dot hiding is done here.
        */
 
 
        /*
        **  Send the data.
        **      Dot hiding is done here.
        */
 
-       message("DATA");
+       smtpmessage("DATA");
        r = reply();
        if (REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
        if (r != 354)
                return (EX_SOFTWARE);
        r = reply();
        if (REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
        if (r != 354)
                return (EX_SOFTWARE);
-       while (fgets(buf, sizeof buf, stdin) != NULL)
-       {
-               /* change trailing newline to crlf */
-               register char *p = index(buf, '\n');
-
-               if (p != NULL)
-                       *p = '\0';
-               message("%s%s", buf[0] == '.' ? "." : "", buf);
-       }
-       message(".");
+       (*editfcn)(SmtpOut, m, TRUE);
+       smtpmessage(".");
        r = reply();
        if (REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
        r = reply();
        if (REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
@@ -237,7 +138,7 @@ runsmtp(fr, tolist)
        **  Make the actual delivery happen.
        */
 
        **  Make the actual delivery happen.
        */
 
-       message("DOIT");
+       smtpmessage("DOIT");
        r = reply();
        if (r != 250)
                return (EX_TEMPFAIL);
        r = reply();
        if (r != 250)
                return (EX_TEMPFAIL);
@@ -245,6 +146,31 @@ runsmtp(fr, tolist)
        return (EX_OK);
 }
 \f/*
        return (EX_OK);
 }
 \f/*
+**  SMTPQUIT -- close the SMTP connection.
+**
+**     Parameters:
+**             name -- name of mailer we are quitting.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             sends the final protocol and closes the connection.
+*/
+
+smtpquit(name)
+       char *name;
+{
+       register int i;
+
+       smtpmessage("QUIT");
+       (void) reply();
+       (void) fclose(SmtpIn);
+       (void) fclose(SmtpOut);
+       i = endmailer(SmtpPid, name);
+       giveresponse(i, TRUE, LocalMailer);
+}
+\f/*
 **  REPLY -- read arpanet reply
 **
 **     Parameters:
 **  REPLY -- read arpanet reply
 **
 **     Parameters:
@@ -259,7 +185,7 @@ runsmtp(fr, tolist)
 
 reply()
 {
 
 reply()
 {
-       fflush(OutConnection);
+       (void) fflush(SmtpOut);
 
        if (Debug)
                printf("reply\n");
 
        if (Debug)
                printf("reply\n");
@@ -270,7 +196,7 @@ reply()
                char buf[MAXLINE];
                register int r;
 
                char buf[MAXLINE];
                register int r;
 
-               if (fgets(buf, sizeof buf, InConnection) == NULL)
+               if (fgets(buf, sizeof buf, SmtpIn) == NULL)
                        return (-1);
                if (Verbose)
                        fputs(buf, stdout);
                        return (-1);
                if (Verbose)
                        fputs(buf, stdout);
@@ -283,7 +209,7 @@ reply()
        }
 }
 \f/*
        }
 }
 \f/*
-**  MESSAGE -- send message to server
+**  SMTPMESSAGE -- send message to server
 **
 **     Parameters:
 **             f -- format
 **
 **     Parameters:
 **             f -- format
@@ -293,17 +219,18 @@ reply()
 **             none.
 **
 **     Side Effects:
 **             none.
 **
 **     Side Effects:
-**             writes message to OutChannel.
+**             writes message to SmtpOut.
 */
 
 */
 
-message(f, a, b, c)
+/*VARARGS1*/
+smtpmessage(f, a, b, c)
        char *f;
 {
        char buf[100];
 
        char *f;
 {
        char buf[100];
 
-       sprintf(buf, f, a, b, c);
+       (void) sprintf(buf, f, a, b, c);
        strcat(buf, "\r\n");
        if (Debug)
                fputs(buf, stdout);
        strcat(buf, "\r\n");
        if (Debug)
                fputs(buf, stdout);
-       fputs(buf, OutConnection);
+       fputs(buf, SmtpOut);
 }
 }
index 7c298c9..f9e9aa4 100644 (file)
@@ -1,3 +1,3 @@
-static char    SccsId[] = "@(#)SendMail version 3.62 of %G%";
+static char    SccsId[] = "@(#)SendMail version 3.63 of %G%";
 
 
-char   Version[] = "3.62 [%G%]";
+char   Version[] = "3.63 [%G%]";