home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / ONLINE / ELM23-2 / ELM23-2.ZIP / os2 / movemail.c < prev    next >
C/C++ Source or Header  |  1994-08-04  |  10KB  |  381 lines

  1. /* movemail.c  -- Convert all the mail messages in files listed in
  2.  * argv[1] into a single file argv[02] so that the EMACS rmail
  3.  * command can find & process it.
  4.  *
  5.  * Return Code is ...
  6.  *     0 - Everything okay.
  7.  *     1 - Some sort of error, look at stderr for the meaning.
  8.  *
  9.  *  Stuart Wilson
  10.  *  stuartw@pec.co.nz
  11.  *  July 1992.
  12.  *
  13.  * Copyright (C) 1992, 1993  Stuart Wilson.
  14.  *
  15.  * movemail.c is free software; you can redistribute it and/or modify
  16.  * it under the terms of the GNU General Public License as published by
  17.  * the Free Software Foundation; either version 1, or (at your option)
  18.  * any later version.
  19.  *
  20.  * movemail.c is distributed in the hope that it will be useful,
  21.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23.  * GNU General Public License for more details.
  24.  *
  25.  * You should have received a copy of the GNU General Public License
  26.  * along with GNU Emacs; see the file COPYING.  If not, write to
  27.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  28.  *
  29.  *
  30.  *
  31.  * Fixes & Adulterations:
  32.  * ~~~~~~~~~~~~~~~~~~~~~~
  33.  *
  34.  *  Make it change dir to the mail spool directory on the correct disk.
  35.  *
  36.  *  Paul Andrew
  37.  *  paula@pec.co.nz
  38.  *  October 1992.
  39.  *
  40.  *
  41.  *  Tidied up the way it decides what directory to change to. Now it
  42.  *  looks at argv[1] to decide, rather than use a constant.
  43.  *
  44.  *  Problems parsing the index file. Sometimes there is a from person
  45.  *  and from machine.
  46.  *
  47.  *  Write the resulting mail file better, so that Emacs rmail code can
  48.  *  actually find the mail messages. The result file is written in the
  49.  *  babyl format that Emacs uses as it's internal format.
  50.  *
  51.  *  Stuart Wilson
  52.  *  stuartw@pec.co.nz
  53.  *  April 1993.
  54.  */
  55.  
  56. /* Modified by Eberhard Mattes, Jun 1994
  57.  * - Fix infinite loop in parser
  58.  * - Fix return codes
  59.  * - Open the index file in SH_DENYRW mode
  60.  */
  61.  
  62. /* changed for use in elm by Kai Uwe Rommel, rommel@ars.muc.de, Sept. 1993 */
  63.  
  64. #include <stdio.h>
  65. #include <ctype.h>
  66. #include <share.h>
  67.  
  68. #ifndef EMACS
  69. #include "sysdefs.h"
  70. #endif
  71.  
  72. /* A few states for the Index file parsing state machine */
  73. #define SKIP_SPACE_1         0
  74. #define SKIP_FROM_USER       1
  75. #define SKIP_SPACE_2         2
  76. #define SKIP_FROM_MACHINE    3
  77. #define SKIP_SPACE_3         4
  78. #define GET_NOTE_NAME        5
  79. #define SKIP_SPACE_4         6
  80. #define GET_NOTE_EXTN        7
  81. #define DONE_NOTE            8
  82. #define NO_FILE              9
  83.  
  84. FILE *resultf;
  85.  
  86. #ifdef TEST
  87. main (argc, argv)
  88. int argc;
  89. char *argv[];
  90. {
  91.     /* Check the number of command line arguments */
  92.     if(argc != 3) {
  93.        fprintf(stderr, "movemail: incorrect usage\n");
  94.          exit(0);
  95.      }
  96.  
  97.     return(movemail(argv[1], argv[2]));
  98. }
  99. #endif
  100.  
  101. movemail(inbox, mailbox)
  102. char *inbox, *mailbox;
  103. {
  104.     char filename[256], indexline[1024];
  105.     FILE *indexf, *notef;
  106.     int index_state;
  107.     char *p, *q, *notename;
  108.  
  109.     /* Go grovelling backwards through the name of the index file, to get
  110.      * the name of the incomming mail spool directory.  We need to change
  111.      * to it.
  112.      */
  113.     strcpy(filename, inbox);
  114.  
  115.     for(p = &filename[strlen(filename)-1] ;
  116.         p != filename && *p != '/' && *p != '\\' ;
  117.         p--);
  118.  
  119.     if(p == filename) {
  120.      fprintf(stderr, "Can't find directory in \"%s\"\n", inbox);
  121.       return(1);
  122.     }
  123.  
  124.     notename = p + 1;
  125.  
  126.     /* Open the index file for reading */
  127.     indexf=_fsopen(inbox, "r", SH_DENYRW);
  128.     if (indexf == NULL) {
  129.       return(1);
  130.     }
  131.  
  132.     /* Open the result file for appending */
  133.     resultf=fopen(mailbox, "a");
  134.     if (resultf == NULL) {
  135.       fprintf(stderr, "Can't open mailbox file \"%s\"\n", mailbox);
  136.       return(1);
  137.     }
  138.  
  139.     /* Read in the index file a line at a time, find the name of the note,
  140.      * and process it
  141.      */
  142.     while (fgets(indexline, sizeof(indexline), indexf) != NULL) {
  143.  
  144.       /* First attempt at finding the note file name, assume that there is
  145.        * a user and machine name in the index entry. we'll have to skip past
  146.        * them.
  147.        */
  148.       p=indexline;
  149.       index_state = SKIP_SPACE_1;
  150.       while((index_state != DONE_NOTE) &&
  151.             (index_state != NO_FILE)) {
  152.         switch(index_state) {
  153.         case SKIP_SPACE_1:
  154.           if (! isspace(*p++))
  155.             index_state = SKIP_FROM_USER;
  156.           break;
  157.  
  158.         case SKIP_FROM_USER:
  159.           if (isspace(*p++))
  160.             index_state = SKIP_SPACE_2;
  161.           break;
  162.  
  163.         case SKIP_SPACE_2:
  164.           if (! isspace(*p++))
  165.             index_state = SKIP_FROM_MACHINE;
  166.           break;
  167.  
  168.         case SKIP_FROM_MACHINE:
  169.           if (isspace(*p++))
  170.             index_state = SKIP_SPACE_3;
  171.           break;
  172.  
  173.         case SKIP_SPACE_3:
  174.           if (! isspace(*p)) {
  175.             index_state = GET_NOTE_NAME;
  176.             q = notename;
  177.             *q++ = *p++;
  178.           }
  179.           else p++;
  180.           break;
  181.  
  182.         case GET_NOTE_NAME:
  183.           if (! isspace(*p)) {
  184.             *q++ = *p++;
  185.           }
  186.           else {
  187.             *q++ = '.';
  188.             index_state = SKIP_SPACE_4;
  189.             p++;
  190.           }
  191.           break;
  192.  
  193.         case SKIP_SPACE_4:
  194.           if (! isspace(*p)) {
  195.             index_state = GET_NOTE_EXTN;
  196.             *q++ = *p++;
  197.           }
  198.           else p++;         /* This line has been added by Eberhard Mattes */
  199.           break;
  200.  
  201.         case GET_NOTE_EXTN:
  202.           if(! isspace(*p)) {
  203.             *q++ = *p++;
  204.           }
  205.           else {
  206.             /* We've got all the name of the next, note...
  207.              * terminate the string, and process the note.
  208.              */
  209.             *q = '\0';
  210.  
  211.             notef=fopen(filename, "r");
  212.             if(notef != NULL) {
  213.               process_note(notef);
  214.               fclose(notef);
  215.               unlink(filename);
  216.               index_state = DONE_NOTE;
  217.             }
  218.             else index_state = NO_FILE;
  219.           }
  220.           break;
  221.         }
  222.       }
  223.       if(index_state == DONE_NOTE)
  224.         continue;
  225.  
  226.       /* Second attempt at finding the file name. Assume there is no user
  227.        * or machine name before the note name in the index entry.
  228.        */
  229.       p=indexline;
  230.       index_state = SKIP_SPACE_3;
  231.       while((index_state != DONE_NOTE) &&
  232.             (index_state != NO_FILE)) {
  233.         switch(index_state) {
  234.         case SKIP_SPACE_3:
  235.           if (! isspace(*p)) {
  236.             index_state = GET_NOTE_NAME;
  237.             q = notename;
  238.             *q++ = *p++;
  239.           }
  240.           else p++;
  241.           break;
  242.  
  243.         case GET_NOTE_NAME:
  244.           if (! isspace(*p)) {
  245.             *q++ = *p++;
  246.           }
  247.           else {
  248.             *q++ = '.';
  249.             index_state = SKIP_SPACE_4;
  250.             p++;
  251.           }
  252.           break;
  253.  
  254.         case SKIP_SPACE_4:
  255.           if (! isspace(*p)) {
  256.             index_state = GET_NOTE_EXTN;
  257.             *q++ = *p++;
  258.           }
  259.           else p++;         /* This line has been added by Kai Uwe Rommel */
  260.           break;
  261.  
  262.         case GET_NOTE_EXTN:
  263.           if(! isspace(*p)) {
  264.             *q++ = *p++;
  265.           }
  266.           else {
  267.             /* We've got all the name of the next, note...
  268.              * terminate the string, and process the note.
  269.              */
  270.             *q = '\0';
  271.             notef=fopen(filename, "r");
  272.             if(notef != NULL) {
  273.               process_note(notef);
  274.               fclose(notef);
  275.               unlink(filename);
  276.               index_state = DONE_NOTE;
  277.             }
  278.             else index_state = NO_FILE;
  279.           }
  280.           break;
  281.         }
  282.       }
  283.       if(index_state == DONE_NOTE)
  284.         continue;
  285.  
  286.       /* Any other attempts ?? */
  287.       }
  288.  
  289.     /* Now remove the index file */
  290.     fclose(indexf);
  291.     /* Here's a timing window! */
  292.     unlink(inbox);
  293.  
  294.     /* everything is Okay */
  295.     fclose(resultf);
  296.     return(0);
  297. }
  298.  
  299.  
  300. /* Return true if the line in the buffer starts with "From "
  301.  */
  302. int fromline(buff)
  303. char *buff;
  304. {
  305.   return(((buff[0]=='F') &&
  306.       (buff[1]=='r') &&
  307.       (buff[2]=='o') &&
  308.       (buff[3]=='m') &&
  309.       (buff[4]==' ')) ? 1 : 0) ;
  310. }
  311.  
  312.  
  313. /* Return true if the line in the buffer has the following regexp
  314.  *              ^[A-Z][a-z-]*:
  315.  */
  316.  
  317. int header_line(buff)
  318. char *buff;
  319. {
  320.   char *p;
  321.  
  322.   p=buff;
  323.   if(! isupper(*p))
  324.     return(0);
  325.   p++;
  326.  
  327.   /* skip to the next character non lower-case and non '-' */
  328.   while((islower(*p) || (*p == '-')))
  329.     p++;
  330.  
  331.   /* It's a header line of some sort */
  332.   if(*p == ':')
  333.     return(1);
  334.  
  335.   /* failed */
  336.   return(0);
  337. }
  338.  
  339.  
  340. /* Copy the contents of the note with name NOTE into the result file...
  341.  * a few little items to think about....
  342.  *
  343.  * We'll unconfuse the Emacs rmail code by chucking out the "From " line
  344.  * from the headers as well as any MMDF delimiters.
  345.  *
  346.  * Things will be alot easier if we write the result file in babyl format,
  347.  * which is the format Emacs uses.
  348.  */
  349. process_note(notef)
  350. FILE *notef;
  351. {
  352.     char buff[1024], *p;
  353. #ifndef EMACS
  354.     fputs(MSG_SEPERATOR, resultf);
  355.     while(fgets(buff, sizeof(buff), notef) != NULL)
  356.       fputs(buff, resultf);
  357. #else
  358.     int doing_headers;
  359.  
  360.     doing_headers = 1;
  361.     fputs("\014\n0, unseen,,\n*** EOOH ***\n", resultf);
  362.  
  363.     while(fgets(buff, sizeof(buff), notef) != NULL) {
  364.       /* chuck out any "From  blh@blhablah" lines */
  365.       if(doing_headers && fromline(buff)) {
  366.         continue;
  367.       }
  368.       if(strlen(buff) == 1)
  369.         doing_headers=0;
  370.  
  371.       /* Flatten any \001 characters remaining from mmdf */
  372.       for(p=buff; *p; p++)
  373.       *p = (*p == '\001') ? ' ' : *p ;
  374.  
  375.       fputs(buff, resultf);
  376.     }
  377.  
  378.     fputs("\037", resultf);
  379. #endif
  380. }
  381.