[comp.bugs.4bsd] Vi bug with fix

cander@unisoft.UUCP (Charles Anderson) (08/30/88)

Description:
    Vi dumps core (segmentation violation or bus error) if initializations 
    contain 'open'.  So does ex.

Repeat By:
    setenv EXINIT open
    vi foo 

Systems:
    All 4.2 derived systems that I've tried, i.e, 4.3 VAX, SunOS 3.3, Pyramid
    OSX 4.1.

Fix:
    init() must be called before processing initializations.  However, if
    the initializations include 'set dir=XXX', init(), or at least fileinit(),
    must be called again to reflect the new directory.  fileinit() has to be
    made smart enough to know when the buffer name changes, so that if it
    gets called twice it won't just return the second time.

    These diffs are from the 4.3 sources, so you're line numbers and milage
    may vary.


Charles.
-----------
*** ex.c.orig	Mon Aug 29 15:06:19 1988
--- ex.c	Mon Aug 29 15:20:01 1988
***************
*** 316,321
  				setterm(cp);
  		}
  	}
  	if (setexit() == 0 && !fast && intty) {
  		if ((globp = getenv("EXINIT")) && *globp)
  			commands(1,1);

--- 316,322 -----
  				setterm(cp);
  		}
  	}
+ 	init(); /* moved up here in case initializations contain open command */
  	if (setexit() == 0 && !fast && intty) {
  		if ((globp = getenv("EXINIT")) && *globp)
  			commands(1,1);
***************
*** 335,340
  		 */
  		 if (iownit(".exrc"))
  			source(".exrc", 1);
  	}
  	init();	/* moved after prev 2 chunks to fix directory option */
  

--- 336,342 -----
  		 */
  		 if (iownit(".exrc"))
  			source(".exrc", 1);
+ 		 init();  /* Init again in case user changed dir */
  	}
  
  	/*
***************
*** 336,342
  		 if (iownit(".exrc"))
  			source(".exrc", 1);
  	}
- 	init();	/* moved after prev 2 chunks to fix directory option */
  
  	/*
  	 * Initial processing.  Handle tag, recover, and file argument

--- 338,343 -----
  			source(".exrc", 1);
  		 init();  /* Init again in case user changed dir */
  	}
  
  	/*
  	 * Initial processing.  Handle tag, recover, and file argument
*** ex_temp.c.orig	Mon Aug 29 15:16:06 1988
--- ex_temp.c	Mon Aug 29 15:20:23 1988
***************
*** 32,38
  	register int i, j;
  	struct stat stbuf;
  
! 	if (tline == INCRMT * (HBLKS+2))
  		return;
  	cleanup(0);
  	close(tfile);

--- 32,39 -----
  	register int i, j;
  	struct stat stbuf;
  
! 					      /* also check for new tmp file name */
! 	if ((tline == INCRMT * (HBLKS+2)) && (strcmp(tfname, svalue(DIRECTORY)) == 0 ))
  		return;
  	cleanup(0);
  	close(tfile);
-- 

Charles.
{sun, amdahl, ucbvax, pyramid, uunet}!unisoft!cander

wk@hpirs.HP.COM (Wayne Krone) (09/02/88)

> Description:
>     Vi dumps core (segmentation violation or bus error) if initializations 
>     contain 'open'.  So does ex.
> 
> Repeat By:
>     setenv EXINIT open
>     vi foo 

I applied this fix and it stops the core dumps (thanks!!).  But, at least
on my implementation, any text inserted into the buffer via the 'open'
command is lost at the point init() is called a second time.  I.e.:

      setenv EXINIT open
      vi
      ithis is a test^[			<-- text inserted during open mode
      Q					<-- quit open mode
					 -- now in vi mode but buffer is empty

Should the 'open' be useful or just not core dump?

Presuming it should work, a fix is to call init() a second time only if
the directory option has been set.  Following are some deltas to Charles'
deltas with this change.

Wayne Krone

********************
To ex.h add:

var	bool	dir_chg;	/* true if directory option reset */

********************
To ex.c modify Charles' changes as follows:

--------------------
Charles' version:
>   				setterm(cp);
>   		}
>   	}
> + 	init(); /* moved up here in case initializations contain open command */
>   	if (setexit() == 0 && !fast && intty) {
>   		if ((globp = getenv("EXINIT")) && *globp)
>   			commands(1,1);

new:
  				setterm(cp);
  		}
  	}
 	init(); /* moved up here in case initializations contain open command */
  	if (setexit() == 0 && !fast && intty) {
+		dir_chg = 0;
  		if ((globp = getenv("EXINIT")) && *globp)
  			commands(1,1);

--------------------
Charles' version:
>   		 */
>   		 if (iownit(".exrc"))
>   			source(".exrc", 1);
> + 		 init();  /* Init again in case user changed dir */
>   	}
>   

new:
  		 */
  		 if (iownit(".exrc"))
  			source(".exrc", 1);
+		 if (dir_chg)
!			 init();  /* Init again if user changed dir */
  	}

********************
To ex_set.c add (~line 106 on 4.2):

                case STRING:
		case OTERM:
+			dir_chg = (op == &options[DIRECTORY]);  /* flag if user changing dir */
			cp = optname;
			while (!setend()) {
				if (cp >= &optname[ONMSZ])