/*
 * Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University
 * in the City of New York.  Permission is granted to any individual or
 * institution to use, copy, or redistribute this software so long as it
 * is not sold for profit, provided this copyright notice is retained.
 */

#ifndef lint
static char *rcsid = "$Header: transform.c,v 1.8 88/06/27 00:17:35 chris Exp $";
#endif

/*
 * transform:  Transform a mail.txt format file brought over from the
 * 20 with ftp to fix the byte counts.  Since the 20's have CR/LF and
 * the UNIX's only have LF, ftp strips out the CRs.  This messes up the
 * byte counts in mail.txt format files.  Try to figure out where the
 * message ends and fix them up.
 *
 * For now, read from argv[1] and write to stdout, like good Unix program.
 * So say "transform mail-20.txt > mail-unix.txt".
 *
 * Note that this program is not yet very robust, but it does do the job.
 * for example, it must read from a real file, or it can't get the size
 * and read the whole thing in at once.
 *
 * Add Michael A. Cooper's modifications to also convert SRI UNIX-MM
 * mail.txt files into Columbia Unix MM format.  The SRI MM uses the
 * byte count only as a guess as to where the end of message is.
 */

#include "config.h"
#include "osfiles.h"
#include "compat.h"

char *index (), *rindex ();

#define FALSE (0)
#define TRUE (!FALSE)

#define hdrlen 81			/* the header's less than 80 chars */
int msgnum = 0;			        /* which message we're up to */

main (argc,argv)
int argc;
char **argv;
{
    struct stat statb;
    FILE *filep;

    char *mail;				/* what's left of the mail file */
    char *date, *psize, *flags, *text;	/* the pieces of a message */

    int oldsize;			/* believed message size */
    int lines;				/* how many lines in this message */
    int eof;

    if (argc != 2) {
	fprintf (stderr, "usage: %s filename\n", argv[0]);
	exit (1);
    }

    if (stat (argv[1],&statb) != 0) {	/* we need the length */
	perror (argv[1]);
	exit(1);
    }

    if ((filep = fopen (argv[1], "r")) == NULL) {
	perror (argv[1]);
	exit(1);
    }

    /* get the whole file */
    if ((mail = (char *) malloc (statb.st_size +1)) == NULL) {
	fprintf (stderr, "%s: File too big for internal buffer.\n", argv[1]);
	exit(1);
    }
    mail[statb.st_size] = '\0';
    if (fread (mail, sizeof (char), statb.st_size, filep) != statb.st_size) {
	perror (argv[1]);
	exit(1);
    }

    while (++msgnum) {			/* do next message */

	date = mail;			/* header starts here */
	text = index (mail, '\n') + 1;	/* the line after the header */
	psize = index (mail, ',') + 1;	/* these have to be... */
	flags = index (mail, ';') + 1;	/* ... in the first line */
	if (psize > text || flags > text ||
	    (text - 1) == NULL || (flags - 1) == NULL || (psize - 1) == NULL) {
	    fprintf (stderr, "Errors in header line\n");
	    fail (msgnum);
	}

	oldsize = atoi (psize);
	/* we want to see if we got a negative number or a non-number */
	/* a non-number gives value 0 */
	if ((oldsize < 1) && (*psize != '0')) { /* really zero is okay */
	    fprintf (stderr, "Illegal size value.\n");
	    fail (msgnum);
	}

	lines = 0;
	mail = text;			/* start searching here */
	eof == FALSE;
        /* oldsize counted CR and LF, so count each LF an extra time */
	while (((mail - text + lines) < oldsize) && !eof) {
	    lines++;			/* doing one more line */
	    mail = index (mail, '\n') + 1;
	    if ((mail-1) == NULL) {	/* no more \n's */
		fprintf (stderr, "Premature end of message\n");
		fail (msgnum);
	    }
	    eof = (*mail == '\0');	/* end of file? */
	}

	while (!ismatch(mail) && !eof) {
	    mail = index (mail, '\n') + 1;
	    if ((mail-1) == NULL) {	/* no more \n's */
		break;
	    }
	    eof = (*mail == '\0');	/* end of file? */
	}

	fwrite (date, sizeof (char), psize - date, stdout); /* date, */
	printf ("%d;", mail - text);	/* length of message */
	fwrite (flags, sizeof(char), mail - flags, stdout); /* flags & text */

	if (eof)			/* made it! */
	    exit (0);
    }
}

/*
 * fail: 
 * give a nice message on failure, tell them which message messed up
 * note that all previous messages were written out successfully
 */
fail (num)
int num;
{
    fprintf (stderr, "Bad mail-txt format in header of message #%d\n", num);
    exit (1);
}

/*
 * ismatch:
 * compare str against a regex looking for a header line.
 * since re_exec() ignores \n's, copy the current "line" and
 * then call re_exec().
 */
ismatch(str)
char *str;
{
    char buf[BUFSIZ];
    char *p;
    static int first = TRUE;
    int st;

    if (first) {
	first = FALSE;
	/* pattern is:         22-Jan-88  3:45:11-GMT,944;000000000201 */
	if ((p = (char *) re_comp(".*-.*-.*:..:..-.*,.*;.*")) != NULL) {
	    fprintf("Bad regex: %s\n", p);
	    fail(msgnum);
	}
    }

    p = index(str, '\n');
    strncpy(buf, str, (p) ? (p - str) : sizeof(buf));
    if (p) {
	buf[p - str] = NULL;
    }

    st = re_exec(buf);

    return(st);
}
