/*
 *	mail.c
 */

#define	exit	return

#include <stdio.h>
#include "host.h"

FILE *FOPEN();
FILE *freopen();

int	debuglevel = 1;

#define LSIZE   	256

char	line[LSIZE];
char	resp[LSIZE];

char	mfilename[132];

struct ldesc {
   int   	delete;		/* status of this message */
   long		adr;		/* address of From line */
   long		date;		/* address of Date: line */
   long		subject;	/* address of Subject: line */
   long		from;		/* address of From: line */
   long		size;		/* number of lines */
};

struct	ldesc letters[300];

int   	letternum   = 0;
char   	thefilename[50];

char   	tmailbox[64];
char 	tmailbag[64];


FILE   	*fmailbox;
FILE 	*rmailbox;
FILE	*fmailbag;

int	error = 0;
int	modified;

int	printonly;

int	PageCount = 0;

mailmain(argc, argv)
char **argv;
{
   
	/* HOSTINIT;
	loadenv(); */

	mkfilename( tmailbox, tempdir, "mailbox");
	mkfilename( tmailbag, tempdir, "mailbag");

	unlink( tmailbox );

	if ( mailbox == (char *)NULL ) 
		mailbox = "???";
	
	if ( argc == 1 || 
		( argv[1][0] == '-' ) && ( argv[1][1] != 's' ))
		showmail (argc, argv );
	else
		lmail (argc, argv );

	finis();
	
}

finis()
{
	if ( fmailbag != (FILE *)NULL) fclose( fmailbag );
	unlink( tmailbox );
	unlink( tmailbag );
	exit( error );
}

/*	sendmail
	send message n to "line"
*/
sendmail( n, line )
{
	char 	*argv[50];
	int 	argc;
	char	buf[BUFSIZ];
	long 	bytes;

	/* open a temporary file */
	fmailbag = FOPEN( tmailbag, "w", 'b' );

	/* copy nth message to mailbag file */
	fseek( fmailbox, letters[ n ].adr, 0 );
	bytes = letters[ n+1 ].adr - letters[ n ].adr;

	while( bytes > 0 && fgets( buf, BUFSIZ, fmailbox) ) {
		fputs( buf, fmailbag  );
		bytes -= strlen( buf );
	}

	fclose( fmailbag );

	/* use mailbag as stdin to mail delivery */
	fclose( stdin );
	FILEMODE( 'b' );
	if ( freopen( tmailbag, "r", stdin ) != (FILE *)NULL ) {
		argc = getargs( line, argv );

		lmail( argc, argv );

		fclose( stdin );
	}
	FILEMODE( 't' );
	freopen( device, "r", stdin );

	/* get rid of mailbag */
	unlink( tmailbag );
}


invert( i )
{
	return( letternum - i - 1 );
}

showmail(argc, argv)
char **argv;
{
	int flg, i, j, k, print;
	char *p, *cp, *getnext();
	long nextadr;
	struct ldesc *letter;

	/* get mailbox file name */
	mkfilename( mfilename, maildir, mailbox );

	/* parse arg's */
	for (; argc > 1; argv++, argc--) {
	   if ( argv[1][0] == '-' ) {
	      if ( argv[1][1] == 'f' ) {
	         if ( argc >= 3) {
	            if ( argv[2][0] == '=' )
	               mkfilename( mfilename, maildir, &argv[2][1] );
	            else
	               strcpy( mfilename, argv[2] );
	         argv++;
	         argc--;
	         }

	      } else if ( argv[1][1 ]== 'p' ) printonly++;
	   else {
	      fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
	      finis();
	   }
	   } else break;
	}

	
	 
	/* open real mailbox file */
	if (( rmailbox = FOPEN( mfilename, "r", 'b' ))  == (FILE *)NULL) {
		fprintf( stdout, "No mail in %s.\n", mfilename );
		return;
	}

	/* open up tmp mailbox file */
  	if (( fmailbox = FOPEN( tmailbox, "w", 'b' )) == (FILE *)NULL ) {
		fprintf( stderr, "mail: cannot open %s for writing\n", tmailbox );
		finis();
	}
   

	/* copy real mailbox file to tmp mailbox file */
	letternum = 0 ;
	nextadr = 0;
	while ( fgets(line, LSIZE, rmailbox ) != (char *)NULL) {
		fputs( line, fmailbox );
	
		if ( strncmp( line, "From ", 5 ) == SAME ) {
			letter = &letters[letternum++];
			letter->from = 
			letter->subject =
			letter->date = -1L;
			letter->adr = nextadr;
			letter->delete = FALSE;
			letter->size = 0L;
		}else if ( strncmp( line, "Date: ", 6 ) == SAME )
			letter->date = nextadr;
		else if ( strncmp( line, "From: ", 6 ) == SAME )
			letter->from = nextadr;
		else if ( strncmp( line, "Subject: ", 9 ) == SAME )
			letter->subject = nextadr;
		
		letter->size += 1L;
		nextadr += strlen( line );
	}
	
	letters[letternum].adr = nextadr;   /* last plus 1 */

	/* close mailbox files */
	fclose( rmailbox );
	fclose( fmailbox );

	fmailbox = FOPEN( tmailbox, "r", 'b' );

	modified = 0;

	if ( printonly ) {
		j = letternum;
		while ( j > 0 ) {
			pager( j );
			j--;
		}

		return;
     }

    
	printsub( -1 );
	
	i = letternum - 1;
	while ( TRUE ) {

		if ( i < 0 )
			i = 0;
		if ( i >= letternum)
			i = letternum - 1;
		j = invert( i );
		
		fprintf( stdout, "%d ? ", invert( i ) );
		
		if ( fgets( resp, LSIZE, stdin) == (char *)NULL )
			break;
					
		switch ( resp[0] ) {
		default:
			fprintf(stderr, "usage\n");
		case '?':
			print = 0;
			fprintf( stderr, "q\tquit\n" );
			fprintf( stderr, "x\texit\tmailbox restored\n" );
			fprintf( stderr, "p\tprint message\n" );
			fprintf( stderr, "s[file]\tsave message to a file (default =mbox)\n" );
			fprintf( stderr, "w[file]\ttsave message to a file (default =mbox) without header\n" );
			fprintf( stderr, "-\tprint last message\n" );
			fprintf( stderr, "d\tdelete current message\n" );
			fprintf( stderr, "+\tnext message (no delete)\n" );
			fprintf( stderr, "f user\tforward current message to user\n" );
			fprintf( stderr, "m user\tmail a message to user\n" );
			fprintf( stderr, "g num\t set current message\n" );
			break;
		case '+':
		case 'n':
			i-- ;
			break;
		case 'g':
			i = invert( atoi( resp+2 ) );
			break;
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			i = invert( atoi( resp ) );
			break;		
		
		case 'x':
			modified = 0;
		case 'q':
			goto donep;
		case '\n':
		case 'p':
			pager( j );
			break;
		case '^':
		case '-':
			i++;
			break;
		case 'y':
		case 'w':
		case 's':
			flg = 0;
			if (resp[1] != '\n' && resp[1] != ' ') {
				printf("illegal\n");
				flg++;
				print = 0;
				continue;
			}
			if (strlen( resp ) == 1)
				strcat( resp, " =mbox" );
			for (p = resp+1; (p = getnext( &cp, p )) != (char *)NULL; ) {
			   if ( *cp == '=' )
	                      mkfilename( thefilename, maildir, ++cp );
			   else
			      strcpy( thefilename, cp );
			   fprintf( stderr, "%s to %s\n", 
			   		(resp[0] == 's') ? "Appending":"Writing", thefilename );
			   if (( fmailbag=FOPEN( thefilename, "a", 't' )) == (FILE *)NULL ) {
			      fprintf( stdout, "mail: cannot append to %s\n",
			               thefilename );
			   flg++;
			   continue;
			   }
			   copymsg( j, fmailbag, resp[0]=='w' );
			   fclose( fmailbag );
			}
			if (flg)
				print = 0;
			else {
				letters[j].delete = TRUE;
				modified++;
				i--;
			}
			break;
		case 'm':
			fprintf( stderr, "mail command not implemented yet!\n" );
			break;
		case 'f':
			flg = 0;
			if (resp[1] == '\n' || resp[1] == '\0') {
				i++;
				continue;
			}
			if (resp[1] != ' ') {
				printf( "invalid command\n" );
				flg++;
				print = 0;
				continue;
			}

			sendmail( j, p );
			
			if (flg)
				print = 0;
			else {
				letters[j].delete = TRUE;
				modified++;
				i++;
			}
			break;

		case 'd':
			letters[j].delete = TRUE;
			modified++;
			i--;
			if (resp[1] == 'q')
				goto donep;
			break;

		case 'h':
			printsub( -1 );
			break;

		case 'H':
			printsub( i );
			break;

		}
			
	}
	donep:
	if ( modified )
		copyback();
}

readaline( adr, line )
long adr;
char *line;
{
	char 	buf[132];
	char	*cp;
	
	*line = '\0';
	if ( adr != -1L )
		if ( fseek( fmailbox, adr, 0 ) == 0 ) 
			if ( fgets( buf, 132, fmailbox ) != (char *)NULL )
				strcpy( line, buf );

	if ( (cp = index( line, '\n' ) ) != (char *) NULL)
		*cp = '\0';
}


/*
returnaddress()
{
	readaline( lp->from, line );
	if ( 
		( i = index( line, '<' )) != 0 && 
		( k = index( line, '>')) != 0 &&
		( k > i )
		) 
	{
		k -= i;
		strncpy( from, line[i], k );
		from[k] = '\0';
	}
	else {


	}
}
*/

printsub( K )
{
	struct ldesc	*ld;
	int		j;
	char	from[132], subject[132], date[132], line[132];
	register char	*sp, *dp, *lp, *tp;
	int k, mink, maxk;

	pagereset();
	
	if ( K == -1 ) {
		maxk = letternum -1;
		mink = 0;
	}
	else 
		maxk = mink = K;
		
	for ( k = maxk ; k >= mink ; k-- ) {
	
		j = invert( k );
		ld = & letters[ j /*k*/];
	
 		(void)strcpy(from, "unknown");	/* default to "unknown" */
		readaline( ld->from, line );
		if ( strlen( line ) > 0 ) {
			/* Assume From: mailbox@site.domain */
			/* get first usable stuff after From: */
			sp = index( line, ':' ) + 1;
	
			/* do we have From: mailbox@site.domain ( Proper Name ) */
			if ( ( ( tp = index( line, '(' )) != (char *) NULL && 
					( lp = index( line, ')')) != (char *) NULL  ) )
				sp = ++tp;
			/* or we may have From: Proper Name < mailbox@site.domain > */
			else
				lp = index( line, '<');
	
			if ( *lp == '<' || *lp == ')' )
				--lp;
			
			/* if we didn't get either of the last two, just grab line */
			if ( lp < sp || lp == (char *) NULL )
				lp = line + strlen( line ) - 1;
	
			/*debugMsg("\PCheck isspace *sp");*/
			while ( isspace( *sp ) ) sp++;
	
			/*debugMsg("\PCheck isspace *lp");*/
			while ( isspace( *lp ) ) lp--;
	
			dp = from;
			while ( sp <= lp ) *dp++ = *sp++;
			*dp = '\0';
		}
		
		/* Date: Wed May 13 23:59:53 1987 */
 		*date = '\0';	/* default date to null */
		readaline( ld->date, date );
		if ( strlen( date ) > 0 ) {
			sscanf( date, "%*s %*s %s %s", line, subject );
			sprintf( date, "%s %s", line, subject );
		}
	
		strcpy( subject, "--- no subject ---" );
		readaline( ld->subject, line );
		if ( strlen( line ) > 0 ) {
			sp = line;
			while ( !isspace( *sp ) ) sp++;
			while ( isspace( *sp ) ) sp++;
			strcpy( subject, sp );
			} 
	
		from[20] = '\0';
		date[6] = '\0';
		subject[35] = '\0';
	
		sprintf( line, "%3d  %6s  %20s %35s (%6d)\n", 
						j, date, from, subject, ld->size );
		if ( pageline( line ) == TRUE )
			break;
	}
}


copyback()  
{
	register i, n, c;
	int new = 0;

	if (( fmailbag = FOPEN( mfilename, "w", 'b' )) == (FILE *)NULL ) {
		fprintf (stderr, "mail: can't rewrite %s\n", thefilename );
		finis();
	}
	n = 0;
	for ( i = 0; i < letternum; i++ )
		if ( letters[i].delete == FALSE ) {
			copymsg( i, fmailbag, FALSE );
			n++;
		}
	fclose (fmailbag );
}


/* copy a message
   if noheaders true, don't copy header lines
*/
copymsg( n, f, noheaders ) 
FILE *f;
{   
	long 	bytes;
	char	buf[BUFSIZ];
	
	fseek( fmailbox, letters[n].adr, 0 );
	bytes = letters[n+1].adr - letters[n].adr;

	while ( bytes > 0 && fgets( buf, BUFSIZ, fmailbox ) != (char *)NULL ) {
		bytes -= strlen( buf );

		/* reset header
		if ( noheaders  && strcmp( buf, "\n") == SAME )
			noheaders  = FALSE;

		/* write line */
		if ( !noheaders  )
			fputs( buf, f );
			
	}
}

pager(n) 
{   
	long 	bytes;
	char	buf[BUFSIZ];
	
	fseek( fmailbox, letters[n].adr, 0 );
	bytes = letters[n+1].adr - letters[n].adr;

	pagereset();
	while ( bytes > 0 && fgets( buf, BUFSIZ, fmailbox ) != (char *)NULL ) {
		bytes -= strlen( buf );
		if ( pageline( buf ) == TRUE )
			break;
	}

	pageline( "\n" );
}

pagereset()
{
	PageCount = 0;
}

pageline( s )
char * s;
{
	char c;
	
	fputs( s, stdout );
	if ( ++PageCount > 24 ) {
		PageCount = 0;
		c = get_one();
		switch( c ) {
		case 'q':
		case 'Q':
		case '\003':
		case 'x':
		case 'X':
			return( TRUE );
		}
	}
	return( FALSE );
}

char *getnext( s, p )  
register char **s, *p;
{
	*s = (char *)NULL;
	while ( *p == ' ' || *p == '\t' )
		p++;
	if ( *p == '\n' || *p == '\0' )
		return( (char *)NULL );
	*s = p;
	while ( *p != ' ' && *p != '\t' && *p != '\n' && *p != '\0' )
		*p++;
	if ( *p != '\0' )
		*p++ = '\0';
	return(p);
}



