home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / ONLINE / MR2IUUCP / UNMBOX.C < prev    next >
C/C++ Source or Header  |  1997-01-05  |  13KB  |  442 lines

  1. /* unmbox.c
  2.  * Program to take a uupc inbox and translate it into separate mail messages
  3.  * ready for processing by MR/2 ICE.
  4.  *
  5.  * Michael Taylor miket@pcug.org.au
  6.  *
  7.  * History:
  8.  * 1.0.00    Initial version.        12/10/1996
  9.  * 1.0.01    Fixes.                  19/10/1996
  10.  *              Fix parsing of UUPC variables
  11.  *              Add fromsep logic - NO fromsep should be defined!
  12.  *              Inprove get_next_fname so it does not
  13.  *              return a filename that already exists.
  14.  *              Rename UUPC mbox so it cannot be written
  15.  *              to by uuxqt/rmail.
  16.  * 1.0.02    Fixes.                  26/12/1996
  17.  *              Use tmpnam rather than tempnam and remove
  18.  *              dependence on envvar TMP being unset.
  19.  *              Do not delete renamed mailbox if no mail.
  20.  * 1.0.03    Fixes.                  01/01/1997
  21.  *              Fix UNMB_MAIL - was broken :-(
  22.  *              Fix bug with writing out to getmail.err - added
  23.  *              new command line parameter for MR/2 username.
  24.  * 1.0.04    Cleanup.                04/01/1997
  25.  *              Remove all global variables.
  26.  *              Fix bug in parsing UUPC definition files - noone found this :-)
  27.  *              Works with nofromsep or fromsep format mailboxes.
  28.  *
  29.  *
  30.  * This program is freely redistributable.
  31.  *
  32.  * Please maintain the current coding style if you want me to
  33.  * incorporate any changes.
  34. */
  35.  
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39.  
  40. static char version[] =
  41. "unmbox by Michael Taylor (miket@pcug.org.au) - Version 1.0.04";
  42.  
  43. static char * get_next_fname (char *basename, char *username);
  44. static int get_uupc_vars (char *username, char * mailbox_name, char * old_mailbox);
  45. static void err (char * str, char * username);
  46. static int parse_nofromsep (FILE *infile, char *xbuf, char *basename,
  47.                  char *username);
  48. static int parse_fromsep (FILE *infile, char *xbuf, char *basename,
  49.                char *username);
  50.  
  51. static char *
  52. get_next_fname (char *basename, char *username) {
  53.         char *  name1;
  54.     char    tname[L_tmpnam];
  55.         static char nxtfname[256];
  56.     FILE *    tmp;
  57.     int     x = 0, y = 1;
  58.  
  59. #define MAXTRIES        25000
  60.  
  61.     while (y && x < MAXTRIES) {
  62.                 if ((name1 = tmpnam (tname)) == NULL) {
  63.                         err ("Cannot create unique filename\n", username);
  64.                         return NULL;
  65.                 }
  66.                 strcpy (nxtfname, basename);
  67.             strcat (nxtfname, "\\");
  68.             strcat (nxtfname, tname+2);
  69. /*printf ("try: %s\n", nxtfname);*/
  70.             if ((tmp = fopen (nxtfname, "r")) != NULL) {
  71.             fclose (tmp);
  72.             ++x;
  73.             continue;
  74.         }
  75.         y = 0;
  76.         
  77.         }
  78.         if (!y) {
  79. /*printf ("use: %s\n", nxtfname);*/
  80.             return (char *)nxtfname;
  81.     } else
  82.         return NULL;
  83.  
  84. }
  85.  
  86. /*
  87.  get_uupc_vars
  88.  
  89.  Checks for the UUPC control files to locate the mail box.
  90.  The environment var UNMB_MAIL can be used to specify the mailbox.
  91. */
  92. static int
  93. get_uupc_vars (char * username, char * mailbox_name, char * old_mailbox) {
  94.     char buf[256];
  95.     int  i, cf;
  96.     char *p, *q, *fn;
  97.         char mailext[256];
  98.         static char mailbox[256];
  99.  
  100.     FILE *tmp;
  101.  
  102.     p = getenv ("UNMB_MAIL");
  103.     if (p != NULL) {
  104.             strcpy (old_mailbox, p);
  105.                 strcpy (mailbox_name, p);
  106.         for (q = (p = mailbox_name) + strlen (mailbox_name); p < q; ++p) {
  107.             if (*p == '.')
  108.                 break;
  109.                 }
  110.                 if (*p == '.')
  111.             p[1] = '\0';
  112.         else {
  113.             p[0] = '.';
  114.             p[1] = '\0';
  115.         }
  116.  
  117.             strcat (mailbox_name, "tmp");
  118.         return (1);
  119.     }
  120.  
  121.     /*--------------------- load UUPC rc files ---------------------------*/
  122.     /* read the system file first */
  123.     for (cf = 0, i = 0; i < 2; i++) {
  124.         /* choose the file to open */
  125.         if (i == 0) {
  126.         fn = getenv ("UUPCSYSRC");
  127.         if (fn == NULL) {
  128.             err ("Enviroment variable UUPCSYSRC not defined\n", username);
  129.                 exit (EXIT_FAILURE);
  130.         }
  131.         } else {
  132.         fn = getenv ("UUPCUSRRC");
  133.         if (fn == NULL) {
  134.             err ("Enviroment variable UUPCUSRRC not defined\n", username);
  135.                 exit (EXIT_FAILURE);
  136.         }
  137.         }
  138.         if ((tmp = fopen (fn, "r")) != NULL) {
  139.             while (fgets (buf, 255, tmp)) {
  140.             p = buf + strlen (buf) - 1;
  141.             if (*p == '\n')
  142.                 *p = '\0';
  143.             if (p > buf)
  144.                 if (*(p-1) == '\n')
  145.                     *(p-1) = '\0';
  146.  
  147.             if (!cf && strnicmp (buf, "confdir=", 8) == 0) {
  148.             /* default root dir if mailbox var not found */
  149.                 cf = 1;
  150.                 strcpy (mailbox_name, buf+8);
  151.                                 strcat (mailbox_name, "\\mail"); /* 1.0.01 */
  152.             } else
  153.             if (strnicmp (buf, "mailbox=", 8) == 0) {
  154.             /* mailbox base name */
  155.                 strcpy (mailbox, buf+8);
  156.             } else
  157.             if (strnicmp (buf, "maildir=", 8) == 0) {
  158.             /* file name for mailbox */
  159.                 cf = 1;
  160.                 strcpy (mailbox_name, buf+8);
  161.             } else
  162.             if (strnicmp (buf, "mailext=", 8) == 0) {
  163.             /* extension of file name for mailbox */
  164.                 strcpy (mailext, buf+8);
  165.             }
  166.             }
  167.             fclose (tmp);
  168.  
  169.         } else {
  170.         fprintf (stderr, "Cannot open %s\n", fn);
  171.         }
  172.     }
  173.  
  174.     if (!cf) {
  175.         return (0);
  176.     }
  177.  
  178.     strcat (mailbox_name, "\\");
  179.     strcat (mailbox_name, mailbox);
  180.     strcat (mailbox_name, ".");
  181.         strcpy (old_mailbox, mailbox_name);
  182.     strcat (old_mailbox, mailext);
  183.     strcat (mailbox_name, "tmp");
  184.     
  185.     return (1);
  186. }
  187.  
  188. static void
  189. err (char * str, char * username) {
  190.     FILE  * errfile;
  191.     char    errfname[256];
  192.  
  193.     strcpy (errfname, username);
  194.     strcat (errfname, "\\getmail.err");
  195.  
  196.         if ((errfile = fopen (errfname, "w")) == NULL) {
  197.             fprintf (stderr, "unmbox: error - cannot open file for error message\n");
  198.         exit (EXIT_FAILURE);
  199.            }
  200.         fprintf (errfile, "%s", str);
  201.         fclose (errfile);
  202. }
  203.  
  204. #define XBUFSIZE        20480
  205. static char x01x20[20] =
  206.     "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01";
  207.  
  208. /*
  209.  parse_nofromsep
  210.  
  211.  parse the mailbox using the 20 x01s as the delimeter between mail items
  212. */
  213. static int
  214. parse_nofromsep (FILE *infile, char *xbuf, char *basename, char *username) {
  215.     FILE *    mfile=0;
  216.     int     nlines, reterr = 0;
  217.  
  218.     fgets (xbuf, XBUFSIZE, infile);
  219.     while (!feof (infile)) {
  220. /*        if (0 == memcmp (xbuf, x01x20, 20))
  221.             goto nextline;*/
  222.         if ((mfile = fopen (get_next_fname (basename, username), "w")) == NULL) {
  223. /* this error most likely occurs if the SMTP directory doesn't exist     */
  224.                     reterr = 1;
  225.             break;
  226.         }
  227.                 fputs (xbuf, mfile); nlines = 1;
  228.         while (fgets (xbuf, XBUFSIZE, infile)) {
  229.             if (0 == memcmp (xbuf, x01x20, 20))
  230.                 break;
  231.                        fputs (xbuf, mfile); nlines++;
  232.         }
  233.  
  234.             if (mfile) { fclose (mfile); mfile = 0;}
  235. /*nextline:*/
  236.         fgets (xbuf, XBUFSIZE, infile);
  237.     }
  238.  
  239.     if (mfile) { fclose (mfile); mfile = 0;}
  240.     return reterr;
  241. }
  242.  
  243. /* new_mail
  244.  *
  245.  * The logic here is that the From line will have the same format.
  246.  * From userid ...
  247.  * To make sure it is a valid From line we identify the format of the
  248.  * first From line and make sure all preceding From lines are the same
  249.  * format - it would be unlikely for a line starting with From to have
  250.  * Numerics and Non-numerics in the same places!
  251.  */
  252. static int
  253. new_mail (char * xbuf, int setup) {
  254.     char *  p;
  255.     static int nparts = 0;
  256.     static char stype[20];
  257.     char ptype[20];
  258.     int     n;
  259. /*
  260.  Example From lines
  261.  Current UUPC From format
  262.  From teamos2.org!owner-teamos2-l Sat Jan  4 18:33:31 1997 remote from miket
  263.  
  264.  This is from UUPC rmail:
  265.  From fkk Sat, 14 Mar 1992 14:53:27 MET remote from stasys
  266.                                                                                 
  267.  while this is another:
  268.  From fkk Sat Mar 14 14:53:27 1992 [MET]
  269. */
  270.            if (memcmp (xbuf, "From ", 5))
  271.             return 0;
  272.  
  273.     for (n = 0; n < 20; ++n)
  274.         ptype[n] = 0;
  275.     for (p = xbuf, n = 0; *p != '\0'; ++p) {
  276.         if (*p == ' ')
  277.             ++n;
  278.         else /* set the type of the part */
  279.             if (n < 20 && !ptype[n] && *p > '0' && *p < '9')
  280.                 ptype[n] = 1; /* Numeric */
  281.             else
  282.                 ptype[n] = 2; /* Non-Numeric */
  283.                 
  284.     }
  285. /* the first two parts are always a From and a userid
  286.  * are numeric userids possible?
  287.  */
  288.     
  289.     ptype[0] = 3;   /* From identifier      */
  290.     ptype[1] = 4;   /* userid               */
  291.  
  292.     if (setup) {
  293.         nparts = n;
  294.         memcpy (stype, ptype, 20);
  295. /*printf ("nparts=%d\n", nparts);*/
  296.         return 1;
  297.     }
  298.  
  299.     /* if the format matches the remembered format then we have a match */
  300.     if (nparts == n && 0 == memcmp (stype, ptype, 20))
  301.         return 1;
  302.  
  303.         return 0;
  304. }
  305.  
  306. /*
  307.  parse_fromsep
  308.  
  309.  parse the mailbox using the FROM+header as the delimeter between mail items
  310. */
  311. static int
  312. parse_fromsep (FILE *infile, char *xbuf, char *basename, char *username) {
  313.     FILE *    mfile=0;
  314.     int     nlines, reterr=0;
  315.  
  316.     /* initialise new_mail test with From line format */
  317.     if (!new_mail (xbuf, 1)) {
  318.             reterr = 2;
  319.         return reterr;
  320.     }
  321.             
  322.     while (!feof (infile)) {
  323.         if ((mfile = fopen (get_next_fname (basename, username), "w")) == NULL) {
  324. /* this error most likely occurs if the SMTP directory doesn't exist     */
  325.                     reterr = 1;
  326.             break;
  327.         }
  328.                 fputs (xbuf, mfile); nlines = 1;
  329.         while (fgets (xbuf, XBUFSIZE, infile)) {
  330.             if (new_mail (xbuf, 0))
  331.                 break;
  332.                        fputs (xbuf, mfile); nlines++;
  333.         }
  334.  
  335.             if (mfile) { fclose (mfile); mfile = 0;}
  336.     }
  337.  
  338.     if (mfile) { fclose (mfile); mfile = 0;}
  339.     return reterr;
  340. }
  341.  
  342. int
  343. main (int argc, char * argv[]) {
  344.     FILE *    infile=0;
  345.     int    isfromsep=1, errs=0;
  346.         char username[256], basename[256], omailbox[256], maildir[256];
  347.         char * mailbox_name = maildir, * old_mailbox = omailbox;
  348.         char * xbuf = NULL;
  349.  
  350.     strcpy (username, "mail"); /* default value for username */
  351.         if (argc < 2) {
  352.         printf ("%s\n", version);
  353.         printf ("usage: unmbox <SMTP directory> [username]\n");
  354.         err ("usage: unmbox <SMTP directory> [username]\n", username);
  355.         exit (EXIT_FAILURE);
  356.     }
  357.  
  358.         strcpy (basename, argv[1]);
  359.         
  360.         if (argc > 2)
  361.                 strcpy (username, argv[2]);
  362.     
  363.         if (!get_uupc_vars (username, mailbox_name, old_mailbox)) {
  364.         err ("error - cannot find UUPC mail box\n", username);
  365.         exit (EXIT_FAILURE);
  366.     }
  367.  
  368.     /* test if any mail - so <mailbox>.tmp is not deleted! */
  369.     if ((infile = fopen (old_mailbox, "r")) == NULL) {
  370. /*        err ("error - cannot open UUPC mailbox\n", username);*/
  371.         exit (EXIT_FAILURE);
  372.     }
  373.     fclose (infile);
  374.  
  375.         remove (mailbox_name);
  376.     if (rename (old_mailbox, mailbox_name)) {
  377. /*        err ("error - cannot access UUPC mailbox - try again later\n", username);*/
  378.         exit (EXIT_FAILURE);
  379.     }
  380.     if ((infile = fopen (mailbox_name, "r")) == NULL) {
  381. /*        err ("error - cannot open UUPC mailbox\n", username);*/
  382.         exit (EXIT_FAILURE);
  383.     }
  384.  
  385.         xbuf = (char *)malloc (XBUFSIZE+1);
  386.         if (xbuf == NULL) {
  387.                 err("error - Cannot allocate temporary buffer\n", username);
  388.             exit (EXIT_FAILURE);
  389.     }
  390.  
  391. /* first check if file is nofromsep or fromsep format */
  392.     fgets (xbuf, XBUFSIZE, infile);
  393.     if (feof (infile)) {
  394.             fclose (infile);
  395. /* just to be nice - rename mailbox so that the user can try again later */
  396.                 rename (mailbox_name, old_mailbox);
  397.                   if (xbuf) {free (xbuf); xbuf = NULL;}
  398.         exit (EXIT_FAILURE);
  399.         }
  400. /* if the first line is 20 0x01s then this is a UUPC-style (nofromsep)
  401.  * delimeted mailbox.
  402. */
  403.     while (1) {
  404.             if (0 == memcmp (xbuf, x01x20, 20)) {
  405.                 isfromsep = 0;
  406.             break;
  407.         }
  408.                    if (0 == memcmp (xbuf, "From ", 5))
  409.             break;
  410.             fgets (xbuf, XBUFSIZE, infile);
  411.             if (feof (infile)) {
  412.                     fclose (infile);
  413. /* just to be nice - rename mailbox so that the user can try again later */
  414.                         rename (mailbox_name, old_mailbox);
  415.                           if (xbuf) {free (xbuf); xbuf = NULL;}
  416.                 err ("error - no From or nofromsep line in mailbox\n", username);
  417.                 exit (EXIT_FAILURE);
  418.                 }
  419.         }
  420.         
  421.     
  422.     if (isfromsep)
  423.         errs = parse_fromsep (infile, xbuf, basename, username);
  424.     else
  425.         errs = parse_nofromsep (infile, xbuf, basename, username);
  426.     if (errs) {
  427.         if (1 == errs)
  428.                 err ("error - cannot open new file for mail\n", username);
  429.         else if (2 == errs)
  430.                 err ("error - no From line at start of mailbox\n", username);
  431.         else
  432.                 err ("error - parse error reading mailbox\n", username);
  433. /* just to be nice - rename mailbox so that the user can try again later */
  434.                 rename (mailbox_name, old_mailbox);
  435.         }
  436.  
  437.     fclose (infile);
  438.     if (xbuf) {free (xbuf); xbuf = NULL;}
  439.     
  440.     exit (EXIT_SUCCESS);
  441.     return (EXIT_SUCCESS); /* gets rid of dumb compiler warning */
  442. }