home *** CD-ROM | disk | FTP | other *** search
/ ftp.uv.es / 2014.11.ftp.uv.es.tar / ftp.uv.es / pub / unix / elm-2.4-pl20.tar.Z / elm-2.4-pl20.tar / filter / actions.c next >
C/C++ Source or Header  |  1993-01-12  |  12KB  |  461 lines

  1.  
  2. static char rcsid[] ="@(#)$Id: actions.c,v 5.3 1992/12/24 19:22:05 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.3 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1988-1992 USENET Community Trust
  8.  *             Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein - elm@DSI.COM
  13.  *            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: actions.c,v $
  17.  * Revision 5.3  1992/12/24  19:22:05  syd
  18.  * Quote from the filter of phrase to prevent RFC-822 parsing problems
  19.  * From: Syd via request from Ian Stewartson <istewart@dlvax2.datlog.co.uk>
  20.  *
  21.  * Revision 5.2  1992/12/11  02:16:08  syd
  22.  * remove unreachable return(0) at end of function
  23.  * From: Syd
  24.  *
  25.  * Revision 5.1  1992/10/03  22:18:09  syd
  26.  * Initial checkin as of 2.4 Release at PL0
  27.  *
  28.  *
  29.  ******************************************************************************/
  30.  
  31.  
  32. /** RESULT oriented routines *chuckle*.  These routines implement the
  33.     actions that result from either a specified rule being true or from
  34.     the default action being taken.
  35. **/
  36.  
  37. #include <stdio.h>
  38. #include <pwd.h>
  39. #include <ctype.h>
  40. #include <fcntl.h>
  41.  
  42. #include "defs.h"
  43. #include "filter.h"
  44. #include "s_filter.h"
  45.  
  46. FILE *emergency_local_delivery();
  47.  
  48. mail_message(address)
  49. char *address;
  50. {
  51.       /* Called with an address to send mail to.   For various reasons
  52.        * that are too disgusting to go into herein, we're going to actually
  53.        * open the users mailbox and by hand add this message.  Yech.
  54.        * NOTE, of course, that if we're going to MAIL the message to someone
  55.        * else, that we'll try to do nice things with it on the fly...
  56.        */
  57.  
  58.     FILE *pipefd, *tempfd, *mailfd;
  59.     int  in_header = TRUE, line_count = 0, mailunit, pid, statusp;
  60.     char tempfile[SLEN], mailbox[SLEN], lockfile[SLEN],
  61.          buffer[VERY_LONG_STRING], *cp;
  62.  
  63.     if (verbose && ! log_actions_only && outfd != NULL)
  64.       fprintf(outfd, catgets(elm_msg_cat,FilterSet,FilterMailingMessage,
  65.                  "filter (%s): Mailing message to %s\n"), 
  66.           username, address);
  67.  
  68.     if (! show_only) {
  69.       sprintf(tempfile, "%s.%d", filter_temp, getpid());
  70.  
  71.       if ((tempfd = fopen(tempfile, "r")) == NULL) {
  72.         if (outfd != NULL)
  73.           fprintf(outfd, catgets(elm_msg_cat,FilterSet,
  74.                      FilterCantOpenTempFile2,
  75.               "filter (%s): Can't open temp file %s!!\n"), 
  76.             username, tempfile);
  77.         if (outfd != NULL) fclose(outfd);
  78.         exit(1);
  79.       }
  80.          
  81.       if (strcmp(address, username) != 0) {    /* mailing to someone else */
  82.         
  83.         if (already_been_forwarded) {    /* potential looping! */
  84.           if (contains(from, username)) {
  85.         if (outfd != NULL)
  86.               fprintf(outfd,
  87.               catgets(elm_msg_cat,FilterSet,FilterLoopDetected, 
  88.     "filter (%s): Filter loop detected!  Message left in file %s.%d\n"), 
  89.             username, filter_temp, getpid());
  90.             if (outfd != NULL) fclose(outfd);
  91.             exit(0);
  92.           }
  93.         }
  94.  
  95.         if (strcmp(sendmail, mailer) == 0)
  96.           sprintf(buffer, "%s %s %s", sendmail, smflags, address);
  97.         else
  98.           sprintf(buffer, "%s %s", mailer, address);
  99.  
  100.         /*
  101.          * we do a fork/exec here to prevent evil people
  102.          * from abusing the setgid privileges of filter.
  103.          */
  104.         
  105.         if ( (pid=fork()) > 0 ) /* we're the parent */
  106.           {
  107.             wait(&statusp);
  108.             if (statusp!=0)
  109.               {
  110.                 fprintf(outfd,
  111.                     catgets(elm_msg_cat,
  112.                         FilterSet,FilterBadWaitStat,
  113.             "filter (%s): Command \"%s\" exited with value %d\n"),
  114.                     username,buffer,statusp);
  115.               }
  116.           }
  117.         else if (pid==0) /* we're the child */
  118.           {
  119.             /* use safe permissions */
  120.             
  121.             setuid(user_uid);
  122.             setgid(user_gid);
  123.             
  124.             if ((pipefd = popen(buffer, "w")) == NULL) {
  125.               if (outfd != NULL)
  126.                 fprintf(outfd,catgets(elm_msg_cat,
  127.                           FilterSet,FilterPopenFailed,
  128.           "filter (%s): popen %s failed!\n"), username, buffer);
  129.               sprintf(buffer, "((%s %s %s ; %s %s) & ) < %s &",
  130.                   sendmail , smflags, address, remove_cmd,
  131.                   tempfile, tempfile);
  132.               exit(system(buffer));
  133.  
  134.             }
  135.             
  136.             fprintf(pipefd, "Subject: \"%s\"\n", subject);
  137.             fprintf(pipefd, catgets(elm_msg_cat,FilterSet,
  138.                         FilterFromTheFilterOf,
  139.                     "From: \"The Filter of %s@%s\" <%s>\n"), 
  140.                 username, hostname, username);
  141.             fprintf(pipefd, "To: %s\n", address);
  142.             fprintf(pipefd, catgets(elm_msg_cat,
  143.                         FilterSet,FilterXFilteredBy,
  144.                 "X-Filtered-By: filter, version %s\n\n"),
  145.                 VERSION);
  146.             
  147.             fprintf(pipefd, catgets(elm_msg_cat,
  148.                         FilterSet,FilterBeginMesg,
  149.                 "-- Begin filtered message --\n\n"));
  150.             
  151.             while (fgets(buffer, SLEN, tempfd) != NULL)
  152.               if (already_been_forwarded && in_header)
  153.             in_header = (strlen(buffer) == 1? 0 : in_header);
  154.               else
  155.             fprintf(pipefd," %s", buffer);
  156.             
  157.             fprintf(pipefd, catgets(elm_msg_cat,
  158.                         FilterSet,FilterEndMesg,
  159.                 "\n-- End of filtered message --\n"));
  160.             fclose(pipefd);
  161.             fclose(tempfd);
  162.  
  163.             exit(0);
  164.  
  165.           }
  166.         else /* fork failed */
  167.           {
  168.             fprintf(outfd,
  169.                 catgets(elm_msg_cat,
  170.                     FilterSet,FilterForkFailed,
  171.             "filter (%s): fork of command \"%s\" failed\n"),
  172.                 username,buffer);
  173.           }
  174.         
  175.         return;        /* YEAH!  Wot a slick program, eh? */
  176.       
  177.       }
  178.       
  179.       /** OTHERWISE it is to the current user... **/
  180.  
  181.       sprintf(mailbox, "%s%s", mailhome, username);
  182.  
  183.       if (!lock()) {
  184.         if (outfd != NULL) {
  185.           fprintf(outfd, catgets(elm_msg_cat,FilterSet,
  186.                      FilterCouldntCreateLockFile,
  187.              "filter (%s): Couldn't create lockfile %s\n"),
  188.             username, lockfile);
  189.           fprintf(outfd, catgets(elm_msg_cat,FilterSet,
  190.                      FilterCantOpenMailBox,
  191.              "filter (%s): Can't open mailbox %s!\n"),
  192.             username, mailbox);
  193.         }
  194.         if ((mailfd = emergency_local_delivery()) == NULL)
  195.           exit(1);
  196.       }
  197.       else if ((mailunit = open(mailbox,
  198.                     O_APPEND | O_WRONLY | O_CREAT, 0600)) >= 0)
  199.         mailfd = fdopen(mailunit, "a");
  200.       else if ((mailfd = emergency_local_delivery()) == NULL)
  201.         exit(1);
  202.  
  203.       while (fgets(buffer, sizeof(buffer), tempfd) != NULL) {
  204.         line_count++;
  205.         if (the_same(buffer, "From ") && line_count > 1)
  206.           fprintf(mailfd, ">%s", buffer);
  207.         else
  208.           fputs(buffer, mailfd);
  209.       }
  210.  
  211.       fputs("\n", mailfd);
  212.  
  213.       fclose(mailfd);
  214.       unlock();        /* blamo or not?  Let it decide! */
  215.       fclose(tempfd);
  216.     } /* end if show only */
  217. }
  218.  
  219. save_message(foldername)
  220. char *foldername;
  221. {
  222.     /** Save the message in a folder.  Use full file buffering to
  223.         make this work without contention problems **/
  224.  
  225.     FILE
  226.          *fd, *tempfd;
  227.     int
  228.          filter_pid, gid, pid,
  229.          statusp, ret;
  230.  
  231.     /* allow for ~ file names expansion in rules */
  232.     (void) expand_filename(foldername);
  233.  
  234.     if (verbose && outfd != NULL)
  235.       fprintf(outfd, catgets(elm_msg_cat,FilterSet,FilterSavedMessage,
  236.                  "filter (%s): Message saved in folder %s\n"), 
  237.           username, foldername);
  238.  
  239.     if (show_only)
  240.          return(0);
  241.  
  242.     gid=getgid();
  243.     filter_pid = getpid();
  244.     
  245.     /*
  246.      * need to save filter's PID because the child process
  247.      * will have different PID
  248.      */
  249.     
  250.     if (gid != user_gid) /* then fork */
  251.     {
  252.           
  253.           if ((pid=fork()) > 0) /* we're the parent */
  254.           {
  255.             wait(&statusp);
  256.             return(statusp);
  257.               
  258.           }
  259.           else if (pid == 0) /* we're the child */
  260.           {
  261.             /*
  262.              *  we want the file to have
  263.              *  the user's group id
  264.              */
  265.             
  266.             ret = setgid(user_gid);
  267.             ret = save_to_folder(foldername,filter_pid);
  268.             
  269.             exit(ret);
  270.             
  271.           }
  272.           else /* fork failed */
  273.           {
  274.             fprintf(outfd,
  275.                 catgets(elm_msg_cat,
  276.                     FilterSet,FilterForkSaveFailed,
  277.             "filter (%s): fork-and-save message failed\n\
  278. \tsaving with current group id\n"),
  279.                 username);
  280.             /*
  281.              * save with the current group id.
  282.              */
  283.             ret = save_to_folder(foldername,filter_pid);
  284.             return(ret);
  285.             
  286.           }
  287.     }
  288.     else
  289.     {
  290.           /*
  291.            *  ok to save with current group id.
  292.            */
  293.           ret = save_to_folder(foldername,filter_pid);
  294.           return(ret);
  295.           
  296.     }
  297. }
  298.  
  299. save_to_folder(foldername,filter_pid)
  300. char
  301.      *foldername;
  302. int
  303.      filter_pid;
  304. {
  305.       /*
  306.        * this function does the actual work of saving the message
  307.        * in the named folder.
  308.        */
  309.       
  310.       FILE  *fd, *tempfd;
  311.       char  filename[SLEN], buffer[SLEN];
  312.       int   fdunit;
  313.       
  314.       sprintf(filename, "%s.%d", filter_temp, filter_pid);
  315.       
  316.       if ((fdunit = open(foldername,
  317.              O_APPEND | O_WRONLY | O_CREAT, 0600)) < 0) {
  318.         if (outfd != NULL)
  319.          fprintf(outfd, 
  320.              catgets(elm_msg_cat,
  321.                  FilterSet,FilterCantSaveMessageToFolder,
  322.          "filter (%s): can't save message to requested folder %s!\n"),
  323.              username, foldername);
  324.         return(1);
  325.       }
  326.       fd = fdopen(fdunit,"a");
  327.       
  328.       if ((tempfd = fopen(filename, "r")) == NULL) {
  329.         if (outfd != NULL)
  330.          fprintf(outfd,catgets(elm_msg_cat,FilterSet,
  331.                        FilterCantOpenTempFile3, 
  332.                "filter (%s): can't open temp file %s for reading!\n"),
  333.              username,filename);
  334.         return(1);
  335.       }
  336.       
  337.       while (fgets(buffer, sizeof(buffer), tempfd) != NULL)
  338.        fputs(buffer, fd);
  339.       
  340.       /*
  341.        * Add two newlines, to ensure that other mailers (which, unlike
  342.        * elm, may only look for \n\nFrom_ as the start-of-message
  343.        * indicator).
  344.        */
  345.       
  346.       /** fprintf(fd, "%s", "\n\n"); **/
  347.       fprintf(fd, "\n\n");
  348.       
  349.       fclose(fd);
  350.       fclose(tempfd);
  351.       
  352.       return(0);
  353. }
  354.  
  355. execute(command)
  356. char *command;
  357. {
  358.     /** execute the indicated command, feeding as standard input the
  359.         message we have.
  360.     **/
  361.  
  362.         int pid, statusp;
  363.     char buffer[SLEN];
  364.  
  365.     if (verbose && outfd != NULL)
  366.       fprintf(outfd, catgets(elm_msg_cat,FilterSet,FilterExecutingCmd,
  367.            "filter (%s): Executing %s\n"), username, command);
  368.  
  369.     if (! show_only) {
  370.           sprintf(buffer, "%s %s.%d | %s",
  371.               cat, filter_temp, getpid(), command);
  372.  
  373.           if ( (pid=fork()) > 0) /* we're the parent */
  374.         {
  375.               wait(&statusp);
  376.               if (statusp!=0)
  377.             {
  378.                   fprintf(outfd,
  379.                       catgets(elm_msg_cat,
  380.                           FilterSet,FilterBadWaitStat,
  381.               "filter (%s): Command \"%s\" exited with value %d\n"),
  382.                           username,command,statusp);
  383.             }
  384.               
  385.         }
  386.           else if (pid==0)/* we're the child */
  387.         {
  388.               /*
  389.                * reset uid/gid to user's uid and gid
  390.                */
  391.               setgid(user_gid);
  392.               setuid(user_uid);
  393.               exit(system(buffer));
  394.         }
  395.           else /* fork() failed */
  396.         {
  397.               fprintf(outfd,
  398.                   catgets(elm_msg_cat,
  399.                       FilterSet,FilterForkFailed,
  400.               "filter (%s): fork of command \"%s\" failed\n"),
  401.                   username,command);
  402.         }
  403.           
  404.     }
  405. }
  406.  
  407. FILE *
  408. emergency_local_delivery()
  409. {
  410.     /** This is called when we can't deliver the mail to the usual
  411.         mailbox in the usual way ...
  412.     **/
  413.  
  414.     FILE *tempfd;
  415.     char  mailbox[SLEN];
  416.     int   mailunit;
  417.  
  418.     sprintf(mailbox, "%s/%s", home, EMERGENCY_MAILBOX);
  419.  
  420.     if ((mailunit = open(mailbox, O_APPEND | O_WRONLY | O_CREAT, 0600)) < 0) {
  421.       if (outfd != NULL)
  422.         fprintf(outfd, catgets(elm_msg_cat,FilterSet,FilterCantOpenEither,
  423.                  "filter (%s): Can't open %s either!!\n"),
  424.             username, mailbox);
  425.  
  426.       sprintf(mailbox,"%s/%s", home, EMERG_MBOX); 
  427.  
  428.       if ((mailunit = open(mailbox, O_APPEND | O_WRONLY | O_CREAT, 0600)) < 0) {
  429.  
  430.         if (outfd != NULL) {
  431.           fprintf(outfd, catgets(elm_msg_cat,FilterSet,
  432.                      FilterCantOpenEither,
  433.                  "filter (%s): Can't open %s either!!\n"),
  434.               username, mailbox);
  435.           fprintf(outfd,catgets(elm_msg_cat,FilterSet,FilterCantOpenAny, 
  436.               "filter (%s): I can't open ANY mailboxes!  Augh!!\n"),
  437.                username);
  438.          }
  439.         
  440.         /* DIE DIE DIE DIE!! */
  441.          leave(catgets(elm_msg_cat,FilterSet,FilterCantOpenAnyLeave,
  442.                "Cannot open any mailbox"));
  443.        }
  444.        else
  445.          if (outfd != NULL)
  446.            fprintf(outfd,catgets(elm_msg_cat,FilterSet,
  447.                      FilterUsingEmergMbox,
  448.             "filter (%s): Using %s as emergency mailbox\n"),
  449.                username, mailbox);
  450.       }
  451.       else
  452.         if (outfd != NULL)
  453.           fprintf(outfd,catgets(elm_msg_cat,FilterSet,
  454.                      FilterUsingEmergMbox,
  455.             "filter (%s): Using %s as emergency mailbox\n"), 
  456.               username, mailbox);
  457.  
  458.     tempfd = fdopen(mailunit, "a");
  459.     return((FILE *) tempfd);
  460. }
  461.