/* 		pcmail.c
 
 
 
		copyright (C) 1987 Stuart Lynne
 
		Copying and use of this program are controlled by the terms of the
		Free Software Foundations GNU Emacs General Public License.
 
 
		version		0.1		March 31/1987
 
	
pcmail
 
		pcmail address1 address2 ... < the.message
 
description
 
	An 822 compatible (hopefully) mail delivery system for pc's.
 
	Designed for delivering mail on a pc based system. It will put
	local mail (ie, not @ or ! in address) into files in the default
	mail directory.
 
	If remote it will put into an outgoing mailbag in the default mail
	directory. Performs a simple bundling of mail messages into one 
	file with arguments prepended as To: arg header lines. And adds a 
	Message-Lines: header which gives the number of lines in the
	content part of the message (after the first blank line).
 
		pcmail john jack jill@xyz.uucp < afile
 
		To: john
		To: jack
		To: jill@xyz.uucp
		X-Message-Lines: ?????
		Content-Length: ?????
 
		...
		...
		...
 
	Content-Length: is used without X- prepended to be compatible with AT&T
	Mail bundles. This is not 822 compatible per se, but is allowed.
 
	It also adds the from From and Date lines. Subject: lines may be inserted
	by placing them at the beginning of the message.
 
	A Unix version should lock the /usr/mail/mailbag file.
 
	Another program called rpcmail will unbundle the files created by 
	pcmail and deliver each message to the local rmail. So conceptually
 
		(pcmail ..... < ...; pcmail .... < ...) | sz -> rz | rpcmail
 
	would deliver remote messages intact.
 
environment variables
 
	The following evironment variables are used:
 
		MAILBOX		current user's mailbox, 	"stuart"
		NAME		current user's name, 		"Stuart Lynne"
		DOMAIN		domain of this machine, 	"slynne.mac.van-bc.can"
		MAILDIR		where is mail kept,			"mpw:mail"
 
compiling
 
	Compiled by itself it will operate as a standalone program. If the 
	compiler option:
 
		-DNOMAIN
	
	is used, it will compile as a routine:
 
		pcmail (argc, argv)
		char **argv;
		int argc;
 
	and can be used internally in other programs.


Customization

	PCMAIL		mailbag for remote mail
	FAKEUUX		emulate uux, make appropriate files in SPOOLDIR

	RMAIL		rmail

	DEBUG1		first level Debug trace


*/

/*
#ifdef NOMAIN
#include "dcp.h"
#else
*/
#include <stdio.h>
#include "host.h"
/*
#endif
*/

FILE *FOPEN();

#define FORWARD		"Forward to"

 
#define	SBUFSIZ		124
 
FILE   *mailfile;
FILE   *tempfile;
 
char	buf[BUFSIZ];
char	miscbuff[100];
long int lines = 0;
long int bytes = 0;
long int sequence = 0;

long tloc;
char chartime[26];	/* current time in characters */
char *thetime;
 
char	tfilename[100];
char	mfilename[100];
char	mailsent[100];


int local = TRUE;

char 	remotes[BUFSIZ];


char uucp[] = "uucp";

char *fgets();
int fputs();

#ifdef NOMAIN

#ifdef RMAIL
#define main	rmail
#else
#define	main	lmail
#endif

#define exit	return

extern int debuglevel;

#else
int debuglevel;
#endif

#ifndef RMAIL
char	Subject[132] = "";
#endif

char *mcurdir;
char s_mcurdir[128];	/* current directory path (save malloc call) */
char * getcwd();
int chdir();



main(argc, argv)
char *argv[];
{
	long int position;
	register int header = 1;
	register int amount;
 
	register int argcount;
	register char **argvec;
	int remote;
	int s1, s2;


	

#ifndef NOMAIN
	/* get environment var's */
	HOSTINIT;
	loadenv();

 	if (argc <= 1) {
		fprintf( stderr, "pcmail usage: pcmail addresses < message\n" );
		exit(1);
	}
	debuglevel = 1;
	
#endif
#ifdef RMAIL
	local = FALSE;
#else
	local = TRUE;
#endif

	if ( debuglevel > 5 ) {
		fprintf( stderr, "pcmail: argc %d ", argc );
		argcount = argc;
		argvec = argv;
		while (argcount--) {
			fprintf( stderr, " \"%s\"", *argvec++ );
			}
		fprintf( stderr, "\n" );

		tloc = time( (long *)NULL );
		thetime = ctime(&tloc);
		fprintf( stderr, "thetime: %s\n",thetime );
	}
	

	mcurdir = getcwd( s_mcurdir, 0 );
	chdir( spooldir );

	/* get sequence number */
	mkfilename( tfilename, confdir, SFILENAME );
	
 	if ( debuglevel > 4 )
 	   fprintf( stderr, "pcmail: opening %s\n", tfilename ); /* */
 
	tempfile = FOPEN( tfilename, "r", 't' );
	if (tempfile != (FILE *)NULL) {
		fscanf( tempfile, "%ld", &sequence );
		fclose( tempfile );
	}
	else 
		fprintf( stderr, "pcmail: can't find %s file, creating\n",
					tfilename );
 
	/* update sequence number */
	if ( debuglevel > 5 ) 
		fprintf( stderr, "pcmail: new sequence # %ld\n", sequence ); 
	
	tempfile = FOPEN( tfilename, "w", 't' );
	if (tempfile != (FILE *)NULL) {
		fprintf( tempfile, "%ld\n", sequence+1 );
		fclose( tempfile );
	}
 
	/* open a temporary file */
	/* sprintf( tfilename, TFILENAME, sequence ); */
 	sprintf( miscbuff, TFILENAME, sequence );
 	mkfilename( tfilename, tempdir, miscbuff );
	
 	if ( debuglevel > 5 ) 
 		fprintf( stderr, "pcmail: opening %s\n", tfilename );

	tempfile = FOPEN( tfilename, "w", 'b' );
 	if (tempfile == (FILE *)NULL)  {
		fprintf( stderr, "pcmail: can't open %s\n", tfilename );
		exit(1);
	}
	
	/* copy stdin to tempfile, counting content lines and bytes */
	header = 1;
	while (fgets( buf, 512, stdin ) != (char *)NULL) {
		if (header != 0) {
			if (strlen( buf ) == 1) {
				header = 0;
				fprintf( tempfile, "\n" );
				continue;
			}
			else if (strchr( buf, ':' ) == NULL) {
				header = 0;
				fprintf( tempfile, "\n" );
			}
		}
		if (header == 0) {
			lines++;
			bytes += strlen( buf );
		}
		fputs( buf, tempfile );	
	}
#ifndef RMAIL
	/* copy stdin to tempfile, counting content lines and bytes */
	/* get sequence number */
	mkfilename( mfilename, home, SIGFILE );
	
	if (debuglevel > 4)
 	   fprintf( stderr, "pcmail: opening sigfile %s\n", mfilename );
	mailfile = FOPEN( mfilename, "r", 't' );
	if (mailfile != (FILE *)NULL) {
		fputs( "\n--\n", tempfile );
		while (fgets( buf, 512, mailfile ) != (char *)NULL) {
			lines++;
			bytes += strlen( buf );
			fputs( buf, tempfile );	
		}
		fclose( mailfile );
 	}
#endif

 	fclose( tempfile );
 	
	if ( debuglevel > 4 ) {
		fprintf( stderr, "pcmail: stdin copied to tmp %ld %ld\n",
	                 bytes, lines ); 
 		fprintf( stderr, "pcmail: args %d\n", argc );
	}
	
	/* loop on args, copying to appropriate postbox, 
	   do remote only once 
	   remote checking is done empirically, could be better
	*/
	remotes[0] = '\0';
	

#ifndef RMAIL
	if ( strcmp( argv[1], "-s" ) == SAME ) {
		argv++;argv++;
		argc--;argc--;
		if ( argc == 0 )
			return( -1 );
		strcpy( Subject, *argv );
		}
#endif
	argcount = argc;
	argvec = argv;
		
	while (--argcount > 0) {
		argvec++;
		if ( debuglevel > 5 ) 
			fprintf( stderr, "pcmail: arg# %d\ %s\n", 
							argcount, *argvec ); 

		if (
			(strchr( *argvec, '!' ) != SAME) ||
			(strchr( *argvec, '@' ) != SAME) ||
			(strchr( *argvec, '%' ) != SAME)
		   ) {
			if ( debuglevel > 5 ) 
				fprintf( stderr, "pcmail: send to remote\n" ); 
				
			s1 = strlen( remotes );
			s2 = strlen( *argvec );

			/* can we cram one more address on line */
			if ( s1 > 0 && (s1 + s2 + 1) > 128 ) {
				/* dump it then, to bad */
				sendone( argc, argv, remotes, TRUE );
				remotes[0] = '\0';
			}

			/* add *arvgvec to list of remotes */
			strcat( remotes, " " );
			strcat( remotes, *argvec );

		}
		else {
			if ( debuglevel > 5 ) 
				fprintf( stderr, "pcmail: calling sendone %s\n",
							*argvec ); 
							
			sendone( argc, argv, *argvec, FALSE );
		}
		
	}
	/* dump remotes if necessary */
	if ( strlen( remotes ) > 0 ) 
		sendone( argc, argv, remotes, TRUE );

#ifndef RMAIL

	mkfilename( mailsent, home, COPYFILE );
	if ( debuglevel > 4 )
	   fprintf( stderr, "pcmail: copfile = %s\n", mailsent );
	sendone( argc, argv, mailsent, FALSE );

#endif

	unlink( tfilename ); 
	chdir( mcurdir );
	exit(0);
}
 
 
char fpat1[] = "%c.%.7s%04ld";
char fpat2[] = "S %s %s %s - %s 0666 %s";


/* sendone copies file plus headers to appropriate postbox
   NB. we do headers here to allow flexibility later, for example
   in being able to do bcc, per host service processing etc.
*/
sendone( argc, argv, address, remote )
char **argv;
int argc;
char *address;
{
	register char 	*cp;
	char	icfilename[32];		/* local C. copy file */
	char	ixfilename[32];		/* local X. xqt file */
	char	idfilename[32];		/* local D. data file */
	char	rxfilename[32];		/* remote X. xqt file */
	char	rdfilename[32];		/* remote D. data file */
 	char	tmfilename[32];		/* temporary storage */

 	if ( remote ) {
 		/* sprintf all required file names */
		sprintf( tmfilename, fpat1, 'C', mailserv, sequence );
		importpath( icfilename, tmfilename );
		sprintf( tmfilename, fpat1, 'D', mailserv, sequence );
		importpath( idfilename, tmfilename );
		sprintf( tmfilename, fpat1, 'D', nodename, sequence );
		importpath( ixfilename, tmfilename );
		sprintf( rdfilename, fpat1, 'D', nodename, sequence );
		sprintf( rxfilename, fpat1, 'X', nodename, sequence );
 	}
 	else {
		/* postbox file name */
 		if ( index( address, SEPCHAR ) == (char *)NULL )
			mkfilename( idfilename, maildir, address );
		else
			strcpy( idfilename, address );
	}
 
	if ( debuglevel > 5 ) 
 		fprintf( stderr, "pcmail: sendone: %s\n", idfilename );
 
 	if ( remote == FALSE ) {
 	   if ( debuglevel > 5 ) 
 	      fprintf( stderr, "pcmail: sendone: check for remote\n" );
		/* check for forwarding */
		if ( (mailfile = FOPEN( idfilename, "r", 'b' )) != (FILE *)NULL ) {
			cp = fgets( buf, BUFSIZ, mailfile );
			fclose( mailfile );
			if (cp != (char *)NULL)
				if (strncmp( buf, FORWARD, 10 ) == 0) {
					strcpy( buf, buf+11 );
					return( sendone( argc, argv, buf, FALSE ) );
				}
		}
	}
 	
	/* open mailfile */
	if ( (mailfile = FOPEN( idfilename, "a", 'b' )) == (FILE *)NULL ) {
		fprintf( stdout, "pcmail: cannot append to %s\n", idfilename );
		return( 0 );
	}

	if ( debuglevel > 5 ) 
		fprintf( stderr, "pcmail: append to mailfile\n" );

	tloc = time( (long *)NULL );
	thetime = ctime(&tloc);
 	(void)strcpy(chartime, thetime);	/* make our own copy */
 	thetime = chartime;	/* and work with our own copy */
	thetime[strlen(thetime)-1] = '\0';

#ifdef RMAIL
	fprintf( mailfile, "From uucp %s", thetime );
	fputc( '\012', mailfile );
	fprintf( mailfile, "Received: by %s (pcmail) %s", domain, thetime );
	fputc( '\012', mailfile );
#else RMAIL
	fprintf( mailfile, "From %s %s", mailbox, thetime );
	if ( remote )
		fprintf( mailfile, " remote from %s", nodename );
	fputc( '\012', mailfile );
	fprintf( mailfile, "Received: by %s (pcmail) %s", domain, thetime );
	fputc( '\012', mailfile );
	fprintf( mailfile, "Date: %s", thetime );
	fputc( '\012', mailfile );
	/* add Date:, From: and Message-ID: headers */
	fprintf( mailfile, "From: %s <%s@%s>", name, mailbox, domain );
	fputc( '\012', mailfile );
	fprintf( mailfile, "Message-ID: <%ld@%s>", sequence, domain );
	fputc( '\012', mailfile );
	/* add To: headers */
	while (--argc > 0) {
		fprintf( mailfile, "To: %s", *++argv );
		fputc( '\012', mailfile );
	}
	if ( strlen( Subject ) > 0 ) {
		fprintf( mailfile, "Subject: %s", Subject );
		fputc( '\012', mailfile );
	}
#ifdef PCMAIL 
	/* add Message-Lines: and Content-Length: headers */
	fprintf( mailfile, "X-Message-Lines: %ld", lines ); 
	fputc( '\012', mailfile );
	fprintf( mailfile, "Content-Length: %ld", bytes ); 
	fputc( '\012', mailfile );
#endif PCMAIL
#endif RMAIL

	/* copy tempfile to postbox file */
	if (debuglevel > 4)
	   fprintf( stderr, "pcmail: copy tempfile %s to %s\n",
	                    tfilename, idfilename );
	tempfile = FOPEN( tfilename, "r", 'b' );
	if ( tempfile == (FILE *)NULL) {
		fprintf( stdout, "pcmail: can't re-open %s\n", tfilename );
		return( 0 );
	}
	while (fgets( buf, 512, tempfile ) != (char *)NULL) {
		if ( strncmp( buf, "From ", 5 ) == 0 )
			fputc( '>', mailfile );
		cp = &buf[ strlen(buf)-1 ];
		if ( *cp == '\n' )
			*cp = '\0';
		fputs( buf, mailfile );
		fputc( '\012', mailfile );
 	}
 	
	/* close files */
	fclose( mailfile );	
	fclose( tempfile );

	/* all done unless going to remote via uucp */
	/* must create the job control files */
	if ( remote == TRUE ) {

		/* create remote X xqt file */
		mailfile = FOPEN( ixfilename, "w", 'b' );
		if 	(mailfile == (FILE *)NULL) {
			fprintf( stdout, "pcmail: cannot append to %s\n", ixfilename );
			return( 0 );
		}
		fprintf( mailfile, "U %s %s", uucp, nodename );
		fputc( '\012', mailfile );
		fprintf( mailfile, "F %s", rdfilename );
		fputc( '\012', mailfile );
		fprintf( mailfile, "I %s", rdfilename );
		fputc( '\012', mailfile );
		fprintf( mailfile, "C rmail %s", address );
		fputc( '\012', mailfile );
		fclose( mailfile );

		/* create local C copy file */
		mailfile = FOPEN( icfilename, "w", 't' );
		if 	(mailfile == (FILE *)NULL) {
			fprintf( stdout, "pcmail: cannot append to %s\n", icfilename );
			return( 0 );
		}
		
		fprintf( mailfile, fpat2, idfilename, rdfilename,
					uucp, idfilename, uucp );
		fputc( '\012', mailfile );
		fprintf( mailfile, fpat2, ixfilename, rxfilename,
					uucp, ixfilename, uucp );
		fputc( '\012', mailfile );
		fclose( mailfile );
		
	} /* if ( remote == TRUE ) */
	
	return( 1 );
}
 
#ifndef AMIGA
#ifdef RMAIL
rnews(argc, argv)
int argc;
char *argv[];
{
	struct tm	*thetm;
	char	filename[132];
	char	format[128];
	FILE 	*f;
	char	buf[BUFSIZ];
	
	static int count = 0;
	
	tloc = time( (long *)NULL );
	thetime = ctime(&tloc);
	tloc = time( (long *)NULL );

	thetm = localtime( &tloc );

	/* mkfilename( format, spooldir, NEWSDIR );	*/
	sprintf( filename, NEWSDIR,
		thetm->tm_year % 100, thetm->tm_mon,
		thetm->tm_mday, thetm->tm_hour,
		thetm->tm_min,  thetm->tm_sec,  count
		);

	count++;
	
	if ( debuglevel > 5 )
		fprintf( stderr, "rnews: %s\n", filename );
	
	if ( (f = FOPEN( filename, "w", 't' )) == (FILE *)NULL ) {
		fprintf( stderr, "rnews: can't open %s %d\n", filename, errno );
		return( -1 );
	}

	while ( fgets( buf, BUFSIZ, stdin ) != (char *)NULL ) 
		fputs( buf, f );

	fclose( f );
}

#endif RMAIL
#endif AMIGA

