/* make executable with the command:
   DOS:
        bcc -ms buildctl.c \borlandc\lib\wildargs.obj
   LINUX:
	gcc buildctl.c -o buildctl
*/


#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef MSDOS
#include <dir.h>
#include <dos.h>
#include <io.h>
#else
#define stricmp strcasecmp
#endif
#define NULLFILE (FILE *) 0
#define NULLCHAR (char *) 0
#define	BM_READ		2

#ifdef MSDOS
char *dirname = ".";
#else
char *dirname = "/nos";
#endif

typedef short int int16;

/* a mailbox entry */
struct let {
	long	start;
	long	size;
	long	bid;
	int16	status;
};


/* Returns 1 if name is in the given area file, 0 otherwise */
static int
isarea(name)
char *name;
{
char buf[100], *cp;
FILE *fp;

	sprintf (buf, "%s/spool/areas.sys", dirname);
	if((fp = fopen(buf,"r")) == NULLFILE)
		return 0;
	while(fgets(buf,sizeof(buf),fp) != NULLCHAR) 	{
		/* The first word on each line is all that matters */
		if(isalnum(buf[0])) 	{ /* skip comments */
		        if((cp = strchr(buf,' ')) != NULLCHAR)
				*cp = '\0';
		        /*There could still be a tab before the space ! -WG7J */
			if((cp = strchr(buf,'\t')) != NULLCHAR)
				*cp = '\0';
		        /*This could be a line with just the area name,
		         *ie terminated with 'CR/LF' - WG7J
		         */
		        if((cp = strchr(buf,'\n')) != NULLCHAR)
				*cp = '\0';
		        if(stricmp(name,buf) == 0) {    /* found it */
				fclose(fp);
				return 1;
				}
			}
		}
	fclose(fp);
	return 0;
}


void
rebuild_one (str)
char *str;
{
long msgid;
char *cp;
register FILE *fp, *cfp;
int nextisBID, firstIDline, k;
char buf[256], buf2[512];
int public, status, lines;
long last, start, size;

	cp = strrchr (str, '/');
	if (!cp)
		cp = strrchr (str, '\\');
	if (!cp)	{
		sprintf (buf2, "%s/spool/mail", dirname);
		sprintf (buf, "%s/control/%s", buf2, str);
		cp = str;
	} else	{
		*cp++ = 0;			
		strcpy (buf2, str);
		sprintf (buf, "%s/control/%s", str, cp);
	}
	if (strstr (buf, ".TXT") || strstr (buf, ".txt"))
		strcpy (&buf[strlen(buf) - 3], "ctl");
	else
		strcat (buf, ".ctl");
	if((cfp = fopen(buf,"wb")) == NULLFILE)	{
		printf ("Can't create control file '%s'\n", buf);
		return;
	}
	sprintf (buf, "%s/%s", buf2, cp);
#if 0
	if (cp)		{
		strcat (buf, "/");
		strcat (buf, cp);
	}
#endif
	if (!strstr (buf, ".txt") && !strstr (buf, ".txt"))
		strcat (buf, ".txt");
	if ((fp = fopen (buf, "rt")) == NULLFILE)	{
		printf ("Can't open file '%s'\n", buf);
		return;
	}
	firstIDline = nextisBID = 0;
	printf ("Building Control Files for: '%s'\n", buf);
	cp = strstr(buf, ".");
	*cp = 0;
	public = isarea (buf);
	start = last = 0;
	lines = 0;
	while(fgets(buf,sizeof(buf),fp) != NULLCHAR){
		if (!strncmp(buf, "From ", 5))	{
#ifdef MSDOS
			size = last - start - lines; 
#else
			size = last - start; 
#endif
			if (size)	{
				fwrite (&start, sizeof(long), 1, cfp);
				fwrite (&size, sizeof(long), 1, cfp);
				fwrite (&msgid, sizeof(long), 1, cfp);
				fwrite (&status, sizeof(int), 1, cfp);
			}
			lines = status = 0;
			start = last;
			firstIDline = 0;
		}
		lines++;

		/* don't think this next section is necessary. All
		   messages SHOULD have a MSGID line */
		if (!firstIDline && nextisBID && (cp=strstr(buf,"AA")) != NULLCHAR) {
			/*what follows is the message-number*/
			msgid = atol(cp+2);
			nextisBID = 0;
			firstIDline = 1;
			}

#if 0
		if (!strncmp ("Message-Id: ", buf, 12))	{
			long nerf;
			cp = &buf[12];
			if (*cp == '<')
				cp++;
			nerf = atol(cp);
			if (nerf)
				msgid = nerf;
		}
#endif
		if (!strncmp ("Received: ", buf, 10))
			nextisBID = 1;
		if (!public && !strncmp ("Status: R", buf, 9))
			status = BM_READ;
		last = ftell (fp);
	}
	fclose(fp);
#ifdef MSDOS
	size = last - start - lines; 
#else
	size = last - start; 
#endif
	fwrite (&start, sizeof(long), 1, cfp);
	fwrite (&size, sizeof(long), 1, cfp);
	fwrite (&msgid, sizeof(long), 1, cfp);
	fwrite (&status, sizeof(int), 1, cfp);
	fclose(cfp);
}

#ifdef MSDOS
int
newertime (txt, ctl)
struct ftime *txt, *ctl;
{
int retval = 1;		/* default to 'yep, it's newer */
int same = 0;

	if ((txt->ft_year <= ctl->ft_year) && (txt->ft_month <= ctl->ft_month)
		&& (txt->ft_day <= ctl->ft_day) && (txt->ft_hour <= ctl->ft_hour))
			retval = 0;
	if ((txt->ft_year == ctl->ft_year) && (txt->ft_month == ctl->ft_month)
		&& (txt->ft_day == ctl->ft_day) && (txt->ft_hour == ctl->ft_hour))
			same = 1;
	if (same && (txt->ft_min > ctl->ft_min))	{
		retval = 1;
		same = 0;
	}
	if (same && (txt->ft_tsec > ctl->ft_tsec))
		retval = 1;
	return (retval);
}
#endif


void
main (argc, argv)
int argc;
char *argv[];
{
int k = 1, doit, doall = 0;
#ifdef MSDOS
char buf[128], *cp;
struct ffblk ff;
struct ftime txt, ctl;
FILE *fp;
long size;
#endif

	if (argc == 1)
#ifdef MSDOS
		doall = 1;
	if ((argc > 1) && ((argv[1][0] == '-') || (argv[1][0] == '/')))	{
#else
	{
		fprintf (stderr, "usage: buildctl [-ddirname] <file> [<file> ...]\n");
		exit (1);
	}
	if (argv[1][0] == '-')	{
#endif
		switch (tolower (argv[1][1]))	{
			case 'd':	if (argv[1][2])		{
						dirname = &argv[1][2];
						k = 2;
						if (argc == 2)
#ifdef MSDOS
							doall = 1;
#else
						{
							fprintf (stderr, "usage: buildctl [-ddirname] <file> [<file> ...]\n");
							exit (1);
						}
#endif
						break;
					}
					/* else fall through */
			default:	printf ("usage: buildctl [-ddirname] [mailfile]\n");
					exit (1);
		}
	}
#ifdef MSDOS
	if (!doall)		{
#endif
		for ( ; k < argc; k++)
			rebuild_one (argv[k]);
#ifdef MSDOS
	} else	{
		sprintf(buf,"%s/spool/mail/*.txt", dirname);
		if (findfirst(buf, &ff, 0) == 0) {
			do {
				sprintf (buf, "%s/spool/mail/%s", dirname, ff.ff_name);
				if ((fp = fopen (buf, "r")) == NULL)
					continue;
				getftime (fileno (fp), &txt);
				fseek(fp,0L,2);
				size = ftell(fp);
				fclose (fp);
				if (size == 0L)	{
					remove (buf);
					continue;
				}
				sprintf (buf, "%s/spool/mail/control/%s", dirname, ff.ff_name);
				cp = &buf[strlen(buf) - 3];
				strcpy (cp, "ctl");
				doit = 1;
				fp = fopen (buf, "r");
				if (fp)		{
					getftime (fileno (fp), &ctl);
					fclose (fp);
					doit = newertime (&txt, &ctl);
				}
				if (doit)
					rebuild_one (ff.ff_name);
			} while (findnext(&ff) == 0);
		} else
			printf ("Couldn't find any mail files...\nThis command (without the -d option) must be executed from your\nTNOS root directory\n");

		/* now we remove any ctl files that do not have coresponding txt files */
		sprintf(buf,"%s/spool/mail/control/*.ctl", dirname);
		if (findfirst(buf, &ff, 0) == 0) {
			do {
				sprintf (buf, "%s/spool/mail/%s", dirname, ff.ff_name);
				cp = &buf[strlen(buf) - 3];
				strcpy (cp, "txt");
				if (access (buf, 0) != NULL)	{
					sprintf(buf,"%s/spool/mail/control/%s", dirname, ff.ff_name);
					remove (buf);
				}
			} while (findnext(&ff) == 0);
		}

	}
#endif	/* MSDOS */
}

