1 --- grantpt.c.orig 2006-04-21 22:41:31.000000000 -0700
2 +++ grantpt.c 2006-04-21 22:43:03.000000000 -0700
5 #include "un-namespace.h"
7 -#define PTM_MAJOR 6 /* pseudo tty master major */
8 -#define PTS_MAJOR 5 /* pseudo tty slave major */
9 #define PTM_PREFIX "pty" /* pseudo tty master naming convention */
10 #define PTS_PREFIX "tty" /* pseudo tty slave naming convention */
13 * The following are range values for pseudo TTY devices. Pseudo TTYs have a
14 - * name of /dev/[pt]ty[p-sP-S][0-9a-v], yielding 256 combinations per major.
15 + * name of /dev/[pt]ty[p-w][0-9a-f], yielding 128 combinations per major.
18 -#define PT_DEV1 "pqrsPQRS"
19 -#define PT_DEV2 "0123456789abcdefghijklmnopqrstuv"
21 +#define PT_DEV1 "pqrstuvw"
22 +#define PT_DEV2 "0123456789abcdef"
25 * grantpt(3) support utility.
27 #define _PATH_PTCHOWN "/usr/libexec/pt_chown"
30 + * On Mac OS X, the major device number may not be the same between reboots.
31 + * So we need to determine the major device number the first time.
33 +#define _PATH_A_PTY (_PATH_DEV PTM_PREFIX "p0")
35 +static int _ptm_major = -1;
42 + if (_ptm_major >= 0)
44 + if (stat(_PATH_A_PTY, &st) < 0)
45 + return -1; /* should never happen */
46 + _ptm_major = major(st.st_rdev);
50 * ISPTM(x) returns 0 for struct stat x if x is not a pty master.
51 * The bounds checking may be unnecessary but it does eliminate doubt.
53 -#define ISPTM(x) (S_ISCHR((x).st_mode) && \
54 - major((x).st_rdev) == PTM_MAJOR && \
55 +#define ISPTM(x) (_init_major() >= 0 && \
56 + S_ISCHR((x).st_mode) && \
57 + major((x).st_rdev) == _ptm_major && \
58 minor((x).st_rdev) >= 0 && \
59 minor((x).st_rdev) < PT_MAX)
64 if ((slave = ptsname(fildes)) != NULL) {
68 - (void)sigemptyset(&nblock);
69 - (void)sigaddset(&nblock, SIGCHLD);
70 - (void)_sigprocmask(SIG_BLOCK, &nblock, &oblock);
72 - switch (pid = fork()) {
76 + /* 4430299: if we are root, we don't need to fork/exec */
77 + if (geteuid() != 0) {
79 - * pt_chown expects the master pseudo TTY to be its
83 - (void)_dup2(fildes, STDIN_FILENO);
84 - (void)_sigprocmask(SIG_SETMASK, &oblock, NULL);
85 - execl(_PATH_PTCHOWN, _PATH_PTCHOWN, (char *)NULL);
86 - _exit(EX_UNAVAILABLE);
88 - default: /* parent */
89 + (void)sigemptyset(&nblock);
90 + (void)sigaddset(&nblock, SIGCHLD);
91 + (void)_sigprocmask(SIG_BLOCK, &nblock, &oblock);
93 + switch (pid = fork()) {
98 + * pt_chown expects the master pseudo TTY to be its
101 + (void)_dup2(fildes, STDIN_FILENO);
102 + (void)_sigprocmask(SIG_SETMASK, &oblock, NULL);
103 + execl(_PATH_PTCHOWN, _PATH_PTCHOWN, (char *)NULL);
104 + _exit(EX_UNAVAILABLE);
106 + default: /* parent */
108 + * Just wait for the process. Error checking is
111 + while ((spid = _waitpid(pid, &status, 0)) == -1 &&
114 + if (spid != -1 && WIFEXITED(status) &&
115 + WEXITSTATUS(status) == EX_OK)
123 - * Just wait for the process. Error checking is
125 + * Restore process's signal mask.
127 - while ((spid = _waitpid(pid, &status, 0)) == -1 &&
130 - if (spid != -1 && WIFEXITED(status) &&
131 - WEXITSTATUS(status) == EX_OK)
136 + (void)_sigprocmask(SIG_SETMASK, &oblock, NULL);
140 - * Restore process's signal mask.
142 - (void)_sigprocmask(SIG_SETMASK, &oblock, NULL);
146 - * pt_chown failed. Try to manually change the
147 + * pt_chown failed (or we're root). Try to manually change the
148 * permissions for the slave.
150 gid = (grp = getgrnam("tty")) ? grp->gr_gid : -1;
154 (void)sprintf(slave, _PATH_DEV PTS_PREFIX "%c%c",
155 - PT_DEV1[minor(sbuf.st_rdev) / 32],
156 - PT_DEV2[minor(sbuf.st_rdev) % 32]);
157 + PT_DEV1[minor(sbuf.st_rdev) / 16],
158 + PT_DEV2[minor(sbuf.st_rdev) % 16]);