From phk@critter.freebsd.dk  Thu Jan 16 02:19:06 2003
Return-Path: <phk@critter.freebsd.dk>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id BB5B637B401
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 16 Jan 2003 02:19:06 -0800 (PST)
Received: from critter.freebsd.dk (esplanaden.cybercity.dk [212.242.40.114])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 9928D43F5F
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 16 Jan 2003 02:19:05 -0800 (PST)
	(envelope-from phk@critter.freebsd.dk)
Received: from critter.freebsd.dk (localhost [127.0.0.1])
	by critter.freebsd.dk (8.12.6/8.12.6) with ESMTP id h0GAIS4u001260
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 16 Jan 2003 11:18:28 +0100 (CET)
	(envelope-from phk@critter.freebsd.dk)
Received: (from phk@localhost)
	by critter.freebsd.dk (8.12.6/8.12.6/Submit) id h0G8i5Tb004957;
	Thu, 16 Jan 2003 09:44:05 +0100 (CET)
Message-Id: <200301160844.h0G8i5Tb004957@critter.freebsd.dk>
Date: Thu, 16 Jan 2003 09:44:05 +0100 (CET)
From: Poul-Henning Kamp <phk@critter.freebsd.dk>
Reply-To: Poul-Henning Kamp <phk@critter.freebsd.dk>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: /bin/sh gets confused if file descriptor 3 is used.
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         47136
>Category:       bin
>Synopsis:       /bin/sh gets confused if file descriptor 3 is used.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    tjr
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jan 16 02:20:02 PST 2003
>Closed-Date:    Mon Feb 03 18:41:45 PST 2003
>Last-Modified:  Mon Feb 03 18:41:45 PST 2003
>Originator:     Poul-Henning Kamp
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
>Environment:
System: FreeBSD critter.freebsd.dk 5.0-CURRENT FreeBSD 5.0-CURRENT #8: Sat Jan 4 18:28:00 CET 2003 root@critter.freebsd.dk:/freebsd/src/sys/i386/compile/C2 i386


>Description:
	/bin/sh gets confused if file descriptor 3 is used.


>How-To-Repeat:

	Type this by hand.  When running these commands as a shellscript
	it works without a hitch.

	# /bin/sh
	# date > /tmp/foo
	# exec 3< /tmp/foo
	# ls -ld /	
	tcsetpgrp failed, errno=25
	tcsetpgrp failed, errno=25

	# exit
	# /bin/sh
	# exec 4< /tmp/foo
	# ls -ld /
	drwxr-xr-x  17 root  wheel  512 Jan  6 12:45 /
	#

>Fix:



>Release-Note:
>Audit-Trail:

From: Friedemann Becker <friedemann.becker@student.uni-tuebingen.de>
To: <freebsd-gnats-submit@FreeBSD.org>, <phk@critter.freebsd.dk>
Cc:  
Subject: Re: bin/47136:
Date: Sun, 26 Jan 2003 19:13:44 +0100 (CET)

 I found, that sh uses fd 3 for the controlling terminal. /bin/sh opens
 /dev/tty and stores the resulting file descriptor in ttyfd:
 
 jobs.c:
 122:    if (on) {
 123:            if (ttyfd != -1)
 124:                    close(ttyfd);
 125:            if ((ttyfd = open(_PATH_TTY, O_RDWR)) < 0) {
 126:                    i = 0;
 127:                    while (i <= 2 && !isatty(i))
 128:                            i++;
 129:                    if (i > 2 || (ttyfd = dup(i)) < 0)
 130:                            goto out;
 131:            }
 
 ttyfd is needed for calls to tcsetpgrp.
 
 To prevent conflicts with user-fd, ttyfd should be moved to a higher fd
 like bash2 does:
 
 jobs.c:
 2911:      /* Get our controlling terminal.  If job_control is set, or
 2912:    interactive is set, then this is an interactive shell no
 2913:    matter where fd 2 is directed. */
 2914:      shell_tty = dup (fileno (stderr));   /* fd 2 */
 2915:
 2916:      shell_tty = move_to_high_fd (shell_tty, 1, -1);
 2917:
 
 here's a patch proposal.
 
 Sorry for sending mails twice, addresses were wrong. :/
 
 Friedemann
 
 
 
 
 --- /usr/src/bin/sh/jobs.c	Wed Jan 22 02:30:07 2003
 +++ jobs.c	Sun Jan 26 19:05:53 2003
 @@ -76,6 +76,7 @@
  #include "mystring.h"
 
 
 +
  struct job *jobtab;		/* array of jobs */
  int njobs;			/* size of array */
  MKINIT pid_t backgndpid = -1;	/* pid of last background process */
 @@ -105,6 +106,9 @@
  STATIC void showjob(struct job *, pid_t, int, int);
 
 
 +int move_to_high_fd __P((int, int, int));
 +
 +
  /*
   * Turn job control on and off.
   */
 @@ -129,6 +133,8 @@
  			if (i > 2 || (ttyfd = dup(i)) < 0)
  				goto out;
  		}
 +		ttyfd = move_to_high_fd (ttyfd, 1, -1);
 +
  		if (fcntl(ttyfd, F_SETFD, FD_CLOEXEC) < 0) {
  			close(ttyfd);
  			ttyfd = -1;
 @@ -1227,4 +1233,48 @@
  		}
  	}
  	cmdnextc = q;
 +}
 +
 +
 +
 +#define HIGH_FD_MAX	256
 +
 +/* Move FD to a number close to the maximum number of file descriptors
 +   allowed in the shell process, to avoid the user stepping on it with
 +   redirection and causing us extra work.  If CHECK_NEW is non-zero,
 +   we check whether or not the file descriptors are in use before
 +   duplicating FD onto them.  MAXFD says where to start checking the
 +   file descriptors.  If it's less than 20, we get the maximum value
 +   available from getdtablesize(2). */
 +int
 +move_to_high_fd (fd, check_new, maxfd)
 +	int fd, check_new, maxfd;
 +{
 +	int script_fd, nfds, ignore;
 +
 +	if (maxfd < 20)
 +	{
 +		nfds = getdtablesize ();
 +		if (nfds <= 0)
 +			nfds = 20;
 +		if (nfds > HIGH_FD_MAX)
 +			nfds = HIGH_FD_MAX;		/* reasonable maximum */
 +	}
 +	else
 +		nfds = maxfd;
 +
 +	for (nfds--; check_new && nfds > 3; nfds--)
 +		if (fcntl (nfds, F_GETFD, &ignore) == -1)
 +			break;
 +
 +	if (nfds > 3 && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
 +	{
 +		if (check_new == 0 || fd != 2)	/* don't close stderr */
 +			close (fd);
 +		return (script_fd);
 +	}
 +
 +	/* OK, we didn't find one less than our artificial maximum; return the
 +	   original file descriptor. */
 +	return (fd);
  }
 
Responsible-Changed-From-To: freebsd-bugs->tjr 
Responsible-Changed-By: tjr 
Responsible-Changed-When: Sun Jan 26 22:33:37 PST 2003 
Responsible-Changed-Why:  
I'll fix this. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=47136 
State-Changed-From-To: open->patched 
State-Changed-By: tjr 
State-Changed-When: Sun Jan 26 23:41:22 PST 2003 
State-Changed-Why:  
Fixed in -current, change will be MFC'd after one week. 
Thanks for the report. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=47136 
State-Changed-From-To: patched->closed 
State-Changed-By: tjr 
State-Changed-When: Mon Feb 3 18:40:26 PST 2003 
State-Changed-Why:  
Fixed in RELENG_4; thanks for the report. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=47136 
>Unformatted:
