/*--------------------------------------------------------------------- */
/* umbox.c								*/
/*	Break nn(1) mbox file into separate articles in a spool		*/
/*	directory tree.							*/
/*	A report is  sent to stdout.					*/
/*									*/
/* Usage:								*/
/*	umbox mboxfile							*/
/*									*/
/* Limitations:								*/
/*	All directories MUST exist.					*/
/*									*/
/* History:								*/
/*	1 Nov 1990	v2.0						*/
/*									*/
/* Author:								*/
/*	Eyal Lebedinsky							*/
/*	Canberra, AUSTRALIA						*/
/*--------------------------------------------------------------------- */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

#ifndef	NEWSDIR
#ifdef amiga
#define NEWSDIR "dh0:news/"
#else
#define	NEWSDIR	"f:\\news\\"
#endif
#endif

#ifndef	DIRSEP
#ifdef amiga
#define	DIRSEP	"/"
#else
#define	DIRSEP	"\\"
#endif
#endif

#ifndef amiga
typedef unsigned char	uchar;
#endif

static uchar	line[4096];
static uchar	newsdir[1024] = NEWSDIR, dirsep[20] = DIRSEP,
		groupname[1024], groupdir[1024], filename[1024];
static int	cc1 = 0, cc2 = 0;

static int
get_dir (group)
uchar	*group;
{
	uchar	*p, *q, *s;
	struct stat	statbuff;

	for (p = groupdir, q = newsdir; *q; *p++= *q++);
	for (q = group; *q; ++q) {
		if (*q == '.')
			for (s = dirsep; *s; *p++ = *s++);
		else
			*p++ = *q;
	}
	*p = '\0';

	if (stat (groupdir, &statbuff))
		printf ("could not stat %s\n", groupdir);
	else if (!(statbuff.st_mode & S_IFDIR))
		printf ("%s not a directory\n", groupdir);
	else
		return (0);
	return (1);
}

FILE *active = NULL;

static void
do_one (file)
uchar	*file;
{
	FILE	*fin = NULL, *fout = NULL;
	int	found, c1 = 0, c2 = 0, body;
	uchar	artno[20], *p;
#ifdef	VBUF
	uchar	*vip, *voq;
#endif

	fin = fopen (file, "rt");
	if (fin == NULL) {
		fprintf (stderr, "could not open %s\n", file);
		return;
	}

#ifdef	VBUF
#define	BSIZE	20480
	if ((vip = malloc (BSIZE)) == NULL ||
	    setvbuf (fin, vip, _IOFBF, BSIZE) ||
	    (voq = malloc (BSIZE)) == NULL ||
	    setvbuf (fout, voq, _IOFBF, BSIZE)) {
		fprintf (stderr, "Out of memory\n");
		if (vip != NULL)
			free (vip);
		if (voq != NULL)
			free (voq);
		exit (1);
	}
#endif
			/* find first header */
	for (found = 0; fgets (line, sizeof (line), fin) != NULL;) {
		if (memcmp (line, "Newsgroup: ", 11) == 0) {
			found = 1;
			break;
		}
	}

	while (found) {
		++c1;
		if (sscanf (line,
		   "Newsgroup: %[abcdefghijklmnopqrstuvwxyz0123456789.-]/%s",
				groupname, artno) != 2) {
			fprintf (stderr, "broken mbox\n");
			break;
		}
		if (get_dir (groupname))
			printf ("%s not a directory\n", groupdir);
		else {
			strcpy (filename, groupdir);
			strcat (filename, dirsep);
			strcat (filename, artno);
			fout = fopen (filename, "wt");
			if (fout == NULL)
				printf ("could not open %s\n",
					filename);
			else {
				printf ("created %s\n", filename);
				++c2;
			}
		}

		fputs (line, stdout);

		if (fout != NULL) {
			if (fputs (line, fout) == EOF) {
			    	fprintf (stderr, "write error on %s\n",
					filename);
				fclose (fout);
				fout = NULL;
			}
		}

		for (body = found = 0;
		     fgets (line, sizeof (line), fin) != NULL;) {
			if (memcmp (line, "Newsgroup: ", 11) == 0) {
				found = 1;
				break;
			}
			if (fout != NULL) {
				if (!memcmp (line, "Lines: ", 7))
					body = 1;
				else if (!body && !memcmp (line, ">From: ", 7))
					for (p = line; p[0] = p[1]; ++p);
				if (fputs (line, fout) == EOF) {
				    	fprintf (stderr, "write error on %s\n",
						filename);
					fclose (fout);
					fout = NULL;
				}
			}
			if (!memcmp (line, "Subject: ", 9) ||
			    !memcmp (line, "Lines: ", 7) ||
			    !memcmp (line, "From: ", 6) ||
			    !memcmp (line, "Date: ", 6) ||
			    !memcmp (line, "Keywords: ", 10))
				fputs (line, stdout);
		}
		fputs ("\n", stdout);
		if (fout != NULL) {
			fclose (fout);
			fout = NULL;
		}
	}

	if (fin != NULL)
		fclose (fin);

#ifdef	VBUF
	free (vip);
	free (voq);
#endif

	fprintf (stderr, "%s: %u articles found, %u saved.\n",
		file, c1, c2);
	cc1 += c1;
	cc2 += c2;
#ifdef amiga
	fprintf (active, "%s %s\n", groupname, artno);
#endif
}

main (argc, argv)
int	argc;
uchar	*argv[];
{
	if (argc < 2) {
		fprintf (stderr, "usage: umbox InputFiles\n");
		exit (0);
	}

#ifdef amiga
	active = fopen ("active", "w");
	if (active == NULL) {
		fprintf (stderr, "could not open 'active' file\n");
		return;
	}
#endif
	while (argc-- > 1)
		do_one (*++argv);

	fprintf (stderr, "total %u articles found, %u saved.\n",
		cc1, cc2);

#ifdef amiga
	fclose (active);
#endif
	exit (0);
}
