home *** CD-ROM | disk | FTP | other *** search
- /* unmbox.c
- * Program to take a uupc inbox and translate it into separate mail messages
- * ready for processing by MR/2 ICE.
- *
- * Michael Taylor miket@pcug.org.au
- *
- * History:
- * 1.0.00 Initial version. 12/10/1996
- * 1.0.01 Fixes. 19/10/1996
- * Fix parsing of UUPC variables
- * Add fromsep logic - NO fromsep should be defined!
- * Inprove get_next_fname so it does not
- * return a filename that already exists.
- * Rename UUPC mbox so it cannot be written
- * to by uuxqt/rmail.
- * 1.0.02 Fixes. 26/12/1996
- * Use tmpnam rather than tempnam and remove
- * dependence on envvar TMP being unset.
- * Do not delete renamed mailbox if no mail.
- * 1.0.03 Fixes. 01/01/1997
- * Fix UNMB_MAIL - was broken :-(
- * Fix bug with writing out to getmail.err - added
- * new command line parameter for MR/2 username.
- * 1.0.04 Cleanup. 04/01/1997
- * Remove all global variables.
- * Fix bug in parsing UUPC definition files - noone found this :-)
- * Works with nofromsep or fromsep format mailboxes.
- *
- *
- * This program is freely redistributable.
- *
- * Please maintain the current coding style if you want me to
- * incorporate any changes.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- static char version[] =
- "unmbox by Michael Taylor (miket@pcug.org.au) - Version 1.0.04";
-
- static char * get_next_fname (char *basename, char *username);
- static int get_uupc_vars (char *username, char * mailbox_name, char * old_mailbox);
- static void err (char * str, char * username);
- static int parse_nofromsep (FILE *infile, char *xbuf, char *basename,
- char *username);
- static int parse_fromsep (FILE *infile, char *xbuf, char *basename,
- char *username);
-
- static char *
- get_next_fname (char *basename, char *username) {
- char * name1;
- char tname[L_tmpnam];
- static char nxtfname[256];
- FILE * tmp;
- int x = 0, y = 1;
-
- #define MAXTRIES 25000
-
- while (y && x < MAXTRIES) {
- if ((name1 = tmpnam (tname)) == NULL) {
- err ("Cannot create unique filename\n", username);
- return NULL;
- }
- strcpy (nxtfname, basename);
- strcat (nxtfname, "\\");
- strcat (nxtfname, tname+2);
- /*printf ("try: %s\n", nxtfname);*/
- if ((tmp = fopen (nxtfname, "r")) != NULL) {
- fclose (tmp);
- ++x;
- continue;
- }
- y = 0;
-
- }
- if (!y) {
- /*printf ("use: %s\n", nxtfname);*/
- return (char *)nxtfname;
- } else
- return NULL;
-
- }
-
- /*
- get_uupc_vars
-
- Checks for the UUPC control files to locate the mail box.
- The environment var UNMB_MAIL can be used to specify the mailbox.
- */
- static int
- get_uupc_vars (char * username, char * mailbox_name, char * old_mailbox) {
- char buf[256];
- int i, cf;
- char *p, *q, *fn;
- char mailext[256];
- static char mailbox[256];
-
- FILE *tmp;
-
- p = getenv ("UNMB_MAIL");
- if (p != NULL) {
- strcpy (old_mailbox, p);
- strcpy (mailbox_name, p);
- for (q = (p = mailbox_name) + strlen (mailbox_name); p < q; ++p) {
- if (*p == '.')
- break;
- }
- if (*p == '.')
- p[1] = '\0';
- else {
- p[0] = '.';
- p[1] = '\0';
- }
-
- strcat (mailbox_name, "tmp");
- return (1);
- }
-
- /*--------------------- load UUPC rc files ---------------------------*/
- /* read the system file first */
- for (cf = 0, i = 0; i < 2; i++) {
- /* choose the file to open */
- if (i == 0) {
- fn = getenv ("UUPCSYSRC");
- if (fn == NULL) {
- err ("Enviroment variable UUPCSYSRC not defined\n", username);
- exit (EXIT_FAILURE);
- }
- } else {
- fn = getenv ("UUPCUSRRC");
- if (fn == NULL) {
- err ("Enviroment variable UUPCUSRRC not defined\n", username);
- exit (EXIT_FAILURE);
- }
- }
- if ((tmp = fopen (fn, "r")) != NULL) {
- while (fgets (buf, 255, tmp)) {
- p = buf + strlen (buf) - 1;
- if (*p == '\n')
- *p = '\0';
- if (p > buf)
- if (*(p-1) == '\n')
- *(p-1) = '\0';
-
- if (!cf && strnicmp (buf, "confdir=", 8) == 0) {
- /* default root dir if mailbox var not found */
- cf = 1;
- strcpy (mailbox_name, buf+8);
- strcat (mailbox_name, "\\mail"); /* 1.0.01 */
- } else
- if (strnicmp (buf, "mailbox=", 8) == 0) {
- /* mailbox base name */
- strcpy (mailbox, buf+8);
- } else
- if (strnicmp (buf, "maildir=", 8) == 0) {
- /* file name for mailbox */
- cf = 1;
- strcpy (mailbox_name, buf+8);
- } else
- if (strnicmp (buf, "mailext=", 8) == 0) {
- /* extension of file name for mailbox */
- strcpy (mailext, buf+8);
- }
- }
- fclose (tmp);
-
- } else {
- fprintf (stderr, "Cannot open %s\n", fn);
- }
- }
-
- if (!cf) {
- return (0);
- }
-
- strcat (mailbox_name, "\\");
- strcat (mailbox_name, mailbox);
- strcat (mailbox_name, ".");
- strcpy (old_mailbox, mailbox_name);
- strcat (old_mailbox, mailext);
- strcat (mailbox_name, "tmp");
-
- return (1);
- }
-
- static void
- err (char * str, char * username) {
- FILE * errfile;
- char errfname[256];
-
- strcpy (errfname, username);
- strcat (errfname, "\\getmail.err");
-
- if ((errfile = fopen (errfname, "w")) == NULL) {
- fprintf (stderr, "unmbox: error - cannot open file for error message\n");
- exit (EXIT_FAILURE);
- }
- fprintf (errfile, "%s", str);
- fclose (errfile);
- }
-
- #define XBUFSIZE 20480
- static char x01x20[20] =
- "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01";
-
- /*
- parse_nofromsep
-
- parse the mailbox using the 20 x01s as the delimeter between mail items
- */
- static int
- parse_nofromsep (FILE *infile, char *xbuf, char *basename, char *username) {
- FILE * mfile=0;
- int nlines, reterr = 0;
-
- fgets (xbuf, XBUFSIZE, infile);
- while (!feof (infile)) {
- /* if (0 == memcmp (xbuf, x01x20, 20))
- goto nextline;*/
- if ((mfile = fopen (get_next_fname (basename, username), "w")) == NULL) {
- /* this error most likely occurs if the SMTP directory doesn't exist */
- reterr = 1;
- break;
- }
- fputs (xbuf, mfile); nlines = 1;
- while (fgets (xbuf, XBUFSIZE, infile)) {
- if (0 == memcmp (xbuf, x01x20, 20))
- break;
- fputs (xbuf, mfile); nlines++;
- }
-
- if (mfile) { fclose (mfile); mfile = 0;}
- /*nextline:*/
- fgets (xbuf, XBUFSIZE, infile);
- }
-
- if (mfile) { fclose (mfile); mfile = 0;}
- return reterr;
- }
-
- /* new_mail
- *
- * The logic here is that the From line will have the same format.
- * From userid ...
- * To make sure it is a valid From line we identify the format of the
- * first From line and make sure all preceding From lines are the same
- * format - it would be unlikely for a line starting with From to have
- * Numerics and Non-numerics in the same places!
- */
- static int
- new_mail (char * xbuf, int setup) {
- char * p;
- static int nparts = 0;
- static char stype[20];
- char ptype[20];
- int n;
- /*
- Example From lines
- Current UUPC From format
- From teamos2.org!owner-teamos2-l Sat Jan 4 18:33:31 1997 remote from miket
-
- This is from UUPC rmail:
- From fkk Sat, 14 Mar 1992 14:53:27 MET remote from stasys
-
- while this is another:
- From fkk Sat Mar 14 14:53:27 1992 [MET]
- */
- if (memcmp (xbuf, "From ", 5))
- return 0;
-
- for (n = 0; n < 20; ++n)
- ptype[n] = 0;
- for (p = xbuf, n = 0; *p != '\0'; ++p) {
- if (*p == ' ')
- ++n;
- else /* set the type of the part */
- if (n < 20 && !ptype[n] && *p > '0' && *p < '9')
- ptype[n] = 1; /* Numeric */
- else
- ptype[n] = 2; /* Non-Numeric */
-
- }
- /* the first two parts are always a From and a userid
- * are numeric userids possible?
- */
-
- ptype[0] = 3; /* From identifier */
- ptype[1] = 4; /* userid */
-
- if (setup) {
- nparts = n;
- memcpy (stype, ptype, 20);
- /*printf ("nparts=%d\n", nparts);*/
- return 1;
- }
-
- /* if the format matches the remembered format then we have a match */
- if (nparts == n && 0 == memcmp (stype, ptype, 20))
- return 1;
-
- return 0;
- }
-
- /*
- parse_fromsep
-
- parse the mailbox using the FROM+header as the delimeter between mail items
- */
- static int
- parse_fromsep (FILE *infile, char *xbuf, char *basename, char *username) {
- FILE * mfile=0;
- int nlines, reterr=0;
-
- /* initialise new_mail test with From line format */
- if (!new_mail (xbuf, 1)) {
- reterr = 2;
- return reterr;
- }
-
- while (!feof (infile)) {
- if ((mfile = fopen (get_next_fname (basename, username), "w")) == NULL) {
- /* this error most likely occurs if the SMTP directory doesn't exist */
- reterr = 1;
- break;
- }
- fputs (xbuf, mfile); nlines = 1;
- while (fgets (xbuf, XBUFSIZE, infile)) {
- if (new_mail (xbuf, 0))
- break;
- fputs (xbuf, mfile); nlines++;
- }
-
- if (mfile) { fclose (mfile); mfile = 0;}
- }
-
- if (mfile) { fclose (mfile); mfile = 0;}
- return reterr;
- }
-
- int
- main (int argc, char * argv[]) {
- FILE * infile=0;
- int isfromsep=1, errs=0;
- char username[256], basename[256], omailbox[256], maildir[256];
- char * mailbox_name = maildir, * old_mailbox = omailbox;
- char * xbuf = NULL;
-
- strcpy (username, "mail"); /* default value for username */
- if (argc < 2) {
- printf ("%s\n", version);
- printf ("usage: unmbox <SMTP directory> [username]\n");
- err ("usage: unmbox <SMTP directory> [username]\n", username);
- exit (EXIT_FAILURE);
- }
-
- strcpy (basename, argv[1]);
-
- if (argc > 2)
- strcpy (username, argv[2]);
-
- if (!get_uupc_vars (username, mailbox_name, old_mailbox)) {
- err ("error - cannot find UUPC mail box\n", username);
- exit (EXIT_FAILURE);
- }
-
- /* test if any mail - so <mailbox>.tmp is not deleted! */
- if ((infile = fopen (old_mailbox, "r")) == NULL) {
- /* err ("error - cannot open UUPC mailbox\n", username);*/
- exit (EXIT_FAILURE);
- }
- fclose (infile);
-
- remove (mailbox_name);
- if (rename (old_mailbox, mailbox_name)) {
- /* err ("error - cannot access UUPC mailbox - try again later\n", username);*/
- exit (EXIT_FAILURE);
- }
- if ((infile = fopen (mailbox_name, "r")) == NULL) {
- /* err ("error - cannot open UUPC mailbox\n", username);*/
- exit (EXIT_FAILURE);
- }
-
- xbuf = (char *)malloc (XBUFSIZE+1);
- if (xbuf == NULL) {
- err("error - Cannot allocate temporary buffer\n", username);
- exit (EXIT_FAILURE);
- }
-
- /* first check if file is nofromsep or fromsep format */
- fgets (xbuf, XBUFSIZE, infile);
- if (feof (infile)) {
- fclose (infile);
- /* just to be nice - rename mailbox so that the user can try again later */
- rename (mailbox_name, old_mailbox);
- if (xbuf) {free (xbuf); xbuf = NULL;}
- exit (EXIT_FAILURE);
- }
- /* if the first line is 20 0x01s then this is a UUPC-style (nofromsep)
- * delimeted mailbox.
- */
- while (1) {
- if (0 == memcmp (xbuf, x01x20, 20)) {
- isfromsep = 0;
- break;
- }
- if (0 == memcmp (xbuf, "From ", 5))
- break;
- fgets (xbuf, XBUFSIZE, infile);
- if (feof (infile)) {
- fclose (infile);
- /* just to be nice - rename mailbox so that the user can try again later */
- rename (mailbox_name, old_mailbox);
- if (xbuf) {free (xbuf); xbuf = NULL;}
- err ("error - no From or nofromsep line in mailbox\n", username);
- exit (EXIT_FAILURE);
- }
- }
-
-
- if (isfromsep)
- errs = parse_fromsep (infile, xbuf, basename, username);
- else
- errs = parse_nofromsep (infile, xbuf, basename, username);
- if (errs) {
- if (1 == errs)
- err ("error - cannot open new file for mail\n", username);
- else if (2 == errs)
- err ("error - no From line at start of mailbox\n", username);
- else
- err ("error - parse error reading mailbox\n", username);
- /* just to be nice - rename mailbox so that the user can try again later */
- rename (mailbox_name, old_mailbox);
- }
-
- fclose (infile);
- if (xbuf) {free (xbuf); xbuf = NULL;}
-
- exit (EXIT_SUCCESS);
- return (EXIT_SUCCESS); /* gets rid of dumb compiler warning */
- }