home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / ONLINE / ELM23-2 / ELM23-2.ZIP / src / fileio.c < prev    next >
C/C++ Source or Header  |  1996-07-30  |  16KB  |  526 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: fileio.c,v 4.1.1.1 90/10/07 19:48:08 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 4.1.1.1 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1986, 1987 Dave Taylor
  8.  *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log:    fileio.c,v $
  17.  * Revision 4.1.1.1  90/10/07  19:48:08  syd
  18.  * fix the bounce problem reported earlier when using MMDF submit as the MTA.
  19.  * From: Jim Clausing <jac%brahms.tinton.ccur.com@RELAY.CS.NET>
  20.  *
  21.  * Revision 4.1  90/04/28  22:43:06  syd
  22.  * checkin of Elm 2.3 as of Release PL0
  23.  *
  24.  *
  25.  ******************************************************************************/
  26.  
  27. /** File I/O routines, including deletion from the folder!
  28.  
  29. **/
  30.  
  31. #include "headers.h"
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #include <ctype.h>
  35. #include <errno.h>
  36.  
  37. #ifdef BSD
  38. #undef tolower
  39. #endif
  40.  
  41. #ifndef OS2
  42. extern int errno;
  43. #endif
  44.  
  45. char *error_name(), *index();
  46.  
  47. copy_message(prefix,
  48.          dest_file,
  49.          remove_header,
  50.          remote,
  51.          update_status,
  52.          mmdf_head,
  53.            remail,
  54.            decrypt)
  55. char *prefix;
  56. FILE *dest_file;
  57. int  remove_header, remote, update_status, mmdf_head, remail, decrypt;
  58. {
  59.     /** Copy current message to destination file, with optional 'prefix'
  60.         as the prefix for each line.  If remove_header is true, it will
  61.         skip lines in the message until it finds the end of header line...
  62.         then it will start copying into the file... If remote is true
  63.         then it will append "remote from <hostname>" at the end of the
  64.         very first line of the file (for remailing)
  65.  
  66.         If "forwarding" is true then it'll do some nice things to
  67.         ensure that the forwarded message looks pleasant; e.g. remove
  68.         stuff like ">From " lines and "Received:" lines.
  69.  
  70.         If "update_status" is true then it will write a new Status:
  71.         line at the end of the headers.  It never copies an existing one.
  72.     **/
  73.  
  74.     char buffer[LONG_STRING];
  75.     register struct header_rec *current_header = headers[current-1];
  76.     register int  lines, front_line, next_front,
  77.           in_header = 1, first_line = TRUE, ignoring = FALSE;
  78.     int    end_header = 0;
  79.     int sender_added = 0;
  80.     FILE *cryptfile;
  81.     char cfilename[SLEN], dfilename[SLEN], basefilename[SLEN];
  82.     char ans;
  83.     int  tlines;
  84.  
  85.       /** get to the first line of the message desired **/
  86.  
  87.     if (fseek(mailfile, current_header->offset, 0) == -1) {
  88.        dprint(1, (debugfile,
  89.         "ERROR: Attempt to seek %d bytes into file failed (%s)",
  90.         current_header->offset, "copy_message"));
  91.        error1("ELM [seek] failed trying to read %d bytes into file.",
  92.          current_header->offset);
  93.        return;
  94.     }
  95.  
  96.     /* how many lines in message? */
  97.  
  98.     lines = current_header->lines;
  99.  
  100.     /* set up for forwarding just in case... */
  101.  
  102.     if (forwarding)
  103.       remove_header = FALSE;
  104.  
  105.     /* now while not EOF & still in message... copy it! */
  106.  
  107.     next_front = TRUE;
  108.  
  109.     while (lines) {
  110.       if (fgets(buffer, sizeof(buffer), mailfile) == NULL)
  111.         break;
  112.  
  113.       fixline(buffer);
  114.       front_line = next_front;
  115.  
  116.       if(buffer[strlen(buffer)-1] == '\n') {
  117.     lines--;    /* got a full line */
  118.     next_front = TRUE;
  119.       }
  120.       else
  121.     next_front = FALSE;
  122.  
  123.       if (front_line && ignoring)
  124.     ignoring = whitespace(buffer[0]);
  125.  
  126.       if (ignoring)
  127.     continue;
  128.  
  129. #ifdef MMDF
  130.       if (mmdf_head && strcmp(buffer, MSG_SEPERATOR) == 0)
  131.     continue;
  132. #endif /* MMDF */
  133.  
  134.       /* are we still in the header? */
  135.  
  136.       if (in_header && front_line) {
  137.     if (strlen(buffer) < 2) {
  138.       in_header = 0;
  139.       end_header = -1;
  140.       if (remail && !sender_added) {
  141.         if (fprintf(dest_file, "%sSender: %s\n", prefix, username) == EOF) {
  142.           Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
  143.           dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  144.           rm_temps_exit();
  145.         }
  146.       }
  147.     }
  148.     else if (!isspace(*buffer)
  149.           && index(buffer, ':') == NULL
  150. #ifdef MMDF
  151.           && strcmp(buffer, MSG_SEPERATOR) != 0
  152. #endif /* MMDF */
  153.         ) {
  154.       in_header = 0;
  155.       end_header = 1;
  156.       if (remail && !sender_added) {
  157.         if (fprintf(dest_file, "%sSender: %s\n", prefix, username) == EOF) {
  158.           Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
  159.           dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  160.           rm_temps_exit();
  161.         }
  162.       }
  163.     } else if (in_header && remote && first_word(buffer, "Sender:")) {
  164.       if (remail)
  165.         if (fprintf(dest_file, "%sSender: %s\n", prefix, username) == EOF) {
  166.           Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
  167.           dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  168.           rm_temps_exit();
  169.         }
  170.       sender_added = TRUE;
  171.       continue;
  172.     }
  173.     if (end_header) {
  174.       if (update_status) {
  175.           if (isoff(current_header->status, NEW)) {
  176.         if (ison(current_header->status, UNREAD)) {
  177.           if (fprintf(dest_file, "%sStatus: O\n", prefix) == EOF) {
  178.             Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
  179.             dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  180.             rm_temps_exit();
  181.           }
  182.         } else    /* read */
  183. #ifdef BSD
  184.           if (fprintf(dest_file, "%sStatus: OR\n", prefix) == EOF) {
  185. #else
  186.           if (fprintf(dest_file, "%sStatus: RO\n", prefix) == EOF) {
  187. #endif
  188.             Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
  189.             dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  190.             rm_temps_exit();
  191.           }
  192.         update_status = FALSE; /* do it only once */
  193.           }    /* else if NEW - indicate NEW with no Status: line. This is
  194.          * important if we resync a mailfile - we don't want
  195.          * NEW status lost when we copy each message out.
  196.          * It is the responsibility of the function that calls
  197.          * this function to unset NEW as appropriate to its
  198.          * reason for using this function to copy a message
  199.          */
  200.  
  201.         /*
  202.          * add the missing newline for RFC 822
  203.          */
  204.           if (end_header > 0) {
  205.         /* add the missing newline for RFC 822 */
  206.         if (fprintf(dest_file, "\n") == EOF) {
  207.           Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
  208.           dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  209.           rm_temps_exit();
  210.         }
  211.           }
  212.       }
  213.     }
  214.       }
  215.  
  216.       if (in_header) {
  217.     /* Process checks while in header area */
  218.  
  219.     if (remove_header) {
  220.       ignoring = TRUE;
  221.       continue;
  222.     }
  223.  
  224.     /* add remote on to front? */
  225.     if (first_line && remote) {
  226.       no_ret(buffer);
  227. #ifndef MMDF
  228.       if (fprintf(dest_file, "%s%s remote from %s\n",
  229.           prefix, buffer, hostname) == EOF) {
  230.         Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
  231.         dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  232.         rm_temps_exit();
  233.       }
  234. #else
  235.       if (first_word(buffer, "From ")) {
  236.         if (strcmp(sendmail, mailer) != 0)
  237.         if (fprintf(dest_file, "%s%s remote from %s\n",
  238.             prefix, buffer, hostname) == EOF) {
  239.         Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
  240.         dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  241.         rm_temps_exit();
  242.         }
  243.       } else {
  244.         if (fprintf(dest_file, "%s%s\n", prefix, buffer) == EOF) {
  245.         Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
  246.         dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  247.         rm_temps_exit();
  248.         }
  249.       }
  250. #endif /* MMDF */
  251.       first_line = FALSE;
  252.       continue;
  253.     }
  254.  
  255.     if (!forwarding) {
  256.       if(! first_word(buffer, "Status:")) {
  257.         if (fprintf(dest_file, "%s%s", prefix, buffer) == EOF) {
  258.               dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  259.           rm_temps_exit();
  260.           }
  261.         continue;
  262.       } else {
  263.         ignoring = TRUE;
  264.         continue;    /* we will output a new Status: line later, if desired. */
  265.       }
  266.     }
  267.     else { /* forwarding */
  268.  
  269.       if (first_word(buffer, "Received:"   ) ||
  270.           first_word(buffer, "From "       ) ||
  271.           first_word(buffer, ">From"       ) ||
  272.           first_word(buffer, "Status:"     ) ||
  273.           first_word(buffer, "Return-Path:"))
  274.           ignoring = TRUE;
  275.       else
  276.         if (remail && first_word(buffer, "To:")) {
  277.           if (fprintf(dest_file, "%sOrig-%s", prefix, buffer) == EOF) {
  278.                 dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  279.             rm_temps_exit();
  280.           }
  281.         } else {
  282.           if (fprintf(dest_file, "%s%s", prefix, buffer) == EOF) {
  283.                 dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  284.             rm_temps_exit();
  285.           }
  286.         }
  287.     }
  288.       }
  289.       else { /* not in header */
  290.         /* Process checks that occur after the header area */
  291.  
  292.     /***  Check to see if text is a PGP message  ***/
  293.  
  294.     /*  if buffer starts with "-----BEGIN PGP MESSAGE-----"
  295.            AND decrypt = TRUE
  296.           divert rest of message to cryptfile
  297.           decrypt cryptfile file.
  298.           if success, copy decrypted file into dest_file, then set
  299.               lines = 0 to stop copying from mailfile.
  300.           else just continue
  301.           continue
  302.     */
  303.  
  304.     if( first_word(buffer, "-----BEGIN PGP MESSAGE-----")
  305.        && decrypt ) {
  306.       PutLine1(LINES-1,0,"Message encrypted with PGP. Do you wish to decrypt? (y/n) y%c", BACKSPACE);
  307.       fflush(stdout);
  308.       ans = ReadCh();
  309.       if( tolower(ans) != 'n' ) {
  310.         Write_to_screen("Yes.",0);
  311.         sprintf(basefilename,"%s%d", temp_dir, getpid());
  312.         strcpy(cfilename,basefilename);
  313.         strcpy(dfilename,basefilename);
  314.         strcat(cfilename,".asc");
  315.         strcat(dfilename,".txt");
  316.  
  317.         if ((cryptfile = fopen(cfilename,"wt")) == NULL) {
  318.           if(batch_only)
  319.         printf("Could not create file %s (%s).\n", cfilename, error_name(errno));
  320.           else
  321.         error2("Could not create file %s (%s).", cfilename, error_name(errno));
  322.         }
  323.         else {
  324.  
  325.           chown(cfilename, userid, groupid);
  326.  
  327.           tlines = lines;
  328.           fputs(buffer,cryptfile);
  329.           while( tlines )  {
  330.         if(fgets(buffer, sizeof(buffer), mailfile) == NULL)
  331.           break;
  332.         fixline(buffer);
  333.         fputs(buffer,cryptfile);
  334.         tlines--;
  335.           }
  336.           fclose(cryptfile);
  337.  
  338.           sprintf(buffer, "pgp %s -o %s", cfilename, dfilename);
  339.           puts("\r\n");
  340.           if( !system_call(buffer, SH, FALSE, FALSE) ) {
  341.         fputs("[pgp-encrypt]\n", dest_file);
  342.         if ((cryptfile = fopen(dfilename, "rt")) != NULL)
  343.           while( !feof(cryptfile) ) {
  344.             if( fgets(buffer, sizeof(buffer), cryptfile) != NULL )
  345.               if (strlen(buffer) >= 6 && strncmp(buffer, "[pgp-", 5) == 0
  346.               && strncmp(buffer + strlen(buffer) - 2, "]\n", 2) == 0)
  347.             /* skip */;
  348.               else
  349.             fprintf(dest_file, "%s%s", prefix, buffer);
  350.           }
  351.           }
  352.           else {
  353.         printf("Error while decrypting.  Copying message as-is.\n\r");
  354.         cryptfile = fopen(cfilename, "rt");
  355.         while( !feof(cryptfile) ) {
  356.           if (fgets(buffer, sizeof(buffer), cryptfile) != NULL)
  357.             fprintf(dest_file, "%s%s", prefix, buffer);
  358.         }
  359.           }
  360.           lines = 0;
  361.           fclose(cryptfile);
  362.           if( !access(cfilename,0) )
  363.         if( remove(cfilename) )
  364.           printf("Could not delete file %s (%s).\n\r", cfilename, error_name(errno));
  365.           if( !access(dfilename,0) )
  366.         if( remove(dfilename) )
  367.           printf("Could not delete file %s (%s).\n\r", dfilename, error_name(errno));
  368.         }
  369.       }
  370.       else
  371.         Write_to_screen("No.",0);
  372.  
  373.     } /*  end check for PGP  */
  374.  
  375. #ifndef MMDF
  376.     if(first_word(buffer, "From ") && (real_from(buffer, NULL))) {
  377.       dprint(1, (debugfile,
  378.          "\n*** Internal Problem...Tried to add the following;\n"));
  379.       dprint(1, (debugfile,
  380.          "  '%s'\nto output file (copy_message) ***\n", buffer));
  381.       break;    /* STOP NOW! */
  382.     }
  383. #endif /* MMDF */
  384.  
  385.     if (fprintf(dest_file, "%s%s", prefix, buffer) == EOF) {
  386.       Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
  387.       dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  388.       rm_temps_exit();
  389.     }
  390.       }
  391.     }
  392. #ifndef MMDF
  393.     if (strlen(buffer) + strlen(prefix) > 1)
  394.     if (fprintf(dest_file, "\n") == EOF) {    /* blank line to keep mailx happy *sigh* */
  395.       Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
  396.       dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
  397.       rm_temps_exit();
  398.     }
  399. #endif /* MMDF */
  400. }
  401.  
  402. static struct stat saved_buf;
  403. static char saved_fname[SLEN];
  404.  
  405. int
  406. save_file_stats(fname)
  407. char *fname;
  408. {
  409.     /* if fname exists, save the owner, group, mode and filename.
  410.      * otherwise flag nothing saved. Return 0 if saved, else -1.
  411.      */
  412.  
  413.     if(stat(fname, &saved_buf) != -1) {
  414.       (void)strcpy(saved_fname, fname);
  415.       dprint(2, (debugfile,
  416.         "** saved stats for file owner = %d group = %d mode = %o %s **\n",
  417.         saved_buf.st_uid, saved_buf.st_gid, saved_buf.st_mode, fname));
  418.       return(0);
  419.     }
  420.     dprint(2, (debugfile,
  421.       "** couldn't save stats for file %s [errno=%d] **\n",
  422.       fname, errno));
  423.     return(-1);
  424.  
  425. }
  426.  
  427. restore_file_stats(fname)
  428. char *fname;
  429. {
  430.     /* if fname matches the saved file name, set the owner and group
  431.      * of fname to the saved owner, group and mode,
  432.      * else to the userid and groupid of the user and to 700.
  433.      * Return    -1 if the  either mode or owner/group not set
  434.      *        0 if the default values were used
  435.      *        1 if the saved values were used
  436.      */
  437.  
  438.     int old_umask, i, new_mode, new_owner, new_group, ret_code;
  439.  
  440.  
  441.     new_mode = 0600;
  442.     new_owner = userid;
  443.     new_group = groupid;
  444.     ret_code = 0;
  445.  
  446.     if(strcmp(fname, saved_fname) == 0) {
  447.       new_mode = saved_buf.st_mode;
  448.       new_owner = saved_buf.st_uid;
  449.       new_group = saved_buf.st_gid;
  450.       ret_code = 1;
  451.     }
  452.     dprint(2, (debugfile, "** %s file stats for %s **\n",
  453.       (ret_code ? "restoring" : "setting"), fname));
  454.  
  455.     old_umask = umask(0);
  456.     if((i = chmod(fname, new_mode & 0777)) == -1)
  457.       ret_code = -1;
  458.  
  459.     dprint(2, (debugfile, "** chmod(%s, %.3o) returns %d [errno=%d] **\n",
  460.         fname, new_mode & 0777, i, errno));
  461.  
  462.     (void) umask(old_umask);
  463.  
  464. #ifdef    BSD
  465.     /*
  466.      * Chown is restricted to root on BSD unix
  467.      */
  468.     (void) chown(fname, new_owner, new_group);
  469. #else
  470.     if((i = chown(fname, new_owner, new_group)) == -1)
  471.       ret_code = -1;
  472.  
  473.     dprint(2, (debugfile, "** chown(%s, %d, %d) returns %d [errno=%d] **\n",
  474.            fname, new_owner, new_group, i, errno));
  475. #endif
  476.  
  477.     return(ret_code);
  478.  
  479. }
  480.  
  481. /** and finally, here's something for that evil trick: site hiding **/
  482.  
  483. #ifdef SITE_HIDING
  484.  
  485. int
  486. is_a_hidden_user(specific_username)
  487. char *specific_username;
  488. {
  489.     /** Returns true iff the username is present in the list of
  490.        'hidden users' on the system.
  491.     **/
  492.  
  493.     FILE *hidden_users;
  494.     char  buffer[SLEN];
  495.  
  496.         /*
  497.     this line is deliberately inserted to ensure that you THINK
  498.     about what you're doing, and perhaps even contact the author
  499.     of Elm before you USE this option...
  500.         */
  501.  
  502.     if ((hidden_users = fopen (HIDDEN_SITE_USERS,"r")) == NULL) {
  503.       dprint(1, (debugfile,
  504.           "Couldn't open hidden site file %s [%s]\n",
  505.           HIDDEN_SITE_USERS, error_name(errno)));
  506.       return(FALSE);
  507.     }
  508.  
  509.     while (fscanf(hidden_users, "%s", buffer) != EOF)
  510.       if (strcmp(buffer, specific_username) == 0) {
  511.         dprint(3, (debugfile, "** Found user '%s' in hidden site file!\n",
  512.             specific_username));
  513.         fclose(hidden_users);
  514.         return(TRUE);
  515.       }
  516.  
  517.     fclose(hidden_users);
  518.     dprint(3, (debugfile,
  519.         "** Couldn't find user '%s' in hidden site file!\n",
  520.         specific_username));
  521.  
  522.     return(FALSE);
  523. }
  524.  
  525. #endif
  526.