home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / emacmail.zip / movemail.c next >
Text File  |  1993-08-07  |  10KB  |  374 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 - Some sort of error, look at stderr for the meaning.
  7.  *   255 - Everything okay.
  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. #include <stdio.h>
  57. #include <ctype.h>
  58.  
  59. #define INCL_NOPMAPI
  60. #include <os2.h> /* pja92oct13 */
  61.  
  62. /* A few states for the Index file parsing state machine */
  63. #define SKIP_SPACE_1         0
  64. #define SKIP_FROM_USER       1
  65. #define SKIP_SPACE_2         2
  66. #define SKIP_FROM_MACHINE    3
  67. #define SKIP_SPACE_3         4
  68. #define GET_NOTE_NAME        5
  69. #define SKIP_SPACE_4         6
  70. #define GET_NOTE_EXTN        7
  71. #define DONE_NOTE            8
  72. #define NO_FILE              9
  73.  
  74. FILE *resultf;
  75.  
  76. main (argc, argv)
  77. int argc;
  78. char *argv[];
  79. {
  80.  
  81.     char notename[64], indexline[1024];
  82.     FILE *indexf, *notef;
  83.     int index_state;
  84.     char *p, *q;
  85.     ULONG disk ;
  86.  
  87.     /* Check the number of command line arguments */
  88.     if(argc != 3) {
  89.        fprintf(stderr, "movemail:This program should only be called by the emacs rmail command\n");
  90.          exit(0);
  91.      }
  92.  
  93.     /* change to the appropriate drive before doing a change dir */
  94.     disk = ((char)((char *)argv[1])[0]) - 'a' ;
  95.     DosSetDefaultDisk (disk+1) ;
  96.  
  97.     /* Go grovelling backwards through the name of the index file, to get
  98.      * the name of the incomming mail spool directory.  We need to change
  99.      * to it.
  100.      */
  101.     for(p = &argv[1][strlen(argv[1])-1] ;
  102.         p != argv[1] && *p != '/' && *p != '\\' ;
  103.         p--);
  104.  
  105.     if(p == argv[1]) {
  106.      fprintf(stderr, "Can't find directory in \"%s\"\n", argv[1]);
  107.       exit(0);
  108.     }
  109.  
  110.  
  111.     /* Terminate argv[1] at the end of the directory, change
  112.      * to that directory and put the final directory delimiter back so
  113.      * we can open the index file
  114.      */
  115.     *p='\000';
  116.     if (chdir(argv[1]) == -1) {
  117.       fprintf(stderr, "Can't change to mail directory \"%s\"\n", argv[1]);
  118.       exit(0);
  119.     }
  120.     *p = '\\';
  121.  
  122.  
  123.  
  124.     /* Open the result file for writing */
  125.     resultf=fopen(argv[2], "w");
  126.     if (resultf == NULL) {
  127.       fprintf(stderr, "Can't open EMACS infile file \"%s\"\n", argv[2]);
  128.       exit(0);
  129.     }
  130.  
  131.  
  132.     /* Open the index file for reading */
  133.     indexf=fopen(argv[1], "r");
  134.     if (indexf == NULL) {
  135.         exit(0);
  136.     }
  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.           break;
  199.  
  200.         case GET_NOTE_EXTN:
  201.           if(! isspace(*p)) {
  202.             *q++ = *p++;
  203.           }
  204.           else {
  205.             /* We've got all the name of the next, note...
  206.              * terminate the string, and process the note.
  207.              */
  208.             *q = '\0';
  209.  
  210.             notef=fopen(notename, "r");
  211.             if(notef != NULL) {
  212.               process_note(notef);
  213.               fclose(notef);
  214.               unlink(notename);
  215.               index_state = DONE_NOTE;
  216.             }
  217.             else index_state = NO_FILE;
  218.           }
  219.           break;
  220.         }
  221.       }
  222.       if(index_state == DONE_NOTE)
  223.         continue;
  224.  
  225.       /* Second attempt at finding the file name. Assume there is no user
  226.        * or machine name before the note name in the index entry.
  227.        */
  228.       p=indexline;
  229.       index_state = SKIP_SPACE_3;
  230.       while((index_state != DONE_NOTE) &&
  231.             (index_state != NO_FILE)) {
  232.         switch(index_state) {
  233.         case SKIP_SPACE_3:
  234.           if (! isspace(*p)) {
  235.             index_state = GET_NOTE_NAME;
  236.             q = notename;
  237.             *q++ = *p++;
  238.           }
  239.           else p++;
  240.           break;
  241.  
  242.         case GET_NOTE_NAME:
  243.           if (! isspace(*p)) {
  244.             *q++ = *p++;
  245.           }
  246.           else {
  247.             *q++ = '.';
  248.             index_state = SKIP_SPACE_4;
  249.             p++;
  250.           }
  251.           break;
  252.  
  253.         case SKIP_SPACE_4:
  254.           if (! isspace(*p)) {
  255.             index_state = GET_NOTE_EXTN;
  256.             *q++ = *p++;
  257.           }
  258.           break;
  259.  
  260.         case GET_NOTE_EXTN:
  261.           if(! isspace(*p)) {
  262.             *q++ = *p++;
  263.           }
  264.           else {
  265.             /* We've got all the name of the next, note...
  266.              * terminate the string, and process the note.
  267.              */
  268.             *q = '\0';
  269.             notef=fopen(notename, "r");
  270.             if(notef != NULL) {
  271.               process_note(notef);
  272.               fclose(notef);
  273.               unlink(notename);
  274.               index_state = DONE_NOTE;
  275.             }
  276.             else index_state = NO_FILE;
  277.           }
  278.           break;
  279.         }
  280.       }
  281.       if(index_state == DONE_NOTE)
  282.         continue;
  283.  
  284.       /* Any other attempts ?? */
  285.       }
  286.  
  287.     /* Now remove the index file */
  288.     fclose(indexf);
  289.     unlink(argv[1]);
  290.  
  291.     /* everything is Okay */
  292.     exit(255);
  293.   }
  294.  
  295.  
  296. /* Return true if the line in the buffer starts with "From "
  297.  */
  298. int fromline(buff)
  299. char *buff;
  300. {
  301.   return(((buff[0]=='F') &&
  302.       (buff[1]=='r') &&
  303.       (buff[2]=='o') &&
  304.       (buff[3]=='m') &&
  305.       (buff[4]==' ')) ? 1 : 0) ;
  306. }
  307.  
  308.  
  309. /* Return true if the line in the buffer has the following regexp
  310.  *              ^[A-Z][a-z-]*:
  311.  */
  312.  
  313. int header_line(buff)
  314. char *buff;
  315. {
  316.   char *p;
  317.  
  318.   p=buff;
  319.   if(! isupper(*p))
  320.     return(0);
  321.   p++;
  322.  
  323.   /* skip to the next character non lower-case and non '-' */
  324.   while((islower(*p) || (*p == '-')))
  325.     p++;
  326.  
  327.   /* It's a header line of some sort */
  328.   if(*p == ':')
  329.     return(1);
  330.  
  331.   /* failed */
  332.   return(0);
  333. }
  334.  
  335.  
  336. /* Copy the contents of the note with name NOTE into the result file...
  337.  * a few little items to think about....
  338.  *
  339.  * We'll unconfuse the Emacs rmail code by chucking out the "From " line
  340.  * from the headers as well as any MMDF delimiters.
  341.  *
  342.  * Things will be alot easier if we write the result file in babyl format,
  343.  * which is the format Emacs uses.
  344.  */
  345. process_note(notef)
  346. FILE *notef;
  347. {
  348.     char buff[1024], *p;
  349.     int doing_headers;
  350.  
  351.     doing_headers = 1;
  352.     fputs("\014\n0, unseen,,\n*** EOOH ***\n", resultf);
  353.  
  354.     while(fgets(buff, sizeof(buff), notef) != NULL) {
  355.       /* chuck out any "From  blh@blhablah" lines */
  356.       if(doing_headers && fromline(buff)) {
  357.         continue;
  358.       }
  359.       if(strlen(buff) == 1)
  360.         doing_headers=0;
  361.  
  362.       /* Flatten any \001 characters remaining from mmdf */
  363.       for(p=buff; *p; p++)
  364.       *p = (*p == '\001') ? ' ' : *p ;
  365.  
  366.       fputs(buff, resultf);
  367.     }
  368.  
  369.     fputs("\037", resultf);
  370.   }
  371.  
  372.  
  373.  
  374.