Subject: bin/1760: /bin/sh `cd -' dumps core if you've never changed directories
To: None <gnats-bugs@gnats.netbsd.org>
From: Scott Reynolds <scottr@Plexus.COM>
List: netbsd-bugs
Date: 11/13/1995 12:30:39
>Number:         1760
>Category:       bin
>Synopsis:       /bin/sh `cd -' dumps core if you've never changed directories
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Nov 13 13:50:02 1995
>Last-Modified:
>Originator:     Scott Reynolds
>Organization:
>Release:        1.1_ALPHA, 13 Nov 1995
>Environment:
	N/A
System: NetBSD beech 1.1_ALPHA NetBSD 1.1_ALPHA (TGI) #1: Mon Nov 6 18:00:40 CST 1995 scottr@beech:/amd/aqua/usr/src/sys/arch/hp300/compile/TGI hp300


>Description:
	In cd.c:94, the `dest' pointer gets the value of prevdir if it's
	non-NULL, otherwise it gets the value of curdir.  At line 97 this
	pointer gets dereferenced.  Unfortunately, 

>How-To-Repeat:
	1) Start /bin/sh
	2) Before typing anything else, enter `cd -'
	3) Watch.

>Fix:
	This diff has two parts.  The change to cd.c removes the fork/exec
	to run /bin/pwd to get the current working directory (because I
	wanted to minimize the amount of time at startup, and this just
	seems ugly anyway).  I instead used getcwd() from libc.

	The change to main.c implements the actual fix by calling getpwd()
	to initialize curdir after initializing everything else of interest,
	but before /etc/profile and ~/.profile are run.

	If there is a real reason to retain the /bin/pwd code, that
	part of the diff can be ignored with the only ill effect being
	the increase in startup time and the reliance on /bin/pwd.

*** bin/sh/cd.c-dist	Fri Oct 13 18:43:57 1995
--- bin/sh/cd.c	Mon Nov 13 12:09:47 1995
***************
*** 328,337 ****
  
  
  /*
!  * Run /bin/pwd to find out what the current directory is.  We suppress
!  * interrupts throughout most of this, but the user can still break out
!  * of it by killing the pwd program.  If we already know the current
!  * directory, this routine returns immediately.
   */
  
  #define MAXPWD 256
--- 328,335 ----
  
  
  /*
!  * If we already know the current directory, this routine returns
!  * immediately.
   */
  
  #define MAXPWD 256
***************
*** 347,382 ****
  
  	if (curdir)
  		return;
! 	INTOFF;
! 	if (pipe(pip) < 0)
! 		error("Pipe call failed");
! 	jp = makejob((union node *)NULL, 1);
! 	if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
! 		close(pip[0]);
! 		if (pip[1] != 1) {
! 			close(1);
! 			copyfd(pip[1], 1);
! 			close(pip[1]);
! 		}
! 		execl("/bin/pwd", "pwd", (char *)0);
! 		error("Cannot exec /bin/pwd");
! 	}
! 	close(pip[1]);
! 	pip[1] = -1;
! 	p = buf;
! 	while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
! 	     || (i == -1 && errno == EINTR)) {
! 		if (i > 0)
! 			p += i;
! 	}
! 	close(pip[0]);
! 	pip[0] = -1;
! 	status = waitforjob(jp);
! 	if (status != 0)
! 		error((char *)0);
! 	if (i < 0 || p == buf || p[-1] != '\n')
! 		error("pwd command failed");
! 	p[-1] = '\0';
  	curdir = savestr(buf);
- 	INTON;
  }
--- 345,351 ----
  
  	if (curdir)
  		return;
! 	if (getcwd(buf, sizeof(buf)) == NULL)
! 		error("getcwd() failed");
  	curdir = savestr(buf);
  }
*** bin/sh/main.c-dist	Sat Oct 14 00:44:09 1995
--- bin/sh/main.c	Mon Nov 13 12:14:37 1995
***************
*** 91,96 ****
--- 91,97 ----
  
  STATIC void read_profile __P((char *));
  STATIC char *find_dot_file __P((char *));
+ STATIC void getpwd __P((void));
  
  /*
   * Main routine.  We initialize things, parse the arguments, execute
***************
*** 159,164 ****
--- 160,166 ----
  	init();
  	setstackmark(&smark);
  	procargs(argc, argv);
+ 	getpwd();
  	if (argv[0] && argv[0][0] == '-') {
  		state = 1;
  		read_profile("/etc/profile");
>Audit-Trail:
>Unformatted: