[comp.bugs.4bsd] Curses steps on the user environment

kathyv@tektools.UUCP (Kathy Vineyard) (12/01/86)

Index:	/usr/src/usr.lib/libcurses/cr_tty.c 4.3BSD

Description:
	When running a program that uses curses, the user environment
	was sometimes getting stepped on.  This resulted in getting the
	famed "x: is not an identifier" from /bin/sh when it was
	exec'd.  This happened only when using a termcap which had
	multiple names ( > 2 ) for the termcap entry, the third name of
	the entry was the one being used by the user, and the length of
	that third name was at least 2 less than the length of the
	second name.

Repeat-By:
	Use a termcap which has it's names set up like:

	   Mc|aaa-c|aaa|aaa with separate scrolling and editing areas:\

	The way I found it was to use initscr() (which calls the
	functions in cr_tty.c) and print out the environment just
	before and after the initscr.  With a termcap entry set up as
	above (with the setups, of course) and your TERM variable set
	to the third name (in this case, the "aaa"), you can run this
	little program to duplicate the bug and see how it messes up
	the environment:

#include <stdio.h>
#include <curses.h>

extern char **environ;

printenv()
{
	int n=1;
	char **c;

	c= environ;
	while (*c) {
		printf("%d. %s\n",n, *c);
		n++;
		*c++;
	}
}

main()
{
	printenv();
	initscr();
	refresh();
	printenv();
	printf("\n");
	execl("/bin/sh","sh","-c","ls");
}

( compile with "cc foo.c -lcurses -ltermlib" )


Fix:
	A fix is to send longname() a copy of the TERM variable, not
	the TERM variable itself, as longname replaces the variable it
	was sent with the second field of the termcap name.  A context
	diff is included, numbering may be a few off:

*** cr_tty.c.old	Mon Dec  1 11:25:35 1986
--- cr_tty.c.new	Mon Dec  1 11:25:09 1986
***************
*** 77,82
  
  	reg int		unknown;
  	static char	genbuf[1024];
  # ifdef TIOCGWINSZ
  	struct winsize win;
  # endif

--- 77,84 -----
  
  	reg int		unknown;
  	static char	genbuf[1024];
+ 	static char	xtype[1024];	/* xtype should be the same size 
+ 					   as genbuf for longname(). */
  # ifdef TIOCGWINSZ
  	struct winsize win;
  # endif
***************
*** 137,143
  
  	PC = _PC ? _PC[0] : FALSE;
  	aoftspace = _tspace;
! 	strncpy(ttytype, longname(genbuf, type), sizeof(ttytype) - 1);
  	ttytype[sizeof(ttytype) - 1] = '\0';
  	if (unknown)
  		return ERR;

--- 139,150 -----
  
  	PC = _PC ? _PC[0] : FALSE;
  	aoftspace = _tspace;
! 	/*
! 	 * longname() steps on the second variable it is passed, so copy type
! 	 * into xtype so it isn't stepped on when you are least suspecting it.
! 	 */
! 	strcpy(xtype,type);
! 	strncpy(ttytype, longname(genbuf, xtype), sizeof(ttytype) - 1);
  	ttytype[sizeof(ttytype) - 1] = '\0';
  	if (unknown)
  		return ERR;

-------------------------------------------------------------------------------

Kathy Vineyard

kathyv@tektools.tek.com
Unix Systems Support, Tektronix Inc.