home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / sendmail / aux / mail-dm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-19  |  9.7 KB  |  468 lines

  1. /*-
  2.  * Copyright (c) 1981 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1981 The Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)mail-dm.c    4.2 (Berkeley) 4/19/91";
  42. #endif /* not lint */
  43.  
  44. #include <arpa/netopen.h>
  45. #include "srvrftp.h"
  46. #include <statbuf.h>
  47. #include <arpa/hostnames.h>
  48. #include <io_buf.h>
  49. #include <arpa/mail.h>
  50. #include <ident.h>
  51. #include <signal.h>
  52. #include <log.h>
  53. extern int fout;
  54.  
  55. /*
  56. Name:
  57.     mail
  58.  
  59. Function:
  60.     handle the MAIL <user> command over the command connection
  61.  
  62. Algorithm:
  63.     see if we have a known user
  64.  
  65.     if mailbox file can't be gotten
  66.         return
  67.     tell him it is ok to go ahead with mail
  68.  
  69.     while he doesn't type a period
  70.         read and write data
  71.     say completed
  72.  
  73. Parameters:
  74.     username in arg
  75.  
  76. Returns:
  77.     nothing
  78.  
  79. Globals:
  80.     arg
  81.     username=
  82.  
  83. Calls:
  84.     strmove
  85.     getuser
  86.     loguser
  87.     openmail
  88.     closemail
  89.     getline
  90.     chown (sys)
  91.     time (sys)
  92.     printf (sys)
  93.     getch    (util)
  94.     putch    (util)
  95.  
  96. Called by:
  97.     main thru command array
  98.  
  99. History:
  100.     initial coding         Mark Kampe UCLA-ATS
  101.     modified 4/13/76 by S. F. Holmgren for Illinois version
  102.     modified 6/30/76 by S. F. Holmgren to call getmbox
  103.     modified 10/18/76 by J. S. Kravitz to improve net mail header
  104.     chown removed by R. Balocca @ CAC, Sunday 1977 February 20
  105.     getline removed and limit on line length removed by using
  106.     getch and putch added by R. Balocca @ CAC, 1977 March 8 Tuesday
  107.     Fixed oversight in above (forgot to translate <crlf> to <lf>)
  108.         1977 March 10 Thursday by Rick Balocca @ CAC
  109.     Added openmail & closemail, added logging, and fixed several
  110.         bugs on or about 12/21/79 by Eric Allman, UCB/INGRES.
  111.     Changed to always accept mail -- bad mail will be sent back --
  112.         1/9/80 by Eric Allman, UCB/INGRES.
  113.     Don't print out 350 enter mail or 256 mail accepted messages --
  114.         sendmail will do that.  8/19/81 Eric Allman UCB/INGRES.
  115. */
  116. #define gt (c = getch())
  117. mail()
  118. {
  119.     register char *p;    /* general use */
  120.     register int c;
  121.     int i;
  122.  
  123.     /* extern struct io_buf obuf; */
  124.  
  125.     /* get to open mailbox file descriptor */
  126.     fflush(&fout);
  127.     if( (fout = openmail(arg, 0)) < 0 )
  128.         return;
  129.  
  130.     for(;;)                /* while no error or <crlf>.<crlf> */
  131.     {
  132.         /* we are at beginning of line */
  133.  
  134.         if(gt=='.')            /*"."*/
  135.         {
  136.             if(gt=='\r')            /*".\r"*/
  137.             {
  138.                 if(gt=='\n')            /*".\r\n"*/
  139.                 {
  140.                     /* end of message */
  141.                     break;
  142.                 }
  143.                 else
  144.                 {                /*".\r"c*/
  145.                     putch('.');
  146.                     putch('\r');
  147.                 }
  148.             }
  149.             else                /*"."c"*/
  150.                 putch('.');
  151.         }
  152.                                 /*"-"*/
  153.                     /* c */
  154.         for(;;)
  155.         {
  156.             for(; c != '\r'; gt)
  157.             {
  158.                 if( c < 0 )
  159.                 {
  160.                     fflush(&fout);
  161.                     write(fout, "\n***** Sender aborted connection *****\n", 39);
  162.                     goto out;
  163.                 }
  164.                 else
  165.                     putch(c);
  166.             }
  167.     
  168.                         /*"\r"*/
  169.             if( gt == '\n' )
  170.             {            /*"\r\n"*/
  171. crlf:
  172.                 putch('\n');
  173.                 break;
  174.             }
  175.             else
  176.             {            /*"\r"c*/
  177. crc:
  178.                 putch('\r');
  179.                 if(c=='\0')
  180.                     gt;    /* "\r\0" */
  181.                         /* is arpa escape for "\r" */
  182.             }
  183.         }
  184.     }
  185.  
  186. out:
  187.     fflush(&fout);
  188.     closemail(fout);
  189. }
  190.  
  191. /*
  192. Name:
  193.     datamail
  194.  
  195. Function:
  196.     handle the MLFL command
  197.  
  198. Algorithm:
  199.     fork
  200.         make sure we have a valid user
  201.             say bad user and exit
  202.         send sock command
  203.         open data connection
  204.         get open mailbox file descriptor
  205.         call rcvdata to receive mail
  206.  
  207. Parameters:
  208.     username in arg
  209.  
  210. Returns:
  211.     nothing
  212.  
  213. Globals:
  214.     arg
  215.  
  216. Calls:
  217.     fork (sys)
  218.     strmove
  219.     netreply
  220.     sendsock
  221.     dataconnection
  222.     getmbox
  223.     rcvdata
  224.     printf (sys)
  225.     time (sys)
  226.  
  227. Called by:
  228.     main thru command array 
  229.  
  230. History:
  231.     initial coding 4/13/76 by S. F. Holmgren
  232.     modified 10/18/76 by J. S. Kravitz to put net mail header
  233.     chown removed by R. Balocca @ CAC, Sunday 1977 February 20
  234. */
  235. datamail()
  236. {
  237.     register netdata;
  238.     /* register mboxfid; */
  239.     register int i;
  240.  
  241.     i = fork();
  242.     if (i < 0)
  243.     {
  244.         netreply("455 Mail server temporarily unavailable\r\n");
  245.         return;
  246.     }
  247.     else if (i == 0)
  248.     {
  249.         fflush(&fout);
  250.         if ((fout = openmail(arg, 1)) < 0)
  251.             exit(3);
  252.  
  253.         /* send sock command */
  254.         sendsock( U4 );
  255.  
  256.         /* open data connection */
  257.         netdata = dataconnection( U4 );
  258.  
  259.         /* say its ok to proceed */
  260.         numreply( NUM250 );
  261.  
  262.         /* get data from net connection and copy to mail file */
  263.         /* rcvdata( netdata,mboxfid ); */
  264.         if (rcvdata(netdata, fout) < 0)
  265.             exit(1);
  266.  
  267.         /* close the mail, see if ok; if so say ok */
  268.         fflush(&fout);
  269.         closemail(fout);
  270.  
  271.         exit( 0 );
  272.     }
  273. }
  274. /*
  275. **  OPENMAIL -- Open a channel to the mail server
  276. **
  277. **    Gets the mail server started up ready to handle our
  278. **    mail.
  279. **
  280. **    Algorithm:
  281. **        See if the user is specified.
  282. **            If not, send to user "root".
  283. **        See if the user exists.
  284. **            If not, signal error 450 and return.
  285. **        Fork.
  286. **        Create a pipe
  287. **            Signal "unavailable" and exit on failure.
  288. **        Fork.
  289. **            Signal "unavailable" and exit on failure
  290. **            In child:
  291. **                Call mailer: /etc/delivermail is preferred.
  292. **            In parent:
  293. **                Avoid pipe signals in case delivermail dies.
  294. **                Save the childs pid.
  295. **                Return file descriptor.
  296. **
  297. **    Notes:
  298. **        The check to see if the user actually exists should
  299. **        go away so that we can do real mail forwarding.
  300. **
  301. **    Parameters:
  302. **        who -- the user to send the mail to.
  303. **        mode -- 0 -- called from mail
  304. **            1 -- called from mlfl
  305. **
  306. **    Returns:
  307. **        File descriptor to send mail to.
  308. **        -1 on failure.
  309. **
  310. **    Side Effects:
  311. **        Forks /etc/delivermail or /bin/mail or /usr/bin/mail.
  312. **        Becomes "network" in the child.
  313. **
  314. **    Requires:
  315. **        strmove
  316. **        getuser
  317. **        netreply
  318. **        pipe (sys)
  319. **        fork (sys)
  320. **        close (sys)
  321. **        dup (sys)
  322. **        execl (sys)
  323. **        signal (sys)
  324. **        exit (sys)
  325. **
  326. **    Called By:
  327. **        mail
  328. **        datamail
  329. **
  330. **    History:
  331. **        1/9/80 -- Added 050 & 455 reply messages if execl's
  332. **            fail.  Eric Allman UCB/INGRES.
  333. **        11/26/79 -- Modified to map upper case to lower
  334. **            case.  Eric Allman UCB/INGRES.
  335. **        11/10/79 -- Written by Eric Allman UCB/INGRES
  336. **        3/6/80 -- Dropped case mapping; delivermail does
  337. **            that now.  EPA UCB/INGRES.
  338. **        8/19/81 -- Added "mode" parameter; call sendmail
  339. **            instead of delivermail.  EPA
  340. */
  341.  
  342. int Mail_pid;
  343. char *Mail_user;
  344.  
  345. openmail(who, mode)
  346.     char *who;
  347.     int mode;
  348. {
  349.     register char *w;
  350.     register int i;
  351.     int pvect[2];
  352.     register char *p;
  353.  
  354.     w = who;
  355.     if (w == 0)
  356.         w = "root";
  357.     Mail_user = w;
  358.  
  359.     /* see if the user exists */
  360.     strmove(w, username);
  361.  
  362.     /* try to get a pipe to the mailer */
  363.     if (pipe(pvect) < 0)
  364.     {
  365.       unavailable:
  366.         netreply("455 Mail server temporarily unavailable\r\n");
  367.         return (-1);
  368.     }
  369.  
  370.     /* fork */
  371.     i = fork();
  372.     if (i < 0)
  373.     {
  374.         /* failure */
  375.         close(pvect[0]);
  376.         close(pvect[1]);
  377.         goto unavailable;
  378.     }
  379.     else if (i == 0)
  380.     {
  381.         /* child */
  382.         close(pvect[1]);
  383.         close(0);
  384.         dup(pvect[0]);
  385.         close(pvect[0]);
  386.         setuid(NETUID);
  387.  
  388.         /* try to call something to deliver the mail */
  389.         execl("/etc/sendmail", "sendmail", "-v", mode == 1 ? "-af" : "-am", w, 0);
  390.  
  391.         /* doesn't seem to be anything around */
  392.         netreply("455 Mail server unavailable\r\n");
  393.         exit(3);
  394.     }
  395.  
  396.     /* else parent */
  397.     signal(SIGPIPE, SIG_IGN);
  398.     Mail_pid = i;
  399.     close(pvect[0]);
  400.     return (pvect[1]);
  401. }
  402. /*
  403. **  CLOSEMAIL -- Close the mail file and get actual status
  404. **
  405. **    The mail file is closed.
  406. **
  407. **    Algorithm:
  408. **        Wait for the mailer to die.
  409. **            If it wasn't there, be non-comittal.
  410. **        If it died a violent death, give error.
  411. **
  412. **    Parameters:
  413. **        fd -- the file descriptor of the mail file.
  414. **
  415. **    Returns:
  416. **        none.
  417. **
  418. **    Side Effects:
  419. **        mailer is soaked up.
  420. **
  421. **    Requires:
  422. **        close (sys)
  423. **        wait (sys)
  424. **
  425. **    Called By:
  426. **        mail
  427. **        datamail
  428. **
  429. **    History:
  430. **        1/9/80 -- Changed to not check for errors in mailing,
  431. **            since these will be mailed back.
  432. **        11/10/79 -- Written by Eric Allman UCB/INGRES.
  433. */
  434.  
  435. closemail(fd)
  436.     int fd;
  437. {
  438.     auto int st;
  439.     register int i;
  440.  
  441.     /* close the pipe -- mail should go away */
  442.     close(fd);
  443.  
  444.     /* wait for its body */
  445.     while ((i = wait(&st)) != Mail_pid)
  446.     {
  447.         if (i < 0)
  448.         {
  449.             /* how did this happen? */
  450.             logmsg(LOG_ERR, "mail from host %d to %s: no child",
  451.                 openparams.o_frnhost & 0377, Mail_user);
  452.             goto unavailable;
  453.         }
  454.     }
  455.  
  456.     /* 'st' is now the status of the mailer */
  457.     if ((st & 0377) != 0)
  458.     {
  459.         logmsg(LOG_ERR, "mail from host %d to %s: status %o",
  460.             openparams.o_frnhost & 0377, Mail_user, st);
  461. unavailable:
  462.         netreply("455 Mail not delivered -- local system error\r\n");
  463.         return (-1);
  464.     }
  465.  
  466.     return (0);
  467. }
  468.