Subject: makesimtape long/int bug, mail can corrupt inbox (#408)
Index:	sys/pdpstand/makesimtape.c,bin/mail.c 2.11BSD

Description:
	On a PDP-11 "sizeof long != sizeof int".  The makesimtape
	program had 'int' where there should have been a 'long'.

	/bin/mail can leave the inbox corrupted if an error (disk full
	for example) occurs while appending a mail item to the inbox.

Repeat-By:
	Run makesimtape on a PDP-11 to create a tape image for use with
	Bob Supnik's simulator.  The end of file indicators will be corrupt
	and tape I/O will not function correctly.  Thanks go to Robin Birch
	for debugging and providing the fix.

	In the words of the person who found the bug and supplied the initial
	fix (thanks go to Megan Gentry):

	The problem which was occuring was that if a message was sent to a 
	user, and there was insufficient space to receive the entire message, 
	it was possible for a partial message to be delivered.  This in itself 
	isn't bad, except for the fact that a subsequent message will appear 
	to disappear since the partial message won't have a complete final 
	line... so the 'From xxx...' message for a new message doesn't go 
	on a line of it's own.

Fix:
	Cut where indicated and save to a file (/tmp/408).  Then:

		patch -p0 < /tmp/408
		cd /usr/src/bin
		make mail
		install -s -m 4751 -o root mail /bin/mail

		cd /sys/pdpstand
		make makesimtape

	That's all there is this time.  A small patch to start 1999 off.

	As always this and previous updates to 2.11BSD are available via
	anonymous FTP to either FTP.IIPO.GTEGSC.COM or MOE.2BSD.COM in the
	directory /pub/2.11BSD.

-------------------------------cut here---------------------------
*** /usr/src/sys/pdpstand/makesimtape.c.old	Mon Aug 11 20:21:11 1997
--- /usr/src/sys/pdpstand/makesimtape.c	Thu Dec 31 20:16:35 1998
***************
*** 1,5 ****
  /*
!  *	@(#)makesimtape.c	2.0 (2.11BSD) 1997/8/7
   *		Hacked 'maketape.c' to write a file in a format suitable for
   *		use with Bob Supnik's PDP-11 simulator (V2.3) emulated tape 
   *		driver.
--- 1,5 ----
  /*
!  *	@(#)makesimtape.c	2.1 (2.11BSD) 1998/12/31
   *		Hacked 'maketape.c' to write a file in a format suitable for
   *		use with Bob Supnik's PDP-11 simulator (V2.3) emulated tape 
   *		driver.
***************
*** 32,38 ****
  	int argc;
  	char *argv[];
  	{
! 	int i, j = 0, k = 0, zero = 0;
  	register char	*outfile = NULL, *infile = NULL;
  	FILE *mf;
  	struct	stat	st;
--- 32,39 ----
  	int argc;
  	char *argv[];
  	{
! 	int i, j = 0, k = 0;
! 	long zero = 0;
  	register char	*outfile = NULL, *infile = NULL;
  	FILE *mf;
  	struct	stat	st;
*** /usr/src/bin/mail.c.old	Thu Oct  2 20:20:01 1997
--- /usr/src/bin/mail.c	Thu Dec 31 12:45:58 1998
***************
*** 1,5 ****
  #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)mail.c	4.33.4 (2.11BSD GTE) 1997/10/2";
  #endif
  
  #include <sys/param.h>
--- 1,5 ----
  #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)mail.c	4.33.5 (2.11BSD) 1998/12/31";
  #endif
  
  #include <sys/param.h>
***************
*** 595,603 ****
  	char *name, *fromaddr;
  {
  	char file[256];
! 	int mask, fd;
  	struct passwd *pw;
  	char buf[128];
  
  	if (*name=='!')
  		name++;
--- 595,604 ----
  	char *name, *fromaddr;
  {
  	char file[256];
! 	int fd;
  	struct passwd *pw;
  	char buf[128];
+ 	off_t oldsize;
  
  	if (*name=='!')
  		name++;
***************
*** 610,620 ****
  	cat(file, maildir, name);
  	if (!safefile(file))
  		return(0);
! 	fd = open(file, O_WRONLY | O_CREAT, MAILMODE);
! 	if (fd >= 0) {
! 		flock(fd, LOCK_EX);
  		malf = fdopen(fd, "a");
- 	}
  	if (fd < 0 || malf == NULL) {
  		close(fd);
  		printf("mail: %s: cannot append\n", file);
--- 611,619 ----
  	cat(file, maildir, name);
  	if (!safefile(file))
  		return(0);
! 	fd = open(file, O_WRONLY | O_CREAT | O_EXLOCK, MAILMODE);
! 	if (fd >= 0)
  		malf = fdopen(fd, "a");
  	if (fd < 0 || malf == NULL) {
  		close(fd);
  		printf("mail: %s: cannot append\n", file);
***************
*** 621,628 ****
  		return(0);
  	}
  	fchown(fd, pw->pw_uid, pw->pw_gid);
! 	(void)sprintf(buf, "%s@%ld\n", name, ftell(malf));
! 	copylet(n, malf, ORDINARY);
  	fclose(malf);
  	notifybiff(buf);
  	return(1);
--- 620,646 ----
  		return(0);
  	}
  	fchown(fd, pw->pw_uid, pw->pw_gid);
! 	oldsize = ftell(malf);
! 	(void)sprintf(buf, "%s@%ld\n", name, oldsize);
! 
! 	copylet(n, malf, ORDINARY);     /* Try to deliver the message */
! 
! 	/* If there is any error during the delivery of the message,
! 	 * the mail file may be corrupted (incomplete last line) and
! 	 * any subsequent mail will be apparently lost, since the
! 	 * <NL> before the 'From ' won't be there.  So, restore the
! 	 * file to the pre-delivery size and report an error.
! 	 *
! 	 * fflush does "_flag |= _IOERR" so we don't need to check both the
! 	 # return from fflush and the ferror status.
! 	*/
! 	(void)fflush(malf);
! 	if (ferror(malf)) {
! 		printf("mail: %s: cannot append\n", file);
! 		ftruncate(fd, oldsize);
! 		fclose(malf);
! 		return(0);
! 	}
  	fclose(malf);
  	notifybiff(buf);
  	return(1);
*** /VERSION.old	Tue Sep 15 21:04:06 1998
--- /VERSION	Thu Dec 31 20:27:01 1998
***************
*** 1,5 ****
! Current Patch Level: 407
! Date: September 15, 1998
  
  2.11 BSD
  ============
--- 1,5 ----
! Current Patch Level: 408
! Date: December 31, 1998
  
  2.11 BSD
  ============
