Loading...
stdlib/FreeBSD/grantpt.c.patch /dev/null Libc-391.5.18
--- /dev/null
+++ Libc/Libc-391.5.18/stdlib/FreeBSD/grantpt.c.patch
@@ -0,0 +1,161 @@
+--- grantpt.c.orig	2006-04-21 22:41:31.000000000 -0700
++++ grantpt.c	2006-04-21 22:43:03.000000000 -0700
+@@ -54,18 +54,16 @@
+ #include <unistd.h>
+ #include "un-namespace.h"
+ 
+-#define PTM_MAJOR	6	/* pseudo tty master major */
+-#define PTS_MAJOR	5	/* pseudo tty slave major */
+ #define PTM_PREFIX	"pty"	/* pseudo tty master naming convention */
+ #define PTS_PREFIX	"tty"	/* pseudo tty slave naming convention */
+ 
+ /*
+  * The following are range values for pseudo TTY devices.  Pseudo TTYs have a
+- * name of /dev/[pt]ty[p-sP-S][0-9a-v], yielding 256 combinations per major.
++ * name of /dev/[pt]ty[p-w][0-9a-f], yielding 128 combinations per major.
+  */
+-#define PT_MAX		256
+-#define	PT_DEV1		"pqrsPQRS"
+-#define PT_DEV2		"0123456789abcdefghijklmnopqrstuv"
++#define PT_MAX		128
++#define	PT_DEV1		"pqrstuvw"
++#define PT_DEV2		"0123456789abcdef"
+ 
+ /*
+  * grantpt(3) support utility.
+@@ -73,11 +71,32 @@
+ #define _PATH_PTCHOWN	"/usr/libexec/pt_chown"
+ 
+ /*
++ * On Mac OS X, the major device number may not be the same between reboots.
++ * So we need to determine the major device number the first time.
++ */
++#define	_PATH_A_PTY	(_PATH_DEV PTM_PREFIX "p0")
++
++static int _ptm_major = -1;
++
++static int
++_init_major(void)
++{
++	struct stat st;
++
++	if (_ptm_major >= 0)
++		return _ptm_major;
++	if (stat(_PATH_A_PTY, &st) < 0)
++		return -1; /* should never happen */
++	_ptm_major = major(st.st_rdev);
++	return _ptm_major;
++}
++/*
+  * ISPTM(x) returns 0 for struct stat x if x is not a pty master.
+  * The bounds checking may be unnecessary but it does eliminate doubt.
+  */
+-#define ISPTM(x)	(S_ISCHR((x).st_mode) && 			\
+-			 major((x).st_rdev) == PTM_MAJOR &&		\
++#define ISPTM(x)	(_init_major() >= 0 &&				\
++			 S_ISCHR((x).st_mode) && 			\
++			 major((x).st_rdev) == _ptm_major &&		\
+ 			 minor((x).st_rdev) >= 0 &&			\
+ 			 minor((x).st_rdev) < PT_MAX)
+ 
+@@ -100,50 +119,53 @@
+ 	serrno = errno;
+ 
+ 	if ((slave = ptsname(fildes)) != NULL) {
+-		/*
+-		 * Block SIGCHLD.
+-		 */
+-		(void)sigemptyset(&nblock);
+-		(void)sigaddset(&nblock, SIGCHLD);
+-		(void)_sigprocmask(SIG_BLOCK, &nblock, &oblock);
+-
+-		switch (pid = fork()) {
+-		case -1:
+-			break;
+-		case 0:		/* child */
++		/* 4430299: if we are root, we don't need to fork/exec */
++		if (geteuid() != 0) {
+ 			/*
+-			 * pt_chown expects the master pseudo TTY to be its
+-			 * standard input.
++			 * Block SIGCHLD.
+ 			 */
+-			(void)_dup2(fildes, STDIN_FILENO);
+-			(void)_sigprocmask(SIG_SETMASK, &oblock, NULL);
+-			execl(_PATH_PTCHOWN, _PATH_PTCHOWN, (char *)NULL);
+-			_exit(EX_UNAVAILABLE);
+-			/* NOTREACHED */
+-		default:	/* parent */
++			(void)sigemptyset(&nblock);
++			(void)sigaddset(&nblock, SIGCHLD);
++			(void)_sigprocmask(SIG_BLOCK, &nblock, &oblock);
++
++			switch (pid = fork()) {
++			case -1:
++				break;
++			case 0:		/* child */
++				/*
++				 * pt_chown expects the master pseudo TTY to be its
++				 * standard input.
++				 */
++				(void)_dup2(fildes, STDIN_FILENO);
++				(void)_sigprocmask(SIG_SETMASK, &oblock, NULL);
++				execl(_PATH_PTCHOWN, _PATH_PTCHOWN, (char *)NULL);
++				_exit(EX_UNAVAILABLE);
++				/* NOTREACHED */
++			default:	/* parent */
++				/*
++				 * Just wait for the process.  Error checking is
++				 * done below.
++				 */
++				while ((spid = _waitpid(pid, &status, 0)) == -1 &&
++				       (errno == EINTR))
++					;
++				if (spid != -1 && WIFEXITED(status) &&
++				    WEXITSTATUS(status) == EX_OK)
++					retval = 0;
++				else
++					errno = EACCES;
++				break;
++			}
++
+ 			/*
+-			 * Just wait for the process.  Error checking is
+-			 * done below.
++			 * Restore process's signal mask.
+ 			 */
+-			while ((spid = _waitpid(pid, &status, 0)) == -1 &&
+-			       (errno == EINTR))
+-				;
+-			if (spid != -1 && WIFEXITED(status) &&
+-			    WEXITSTATUS(status) == EX_OK)
+-				retval = 0;
+-			else
+-				errno = EACCES;
+-			break;
++			(void)_sigprocmask(SIG_SETMASK, &oblock, NULL);
+ 		}
+ 
+-		/*
+-		 * Restore process's signal mask.
+-		 */
+-		(void)_sigprocmask(SIG_SETMASK, &oblock, NULL);
+-
+ 		if (retval) {
+ 			/*
+-			 * pt_chown failed.  Try to manually change the
++			 * pt_chown failed (or we're root).  Try to manually change the
+ 			 * permissions for the slave.
+ 			 */
+ 			gid = (grp = getgrnam("tty")) ? grp->gr_gid : -1;
+@@ -227,8 +249,8 @@
+ 			errno = EINVAL;
+ 		else {
+ 			(void)sprintf(slave, _PATH_DEV PTS_PREFIX "%c%c",
+-				      PT_DEV1[minor(sbuf.st_rdev) / 32],
+-				      PT_DEV2[minor(sbuf.st_rdev) % 32]);
++				      PT_DEV1[minor(sbuf.st_rdev) / 16],
++				      PT_DEV2[minor(sbuf.st_rdev) % 16]);
+ 			retval = slave;
+ 		}
+ 	}