/*
 *			M S G 5 . C
 *
 * Functions -
 *	setup		read mailbox file
 *	newmessage	notice & read new mail
 *	overwrit	remove deleted messages from a file by overwriting
 *	undigestify	process an undigestify command
 *	nambinary	build path name for binary parallel file
 *	binbuild	Write out a fresh binary parallel file
 *	binupdate	Update one record of the binary file
 *	binheaderupdate	Update the header of the binary file
 *
 *
 *		R E V I S I O N   H I S T O R Y
 *
 *	09/13/82  MJM	This module split off from msg1.c, to even
 *			the sizes and ease editing.
 *
 *	09/22/82  MJM	Added in most of the support for the parallel
 *			binary map file.
 *
 *	03/16/83  MJM	Added binary update routines, neatened manipulation
 *			of binary box overall.  Faster, too!
 *
 *	11/10/83  DPK	Added Steve Kille (SEK) continuation line fix.
 *
 *	07/15/84  HAW	Made binarybox and memory structures identical.
 *			Added readonly mode.
 */

#include "util.h"
#include "mmdf.h"
#include <pwd.h>
#include <signal.h>
#include <sys/stat.h>
#include "./msg.h"
#ifdef V4_2BSD
#include <sys/file.h>
#include <strings.h>
#else V4_2BSD
#include <string.h>
#endif V4_2BSD

#ifndef V4_2BSD
sigtype	(*oldhup)();
sigtype	(*oldintr)();
sigtype	(*oldquit)();
#endif

#ifndef W_OK
#define	W_OK 2
#endif

extern FILE *lk_fopen();

/*
 *			S E T U P
 *
 *	This function is called to scan the contents of the mailbox.
 */
setup( setflg)
int     setflg;
{
	char    line[LINESIZE];
	char	name[LINESIZE];
	char	mbox[LINESIZE];
	char    datestr[M_BSIZE];	/* where to save Date field */
	char	fromstr[M_BSIZE];	/* where to save From field */
	char	sndstr[M_BSIZE];	/* where to save Sender field */
	char	tostr[M_BSIZE];		/* where to save To field */
	char	subjstr[M_BSIZE];	/* where to save Subj field */
	char	curhdr[M_BSIZE];	/* Scratch for gothdr() */
	char	digsubject[SIZESUBJ];	/* Scratch for undigest function */
	char	*cpy, *cpz;
	int	needscan;
	unsigned int     inmsg;
	unsigned int    count;
	long    newpos;
	long    curpos;
	int     oldflag = 0;
	int	oldsig;
	static int i;		/* String index */

	needscan = inmsg = 0;

	switch( setflg )  {

	case SETAPND:
		status.ms_time = statb2.st_mtime;
		fseek( filefp, status.ms_eofpos, 0);
		newpos = status.ms_eofpos;
		break;

	case SETREAD:
		if( filefp != NULL)  {
			++oldflag;
			fclose( filefp);
		}
		if( (filefp = fopen( filename, "r")) == NULL)  {
			printf( "can't open '%s'\r\n", filename);
			if( oldflag)  {
				strcpy( filename, oldfile);
				filefp = fopen( filename, "r");
			}
			error( "");
		}
		if( binfp != (FILE *)NULL ) {
		        lk_fclose( binfp, binarybox, (char *)0, (char *)0);
			binfp = (FILE *)NULL;
		}

		fstat( fileno( filefp), &statb1);

		if( statb1.st_size == 0 ) {		/* No mail - exit */
			if( quickexit == ON ) {
				printf("%s is empty!\n",filename);
				tt_norm();
				exit(0);
			}
		}

		status.ms_time = statb1.st_mtime;
		if( (statb1.st_mode & S_IFMT) != S_IFREG)
			error( "File is not a regular file.\r\n");

		if( access( filename, W_OK ) < 0 ) {
			printf(" Unable to write %s - READONLY mode\r\n",filename);
			readonly = TRUE;
		}

		/* Set flags if this is the default mail file */
		mainbox();

		/* Build the name of the binary mail index file */
		nambinary( filename );

		if( (binfp = fopen( binarybox, "r" )) != NULL )  {

#ifndef V4_2BSD
			oldhup = signal(SIGHUP,SIG_IGN);
			oldintr = signal(SIGINT,SIG_IGN);
			oldquit = signal(SIGQUIT,SIG_IGN);
#else
			oldsig = sigsetmask(SPSIGS);
#endif
			binaryvalid = FALSE;

			/* Load binary map first */
			if( bprint == ON ) {
				printf("Loading binary box %s ", binarybox );
				fflush( stdout );
			}
			/* Read header */
			fread( &status, sizeof(struct status), 1, binfp );

			/* Quick hack - change from OLDIDENTITY to
			 * IDENTITY can be done by msg */
			if( status.ms_ident == OLDIDENTITY ) {
				rewind(binfp);
				fread( &status, sizeof(struct oldstatus),
					1, binfp );
				status.ms_markno = 0;
				/* binbuild will be called below */
			} else if( status.ms_ident != IDENTITY )  {
				tt_norm();
				printf("\n\nBinary file version error.");
				printf("  file=%x, program=%x\n", status.ms_ident, IDENTITY );
				printf("This version of msg uses a new binary file which is not compatible\n");
				printf("with the old version. You may either delete the binary\n");
				printf("file %s and restart msg\n", binarybox );
				printf("or use the old version of msg. Deleting the binary file\n");
				printf("will destroy the old status flags but no mail will be lost.\n");
 				printf("The old version may still be used by typing msg.bak but may disappear\n");
				printf("soon so plan to convert to the new version as soon as possible.\n");

				exit(10);
				/* NOTREACHED */
			}

			/* Read data */
			for( i = 0; i < status.ms_nmsgs; i++ )  {
				if( (msgp[i] = (struct message *) malloc(sizeof(struct message)) ) == NULL ) {
					status.ms_nmsgs = i-1;	
					nomem();
					/* NOTREACHED */
				}

				if(fread( msgp[i], sizeof(struct message), 1, binfp ) != 1) {
					tt_norm();
					printf("\nThe binary box is corrupted.\n");
					printf("rm %s and retry 'msg'.\n", binarybox);
					exit(11);
				}

				if( bdots == ON && bprint == ON ) {
					putchar('.');
					fflush(stdout);
				}
			}
			/* Quick check of binary box integrity:
			 * check for delimiters in last message */
			fseek( filefp, status.ms_eofpos-strlen( delim2 ), 0 );
			if( ( xfgets( line, 2+strlen( delim2 ), filefp ) == NULL )
			    || (strequ( line, delim2 ) == FALSE ))  {
				tt_norm();
				printf("\nThe binary box is corrupted.\n");
				printf("rm %s and retry 'msg'.\n", binarybox);
				exit(11);
			}
			
			if( bprint == ON ) {
				printf(" - Done\r\n");
				fflush( stdout );
			}

			if( status.ms_ident == OLDIDENTITY ) {
				printf("Rebuilding binary box\r\n");
				binbuild();
			}

			/* Proceed with appending the rest of the messages */
			newpos = status.ms_eofpos;

			fclose( binfp );
			binfp = (FILE *)NULL;
			binaryvalid = TRUE;
#ifndef V4_2BSD
			signal(SIGHUP,oldhup);
			signal(SIGINT,oldintr);
			signal(SIGQUIT,oldquit);
#else
			sigsetmask(oldsig);
#endif

			/* Fall through to read any new messages */
			setflg = SETAPND;	/* to get "new" flags */

		}  else  {

			printf( "Reading %s ", filename);
			fflush( stdout);

			status.ms_curmsg = 0;		/* Global */
			status.ms_nmsgs = 0;		/* Global */
			newpos = status.ms_eofpos = 0;

			if( readonly == FALSE )
				if( (i = creat( binarybox, sentprotect )) < 0 )  {
					printf("Unable to create %s - READONLY mode\r\n", binarybox );
					readonly = TRUE;
				}
				else
					close(i);
		}

		if( readonly == FALSE ) {
			/* get exclusive control of file */
			if (access(binarybox, W_OK) < 0 ) {
				printf("Can't write %s - READONLY mode\n",binarybox);
				readonly = TRUE;
			}
			else if ((binfp = lk_fopen(binarybox, "r+", (char *)0,
  					     (char *)0, 5)) == (FILE *) NULL) {
				printf("%s busy - READONLY mode\n",binarybox);
				readonly = TRUE;
			}
		}
		break;

	case SETUNDIGEST:
		fseek( filefp, mptr->start, 0);
		newpos = mptr->start;
		strncpy( digsubject, mptr->subject, SIZESUBJ );
		break;

	default:
		error( "Bad setup()" );
	}

	fseek( filefp, newpos, 0 );
	while( xfgets( line, sizeof( line), filefp) != NULL)  {
		curpos = newpos;
		count = strlen( line);
		newpos += count;

		/*
		 * Check for Message Separators  (Two types)
		 */
		if( strequ( line, delim1) || strequ( line, delim2))  {
			if( setflg == SETUNDIGEST )
				return;
			if( inmsg != 0 )  {
				/* wants message NUMBER */
				binupdate( (int)status.ms_nmsgs );
				status.ms_eofpos = newpos;
			}
			inmsg = 0;
			continue;
		}

		if(
			setflg == SETUNDIGEST &&
			strncmp( line, "--------------------", 20 ) == 0
		)  {
			inmsg = 0;
			continue;
		}

		/*
		 * Note each new message.  If we are not in a message, and
		 * a line of non-separator has been found, start off a new
		 * message.
		 */
		if( inmsg == 0)  {
			if( mdots == ON ) {
				putchar( '.' );
				fflush( stdout);
			}
			/* Clear out header scan area */
			datestr[0] =
			    fromstr[0] =
			    sndstr[0] =
			    tostr[0] =
			    subjstr[0] = '\0';
			curhdr[0] = '\0';	/* SEK continuation fix! */

			/* scan off leading blank lines */
			while( count == 1)  {
				xfgets( line, sizeof( line), filefp);
				curpos = newpos;
				count = strlen( line);
				newpos += count;
			}

			/* Build new table entry */
			if( status.ms_nmsgs >= Nmsgs)  {
				printf("More than %d messages in file.\r\n", Nmsgs);
				status.ms_nmsgs--;
				nomem();
				/* NOTREACHED */
			}

			/*
			 * Allocate a new msgp slot, either at the end of the
			 * messages, or in the middle, depending.
			 */
			if( setflg != SETUNDIGEST )  {
				if( (mptr = msgp[status.ms_nmsgs++] = (struct message *) malloc(sizeof(struct message)) ) == NULL ) {
					status.ms_nmsgs--;
					nomem();
					/* NOTREACHED */
				}
				mptr->flags = 0;
			}  else  {
				/*
				 * scrunch down.
				 *   msgno is current message NUMBER
				 *   status.ms_nmsgs is last message NUMBER.
				 * offsets are one less than numbers.
				 */
				if( (mptr = msgp[status.ms_nmsgs] = (struct message *) malloc(sizeof(struct message)) ) == NULL ) {
					error("Out of memory - operation aborted\n");
					/* NOTREACHED */
				}
				
				for( i = status.ms_nmsgs-1; i >= msgno; i-- )  {
					msgp[i+1] = msgp[i];
				}
				status.ms_nmsgs++;
				msgp[ msgno++ ] = mptr;
				mptr->flags = M_NEW;
			}

			mptr->start = curpos;
			mptr->len = 0L;
			mptr->date = 0L;
			mptr->from[0] = mptr->datestr[0] = mptr->subject[0] = mptr->to[0] = '\0';

			needscan = 1;
			inmsg++;
		}
		mptr->len += count;

		if( count == 1 && needscan)  {
			/*
			 * Blank line found while reading header.
			 * Digest header information and store results
			 * into msgp[] structure entry.
			 */

			/* Process date field( if any) */
			if( !isnull( datestr[0])) {
				if( (mptr->date = smtpdate( datestr )) != -1L)
					makedate( &mptr->date, mptr->datestr);
			}

			/* Process to field ( if any ) */
			if( !isnull( tostr[0] ) ) {
				strncpy( mptr->to, tostr, SIZETO );
				mptr->to[SIZETO-1] = '\0';
			}

			/* Process from field( if any) */
			if( !isnull( fromstr[0]))  {
				parsadr( fromstr, name, mbox, (char *)0);

				if( prefix( username, mbox) && !isnull( tostr[0]))  {
					/* sender was self */
					parsadr(tostr, name, mbox,( char *) 0);
					if( !isnull( name[0]))
						sprintf( fromstr, "To: %s%c", name, '\0');
					else
						sprintf( fromstr, "To: %s%c", mbox, '\0');
				}  else  {
					if( !isnull( name[0]))
						strncpy(fromstr,name,SIZEFROM);
					else
						strncpy(fromstr,mbox,SIZEFROM);
				}
				mptr->from[SIZEFROM-1] = '\0';
				/* Try to eliminate UUCP prefixes */
				{
					register char *cp;
					char * indent;

					indent = cp = fromstr;
					while( *cp )
						if( *cp++ == '!' )
							indent = cp;

					strncpy(mptr->from,indent,SIZEFROM-1);
				}

				mptr->flags |= M_NEW;
			}

			/* Process Subject field, if any */
			if( !isnull( subjstr[0]))  {
				subjstr[M_BSIZE-1] = '\0';
				if( (cpz = index(subjstr,'\n')) != 0 )
					*cpz = '\0';
				if( filoutflag == ON ) {
					for(cpz = subjstr,cpy = mptr->subject;
					    (*cpz != '\0') && (cpy - mptr->subject < SIZESUBJ);
					    cpz++ ) {
						if( *cpz < ' ' || *cpz == '\177' ) {
							*cpy++ = '^';
							*cpy++ = '@' + *cpz;
						}
						else
							*cpy++ = *cpz;
					}
					*cpy = '\0';
				}
				else
					strncpy( mptr->subject, subjstr, SIZESUBJ );
				mptr->subject[SIZESUBJ-1] = '\0';
			}

			/* Header scan complete */
			needscan = 0;
		}

		/* This line is part of the header -- scan it */
		if( needscan && line[0] != '\n' )  {
			gothdr( curhdr, "date:", line, datestr);
			gothdr( curhdr, "from:", line, fromstr);
			gothdr( curhdr, "sender:", line, sndstr);
			gothdr( curhdr, "To:", line, tostr);
			gothdr( curhdr, "subject:", line, subjstr);
		}
	}
	fstat( fileno( filefp), &statb1);
	status.ms_time = statb1.st_mtime;

	/*
	 * Check for having read a message while it was being delivered.
	 * Exclusive opens might be better, but for now...
	 */
	if( inmsg != 0 )  {
		printf("(partial message ignored) ");
		free( (char *) msgp[--status.ms_nmsgs]);
	}

	printf( " %d message%c total.\r\n", status.ms_nmsgs, status.ms_nmsgs == 1 ? ' ' : 's');

	/*
	 * rewrite entire binary file if we expanded the middle of the
	 * table with an undigestify operation.  SETREAD and SETAPND handled
	 * inside loop, with a binupdate() after each new message.
	 */
	if( readonly == FALSE ) {
		if( setflg == SETUNDIGEST )
			binbuild();
		else
			binheaderupdate();
		fflush( binfp );
	}
}

/*
 *			N E W M E S S A G E
 *
 * notice & include new mail
 */
newmessage()
{
	/* Might also be useful to check the sizes */
	if( filefp == NULL ||
	    fstat( fileno( filefp), &statb2) < 0 ||
	    statb2.st_mtime == status.ms_time
	) {
		return;		/* nothing new */
	}
	printf( "Reading new messages ");
	setup( SETAPND );		/* incorporate appended messages */
}

/*
 *			V P U T M S G
 *
 * This routine gives a visual indication of each message being written
 * out, with one dot per message.  Makes the user feel better about the
 * often longish wait.
 *
 * This routine is really intended only for the use of the overwrite function,
 * as it records the NEW position of of the message in the file, to avoid
 * guesswork about message lengths in overwrite().
 */
vputmsg()
{
	long pos, ftell();
	char tbuf[1024];
	register int tt;
		
	if( mdots == ON ) {
		putchar('.');
		fflush( stdout );
	}

	fputs( delim1, outfp );

	pos = ftell( outfp );
	if( mptr->flags & M_RESTMAIL ) {
		/* Write the rest of the mail file */
		fseek(filefp, mptr->start, 0);
		while( (tt = fread(tbuf, sizeof(char), sizeof(tbuf), filefp)) == sizeof(tbuf) )
			fwrite(tbuf, sizeof(char), strlen(tbuf), outfp);
		fwrite(tbuf,sizeof(char), tt, outfp);
	}
	else {
		writmsg();
		fputs( delim2, outfp );
	}
	mptr->start = pos;
}

/*
 *			O V E R W R I T
 *
 * remove deleted messages from file.
 *
 * Note that vputmsg() above updates the message start position info.
 */
overwrit()
{
	static char tempfile[128];	/* build name of temporary file */
	unsigned int ndeleted;
	unsigned int i,ii;
	static char *ptr;
	register struct message **inp, **outp;	/* For mashing table */
	
	if( readonly == TRUE )
		error("READONLY mode - overwrite ignored\n");

	for( ndeleted = 0, i = status.ms_nmsgs; i-- != 0; ) {
		if( msgp[i]->flags & M_RESTMAIL )
			msgp[i]->flags &= ~M_DELETED;

		if( msgp[i]->flags & M_DELETED )
			ndeleted++;		/* how many dead messages */
	}
	
	if( ndeleted == 0)  {
		printf( "file unchanged, so not updated\r\n");
		return;
	}

	if( outmem == FALSE && stat( filename, &statb2) >= 0 && status.ms_time != statb2.st_mtime)  {
			/* Leave the processing to newmessage() */
			/* We can't just return here, because this is called
			 * from the "exit" command...
			 */
			error( "File updated since last read...\r\n");
	}

	/* get exclusive control of file */
	if( (exclfd = lk_open( filename, 1, (char *)0, (char *)0, 5))
	     < 0 && errno == ETXTBSY)  {
		printf( "'%s' busy; try later", filename);
		error( "\r\n");
	}

	if( ndeleted == status.ms_nmsgs)  {
		/*
		 *  All the messages are deleted.
		 *  Truncate (always if mailbox), otherwise delete
		 */
		printf("All messages deleted from %s.\r\n", filename );
		if( ismainbox)  {
			creat( filename, sentprotect);
			creat( binarybox, sentprotect );
		}  else  {
			printf( "delete %s", filename);
			/* for safety... */
			if( confirm((char *)0,DOLF))  {
				unlink( filename );
				unlink( binarybox );
			}
			else {
				creat( filename, sentprotect);
				creat( binarybox, sentprotect );
			}
		}
	}  else  {
		strcpy( tempfile, filename);
		/* get the path to directory of file  */
		if (ptr = rindex(tempfile, '/'))
			*++ptr = '\0';
		else
			ptr = tempfile;
		strcpy(ptr, tempname);
		mktemp(tempfile);

		if( (outfd = creat( tempfile, sentprotect)) < 0)
			error( "can't create temporary file\r\n");

		if( (outfp = fdopen( outfd, "w" )) == NULL )
			error( "can't fdopen temp file\n" );
		outfd = -1;

		/* save the undeleted messages */
		printf("OverWriting %s ", filename);
		unset();
		settype( 'u' );
		doiter( vputmsg );
		status.ms_eofpos = ftell(outfp);
		fclose( outfp );
		if( unlink( filename) < 0)
			error( "can't delete old file\r\n");
		if( link( tempfile, filename) < 0)  {
			printf( "can't rename temporary file '%s' to be '%s'.\r\n",
			tempfile, filename);
			error( "The temporary file still exists.\r\n");
		}
		unlink( tempfile);
	}
	if( exclfd >= 0 ) {
		lk_close( exclfd, filename, NULL, NULL);
		if( stat( filename, &statb2 ) >= 0 )
			status.ms_time = statb2.st_mtime;
	}

	/* Mash table down to reflect new file layout */
	inp = &msgp[0];
	outp = &msgp[0];
	ndeleted = 0;
	i = status.ms_curmsg;
	ii = status.ms_markno;
	for( msgno = 1; msgno <= status.ms_nmsgs; msgno++ )  {
	
		if( (*inp)->flags & M_DELETED )  {
			ndeleted++;
			free(*inp++);
			if( msgno < i )
				status.ms_curmsg--;
			if( msgno < ii )
				status.ms_markno--;
		}  else  {
			/* Note that position changes are done by vputmsg() */
			/*
			 * If the input and output slots are different,
			 * clean up the input slot.  (Else we clobber
			 * ourselves!).
			 */
			if( (*inp) != (*outp) )  {
				*outp = *inp;
			}
			inp++;
			outp++;
		}
	}

	/* Adjust current message so as not to run off end */
	status.ms_nmsgs -= ndeleted;
	if( status.ms_curmsg > status.ms_nmsgs )
		status.ms_curmsg = status.ms_nmsgs;

	if( status.ms_markno > status.ms_nmsgs )
		status.ms_markno = status.ms_curmsg;
		
	if( status.ms_nmsgs == 0 ) {
		status.ms_curmsg = 0;
		return;
	}

	fclose( filefp );
	if( (filefp = fopen( filename, "r" )) == NULL )
		error("Unable to re-open file");

	fstat( fileno( filefp ), &statb1 );
	status.ms_time = statb1.st_mtime;

	printf( " %d message%c total.\r\n", status.ms_nmsgs, status.ms_nmsgs == 1 ? ' ' : 's');

	if( outmem == TRUE ) {
		/* Alter the status struct so the rest of the msgs will
		 *  be recovered by newmessage()
		 */
		for( i = status.ms_nmsgs; i-- != 0; )
			if( msgp[i]->flags & M_RESTMAIL )
				status.ms_eofpos = msgp[i]->start;
		status.ms_nmsgs--;
		status.ms_time = 0;
	}

	/*
	 * At this point, the rest of the program should not even
	 * know that anything has happened.  Things should be in
	 * a good enough state that everything else works normally.
	 */
	/* Update the binary file */
	binbuild();
}

/*
 *			U N D I G E S T I F Y
 */
undigestify()
{
	/* mptr set by doiter for setup() */
	delmsg();
	setup( SETUNDIGEST );
}


/*
 *			N A M B I N A R Y
 *
 * Build the name of the associated binary file, and save the name
 * in the string "binarybox".
 */
nambinary( arg )
register char *arg;
{
	register char *sav, *cp;
	char ending[32];
	char fname[72];

	ending[0] = fname[0] = 0;
	strcpy( fname, arg );

	/* Find the last path component */
	sav = cp = fname;
	while( *cp )
		if( *cp++ == '/' )
			sav = cp;

	if( sav == fname )  {
		/* No slashes found in path name */
		sprintf( binarybox, "%s%s", binarypre, fname );
	}  else  {
		strcpy( ending, sav );
		*(sav-1) = 0;

		sprintf( binarybox, "%s/%s%s", fname, binarypre, ending );
	}
}

/*
 *			B I N B U I L D
 *
 * Rewrite the entire binary file, including the header.
 */
binbuild()
{
	static char tempfile[128];	/* build name of temporary file */
	register int i;
	char *ptr;
	int oldsig;

	if( readonly == TRUE )
		return;

	if( binfp != (FILE *) NULL ) {
		lk_fclose( binfp, binarybox, (char *)0, (char *)0 );
		binfp = (FILE *)NULL;
	}

	/* Don't bother making a new binary file if mailbox is empty */
	if( status.ms_nmsgs <= 0 )  {
		unlink( binarybox );
		return;
	}

#ifndef V4_2BSD
	oldhup = signal(SIGHUP,SIG_IGN);
	oldintr = signal(SIGINT,SIG_IGN);
	oldquit = signal(SIGQUIT,SIG_IGN);
#else
	oldsig = sigsetmask(SPSIGS);	/* Block all signals */
#endif
	strcpy( tempfile, binarybox);
	/* get the path to directory of file  */
	if (ptr = rindex(tempfile, '/'))
		*++ptr = '\0';
	else
		ptr = tempfile;
	strcpy(ptr, tempname);
	mktemp(tempfile);

	if( (i = creat( tempfile, sentprotect )) < 0 )
		error("Unable to create temporary file\r\n");

	if( (binfp = fdopen( i, "w" )) == NULL )
			error( "can't fdopen temp file\n" );

	if( bprint == ON ) {
		printf("Writing binary file:");
		fflush (stdout);
	}

	binheaderupdate();

	for( i=0; i < status.ms_nmsgs; i++ )  {
		fwrite( msgp[i], sizeof(struct message), 1, binfp );
		if( bdots == ON && bprint == ON ) {
			putchar( '.' );
			fflush( stdout );
		}
	}
	fclose( binfp );
	if( unlink( binarybox ) < 0)
			error( "can't delete old binarybox\r\n");
	if( link( tempfile, binarybox ) < 0)  {
		printf( "can't rename temporary file '%s' to be '%s'.\r\n",
			tempfile, binarybox);
		error( "The temporary file still exists.\r\n");
	}
	unlink( tempfile);

	if( (binfp = lk_fopen( binarybox, "r+", (char *)0, 
					  (char *)0, 5 )) == (FILE *) NULL )
		error("Can't re-open binary box\r\n");

	if( bprint == ON )
		printf(" done\r\n");
	fflush( stdout );
#ifndef V4_2BSD
	signal(SIGHUP,oldhup);
	signal(SIGINT,oldintr);
	signal(SIGQUIT,oldquit);
#else
	sigsetmask(oldsig);	/* restore signals */
#endif
}

/*
 *			B I N U P D A T E
 *
 * Update a single message in the binary box.
 * The number given is in the range 1...nmsgs.
 */
binupdate( number )
int number;
{
	long place;

	if( readonly == TRUE )
		return;

	if( number <= 0 || number > Nmsgs )
		printf("binupdate(%d): out of range\n", number);

	if( binfp == (FILE *) NULL )  {
		printf("binupdate: opening binary box\n");
		if( (binfp = lk_fopen( binarybox, "r+", (char *)0,
					  (char *)0, 5 )) == (FILE *) NULL ) {
			printf("binupdate: unable to open binary box");
			fflush(stdout);
			return;
		}
	}	

	place = (number-1) * sizeof(struct message) + sizeof(struct status);
	if( fseek( binfp, place, 0) < 0 )
		printf("binupdate: fseek error\n");

	fwrite( msgp[number-1], sizeof(struct message), 1, binfp );
}

/*
 *			B I N H E A D E R U P D A T E
 */
binheaderupdate()
{
	if( readonly == TRUE )
		return;

	/* Build header record */
	fseek( binfp, (long) 0, 0 );
	status.ms_ident = IDENTITY;
	fwrite( &status, sizeof(struct status), 1, binfp );
}

/*			N O M E M
 *  
 *  Recover gracefully when out of memory
 */
nomem() {

	struct message **sp;
	long ls;

	/* Find the last msg; not always the "last" one */
	ls = msgp[0]->start;
	for( sp = &msgp[1]; sp < &msgp[status.ms_nmsgs]; sp++ ) {
		if( (*sp)->start > ls ) {
			mptr = (*sp);
			ls = (*sp)->start;
		}
	}

	mptr->flags |= M_RESTMAIL;
	outmem = TRUE;
	printf("\n\007***********************************************\n");
	printf("\007Out of memory - Move or delete existing messages then overwrite\n");
	printf("Additional messages will appear after the overwrite!\n");
	error("\007***********************************************\n");
	/* NOTREACHED */
}

setmbox(file)
register char *file;
{
	strcpy(defmbox, file);
	strcpy(defoutfile, file);
	ismainbox++;
}

closeup(status)
register int status;
{
	if (binfp != (FILE *) NULL)
		if (readonly == TRUE)
			fclose(binfp);
		else
			lk_fclose(binfp, binarybox, (char *)0, (char *)0);
	exit(status);

	/* NOT REACHED */
}
