
/*
 *  UNPACKMAIL.C
 */

#include "news.h"
#include <expand_path.h>
#include <ctype.h>

static FILE *mp;

static void
CloseOldFile(void)
{
    if (mp) {
	fflush(mp);
	if (fclose(mp) != 0) {
	    printf("FATAL -- I/O error while writing message\n");
	    exit(20);
	}
	mp = NULL;
    }
}

static int
NewFile(char *dir, int count)
{
    char namebuf[64];

    CloseOldFile();

    do {
	sprintf(namebuf, "%s/%d", dir, ++count);
    } while (access(namebuf, 0) == 0);

    if ((mp = fopen(namebuf, "w")) == NULL) {
	printf("FATAL -- can't create %s to hold new message\n", namebuf);
	exit(10);
    }
    printf("%4d: ", count);
    return (count);
}

static void
copyline(register char *buf, FILE *fp)
{
    register int c;

    if (mp == NULL)
	return;

    while (*buf != '\0') {
	putc(*buf, mp);
	if (*buf == '\n')
	    return;
	++buf;
    }
    while ((c = getc(fp)) != EOF) {
	putc(c, mp);
	if (c == '\n')
	    return;
    }
}

static int
real_from(char *buffer, char *who)
{
    /*
     * returns true if 's' has the seven 'from' fields,
     * initializing the who to the sender
     * also returns true if has dmail ARCHIVE flag
     */
    char fld3[20], fld7[20];

    if (strncmp(buffer, "From ", 5) != 0)
	return (0);

    fld7[0] = '\0';
    sscanf(buffer, "%*s %s %s %*s %*s %*s %s", who, fld3, fld7);
    if (fld7[0] != '\0')
	return (1);
    if (strcmp(fld3, "(ARCHIVE)") != 0)
	return (0);
    strcpy(who, fld3);
    return (1);
}

static void
forwarded(char *buffer, char *who)
{
    /*
     * change 'from' and date fields to reflect the ORIGINATOR of
     * the message by iteratively parsing the >From fields...
     */
    char machine[80], buff[80], *strncpy();

    machine[0] = '\0';
    sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s", who, machine);

    if (machine[0] == '\0') /* try for srm address */
	sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s", who, machine);

    if (machine[0] == '\0')
	sprintf(buff, "anonymous");
    else
	sprintf(buff, "%s!%s", machine, who);

    strncpy(who, buff, 80);
}

static void
remove_first_word(char *dest, char *string)
{
    /*
     * Removes first word of string, i.e., up to first non-white space
     * following a white space, and copies it to the destination.
     */
    while (!isspace(*string))
	++string;
    while (isspace(*string))
	++string;
    while (*dest++ = *string++)
	;
    if (dest[-2] == '\n')
	dest[-2] = '\0';
}

static void
show_header(char *from, char *subject)
{
    /*
     * output header in clean format, including abbreviation
     * of return address if more than one machine name is
     * contained within it!
     */
    register char *p, *q, *r;
    extern char *strchr();

#ifdef PREFER_UUCP
    if (chloc(from, '!') != -1 && chloc(from, '@') > 0) {
	for (p=from; *p != '@'; p++)
	    ;
	*p = '\0';
    }
#endif

    p = from;
    q = from;	  /* find address portion */
    while ((r = strchr(q, '!')) != NULL) {
	p = q;
	q = r + 1;
    }

    printf("%-30s  %s\n", p, subject);
}

static void
parse_arpa_from(char *buffer, char *newfrom)
{
    /*
     * Try to parse the 'From:' line given... It can be in one of
     * two formats:
     *	    From: Dave Taylor <hpcnou!dat>
     * or   From: hpcnou!dat (Dave Taylor)
     * Change 'newfrom' ONLY if sucessfully parsed this entry and
     * the resulting name is non-null!
     */
    register char *p, *q;
    register int i;
    extern char *strncpy();

    if (*(q = buffer + strlen(buffer) - 1) == '>') {
	    p = buffer + 6, q = p;	    /* skip "From: " */
	    do {
		++q;
	    } while (*q != '\0' && *q != '<' && *q != '(');
    } else if (*q == ')') {
	    p = q;
	    do {
		--p;
	    } while ((p > buffer + 5) && *p != '(' && *p != '<');
    } else
	return;

    if (p >= q)
	return;

    /* remove leading spaces... */
    while (isspace(*++p))
	;

    /* remove trailing spaces... */
    while (isspace(*--q))
	;

    /* if anything is left, let's change 'from' value! */
    if (p >= q)
	return;
    i = p - q + 1;
    strncpy(newfrom, p, i)[i] = '\0';
}

static char buffer[1000];
static char from_whom[512], subject[512];

int
unpackmail(char *dir, int count)
{
    register FILE *fp;
    register char *mailfile;

    if (access(mailfile = expand_path(dir, ".mailfile"), 0) != 0)
	return count;
    if ((fp = fopen(mailfile, "r")) == NULL)
	return count;
    mailfile = fgets(buffer, (int)sizeof buffer, fp);
    fclose(fp);
    if (mailfile == NULL)
	return count;
    if ((mailfile = strchr(buffer, '\n')) != NULL)
	*mailfile = '\0';
    if ((fp = fopen(buffer, "r")) == NULL)
	return count;
    mailfile = strdup(buffer);

    printf("New mail:\n");
    mp = NULL;
    while (fgets(buffer, (int)sizeof buffer, fp) != NULL) {
	if (real_from(buffer, from_whom)) {
	    count = NewFile(dir, count);
	} else if (from_whom[0] != '\0') {
	    if (strncmp(buffer, ">From ", 6) == 0) {
		forwarded(buffer, from_whom);
	    } else if (strncmp(buffer, "Subject:", 8) == 0 || strncmp(buffer, "Re:", 3) == 0) {
		if (subject[0] == '\0')
		    remove_first_word(subject, buffer);
	    } else if (strncmp(buffer, "From:", 5) == 0)
		parse_arpa_from(buffer, from_whom);
	    else if (buffer[0] == '\n') {
		show_header(from_whom, subject);
		from_whom[0] = 0, subject[0] = 0;
	    }
	}
	copyline(buffer, fp);
    }
    fclose(fp);
    CloseOldFile();

#ifndef TEST
    remove(mailfile);
#else
    printf("remove(%s)\n", mailfile);
#endif
    free(mailfile);
    return count;
}

#ifdef TEST
main(int argc, char **argv)
{
    printf("New value of count is %d\n", unpackmail("UUNEWS:mail.test", 9));
    return 0;
}
#endif

