Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 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; } } |