+/*-
+ * Copyright (c) 1981 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 lint
+char copyright[] =
+"@(#) Copyright (c) 1981 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mail-dm.c 4.2 (Berkeley) 4/19/91";
+#endif /* not lint */
+
+#include <arpa/netopen.h>
+#include "srvrftp.h"
+#include <statbuf.h>
+#include <arpa/hostnames.h>
+#include <io_buf.h>
+#include <arpa/mail.h>
+#include <ident.h>
+#include <signal.h>
+#include <log.h>
+extern int fout;
+
+/*
+Name:
+ mail
+
+Function:
+ handle the MAIL <user> command over the command connection
+
+Algorithm:
+ see if we have a known user
+
+ if mailbox file can't be gotten
+ return
+ tell him it is ok to go ahead with mail
+
+ while he doesn't type a period
+ read and write data
+ say completed
+
+Parameters:
+ username in arg
+
+Returns:
+ nothing
+
+Globals:
+ arg
+ username=
+
+Calls:
+ strmove
+ getuser
+ loguser
+ openmail
+ closemail
+ getline
+ chown (sys)
+ time (sys)
+ printf (sys)
+ getch (util)
+ putch (util)
+
+Called by:
+ main thru command array
+
+History:
+ initial coding Mark Kampe UCLA-ATS
+ modified 4/13/76 by S. F. Holmgren for Illinois version
+ modified 6/30/76 by S. F. Holmgren to call getmbox
+ modified 10/18/76 by J. S. Kravitz to improve net mail header
+ chown removed by R. Balocca @ CAC, Sunday 1977 February 20
+ getline removed and limit on line length removed by using
+ getch and putch added by R. Balocca @ CAC, 1977 March 8 Tuesday
+ Fixed oversight in above (forgot to translate <crlf> to <lf>)
+ 1977 March 10 Thursday by Rick Balocca @ CAC
+ Added openmail & closemail, added logging, and fixed several
+ bugs on or about 12/21/79 by Eric Allman, UCB/INGRES.
+ Changed to always accept mail -- bad mail will be sent back --
+ 1/9/80 by Eric Allman, UCB/INGRES.
+ Don't print out 350 enter mail or 256 mail accepted messages --
+ sendmail will do that. 8/19/81 Eric Allman UCB/INGRES.
+*/\f
+#define gt (c = getch())
+mail()
+{
+ register char *p; /* general use */
+ register int c;
+ int i;
+
+ /* extern struct io_buf obuf; */
+
+ /* get to open mailbox file descriptor */
+ fflush(&fout);
+ if( (fout = openmail(arg, 0)) < 0 )
+ return;
+
+ for(;;) /* while no error or <crlf>.<crlf> */
+ {
+ /* we are at beginning of line */
+
+ if(gt=='.') /*"."*/
+ {
+ if(gt=='\r') /*".\r"*/
+ {
+ if(gt=='\n') /*".\r\n"*/
+ {
+ /* end of message */
+ break;
+ }
+ else
+ { /*".\r"c*/
+ putch('.');
+ putch('\r');
+ }
+ }
+ else /*"."c"*/
+ putch('.');
+ }
+ /*"-"*/
+ /* c */
+ for(;;)
+ {
+ for(; c != '\r'; gt)
+ {
+ if( c < 0 )
+ {
+ fflush(&fout);
+ write(fout, "\n***** Sender aborted connection *****\n", 39);
+ goto out;
+ }
+ else
+ putch(c);
+ }
+
+ /*"\r"*/
+ if( gt == '\n' )
+ { /*"\r\n"*/
+crlf:
+ putch('\n');
+ break;
+ }
+ else
+ { /*"\r"c*/
+crc:
+ putch('\r');
+ if(c=='\0')
+ gt; /* "\r\0" */
+ /* is arpa escape for "\r" */
+ }
+ }
+ }
+
+out:
+ fflush(&fout);
+ closemail(fout);
+}
+
+\f/*
+Name:
+ datamail
+
+Function:
+ handle the MLFL command
+
+Algorithm:
+ fork
+ make sure we have a valid user
+ say bad user and exit
+ send sock command
+ open data connection
+ get open mailbox file descriptor
+ call rcvdata to receive mail
+
+Parameters:
+ username in arg
+
+Returns:
+ nothing
+
+Globals:
+ arg
+
+Calls:
+ fork (sys)
+ strmove
+ netreply
+ sendsock
+ dataconnection
+ getmbox
+ rcvdata
+ printf (sys)
+ time (sys)
+
+Called by:
+ main thru command array
+
+History:
+ initial coding 4/13/76 by S. F. Holmgren
+ modified 10/18/76 by J. S. Kravitz to put net mail header
+ chown removed by R. Balocca @ CAC, Sunday 1977 February 20
+*/\f
+datamail()
+{
+ register netdata;
+ /* register mboxfid; */
+ register int i;
+
+ i = fork();
+ if (i < 0)
+ {
+ netreply("455 Mail server temporarily unavailable\r\n");
+ return;
+ }
+ else if (i == 0)
+ {
+ fflush(&fout);
+ if ((fout = openmail(arg, 1)) < 0)
+ exit(3);
+
+ /* send sock command */
+ sendsock( U4 );
+
+ /* open data connection */
+ netdata = dataconnection( U4 );
+
+ /* say its ok to proceed */
+ numreply( NUM250 );
+
+ /* get data from net connection and copy to mail file */
+ /* rcvdata( netdata,mboxfid ); */
+ if (rcvdata(netdata, fout) < 0)
+ exit(1);
+
+ /* close the mail, see if ok; if so say ok */
+ fflush(&fout);
+ closemail(fout);
+
+ exit( 0 );
+ }
+}
+\f/*
+** OPENMAIL -- Open a channel to the mail server
+**
+** Gets the mail server started up ready to handle our
+** mail.
+**
+** Algorithm:
+** See if the user is specified.
+** If not, send to user "root".
+** See if the user exists.
+** If not, signal error 450 and return.
+** Fork.
+** Create a pipe
+** Signal "unavailable" and exit on failure.
+** Fork.
+** Signal "unavailable" and exit on failure
+** In child:
+** Call mailer: /etc/delivermail is preferred.
+** In parent:
+** Avoid pipe signals in case delivermail dies.
+** Save the childs pid.
+** Return file descriptor.
+**
+** Notes:
+** The check to see if the user actually exists should
+** go away so that we can do real mail forwarding.
+**
+** Parameters:
+** who -- the user to send the mail to.
+** mode -- 0 -- called from mail
+** 1 -- called from mlfl
+**
+** Returns:
+** File descriptor to send mail to.
+** -1 on failure.
+**
+** Side Effects:
+** Forks /etc/delivermail or /bin/mail or /usr/bin/mail.
+** Becomes "network" in the child.
+**
+** Requires:
+** strmove
+** getuser
+** netreply
+** pipe (sys)
+** fork (sys)
+** close (sys)
+** dup (sys)
+** execl (sys)
+** signal (sys)
+** exit (sys)
+**
+** Called By:
+** mail
+** datamail
+**
+** History:
+** 1/9/80 -- Added 050 & 455 reply messages if execl's
+** fail. Eric Allman UCB/INGRES.
+** 11/26/79 -- Modified to map upper case to lower
+** case. Eric Allman UCB/INGRES.
+** 11/10/79 -- Written by Eric Allman UCB/INGRES
+** 3/6/80 -- Dropped case mapping; delivermail does
+** that now. EPA UCB/INGRES.
+** 8/19/81 -- Added "mode" parameter; call sendmail
+** instead of delivermail. EPA
+*/
+
+int Mail_pid;
+char *Mail_user;
+
+openmail(who, mode)
+ char *who;
+ int mode;
+{
+ register char *w;
+ register int i;
+ int pvect[2];
+ register char *p;
+
+ w = who;
+ if (w == 0)
+ w = "root";
+ Mail_user = w;
+
+ /* see if the user exists */
+ strmove(w, username);
+
+ /* try to get a pipe to the mailer */
+ if (pipe(pvect) < 0)
+ {
+ unavailable:
+ netreply("455 Mail server temporarily unavailable\r\n");
+ return (-1);
+ }
+
+ /* fork */
+ i = fork();
+ if (i < 0)
+ {
+ /* failure */
+ close(pvect[0]);
+ close(pvect[1]);
+ goto unavailable;
+ }
+ else if (i == 0)
+ {
+ /* child */
+ close(pvect[1]);
+ close(0);
+ dup(pvect[0]);
+ close(pvect[0]);
+ setuid(NETUID);
+
+ /* try to call something to deliver the mail */
+ execl("/etc/sendmail", "sendmail", "-v", mode == 1 ? "-af" : "-am", w, 0);
+
+ /* doesn't seem to be anything around */
+ netreply("455 Mail server unavailable\r\n");
+ exit(3);
+ }
+
+ /* else parent */
+ signal(SIGPIPE, SIG_IGN);
+ Mail_pid = i;
+ close(pvect[0]);
+ return (pvect[1]);
+}
+\f/*
+** CLOSEMAIL -- Close the mail file and get actual status
+**
+** The mail file is closed.
+**
+** Algorithm:
+** Wait for the mailer to die.
+** If it wasn't there, be non-comittal.
+** If it died a violent death, give error.
+**
+** Parameters:
+** fd -- the file descriptor of the mail file.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** mailer is soaked up.
+**
+** Requires:
+** close (sys)
+** wait (sys)
+**
+** Called By:
+** mail
+** datamail
+**
+** History:
+** 1/9/80 -- Changed to not check for errors in mailing,
+** since these will be mailed back.
+** 11/10/79 -- Written by Eric Allman UCB/INGRES.
+*/
+
+closemail(fd)
+ int fd;
+{
+ auto int st;
+ register int i;
+
+ /* close the pipe -- mail should go away */
+ close(fd);
+
+ /* wait for its body */
+ while ((i = wait(&st)) != Mail_pid)
+ {
+ if (i < 0)
+ {
+ /* how did this happen? */
+ logmsg(LOG_ERR, "mail from host %d to %s: no child",
+ openparams.o_frnhost & 0377, Mail_user);
+ goto unavailable;
+ }
+ }
+
+ /* 'st' is now the status of the mailer */
+ if ((st & 0377) != 0)
+ {
+ logmsg(LOG_ERR, "mail from host %d to %s: status %o",
+ openparams.o_frnhost & 0377, Mail_user, st);
+unavailable:
+ netreply("455 Mail not delivered -- local system error\r\n");
+ return (-1);
+ }
+
+ return (0);
+}