]>
Commit | Line | Data |
---|---|---|
a5cd208c A |
1 | --- grantpt.c.orig 2006-04-21 22:41:31.000000000 -0700 |
2 | +++ grantpt.c 2006-04-21 22:43:03.000000000 -0700 | |
3d9156a7 A |
3 | @@ -54,18 +54,16 @@ |
4 | #include <unistd.h> | |
5 | #include "un-namespace.h" | |
6 | ||
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 */ | |
11 | ||
12 | /* | |
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. | |
16 | */ | |
17 | -#define PT_MAX 256 | |
18 | -#define PT_DEV1 "pqrsPQRS" | |
19 | -#define PT_DEV2 "0123456789abcdefghijklmnopqrstuv" | |
20 | +#define PT_MAX 128 | |
21 | +#define PT_DEV1 "pqrstuvw" | |
22 | +#define PT_DEV2 "0123456789abcdef" | |
23 | ||
24 | /* | |
25 | * grantpt(3) support utility. | |
26 | @@ -73,11 +71,32 @@ | |
27 | #define _PATH_PTCHOWN "/usr/libexec/pt_chown" | |
28 | ||
29 | /* | |
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. | |
32 | + */ | |
33 | +#define _PATH_A_PTY (_PATH_DEV PTM_PREFIX "p0") | |
34 | + | |
35 | +static int _ptm_major = -1; | |
36 | + | |
37 | +static int | |
38 | +_init_major(void) | |
39 | +{ | |
40 | + struct stat st; | |
41 | + | |
42 | + if (_ptm_major >= 0) | |
43 | + return _ptm_major; | |
44 | + if (stat(_PATH_A_PTY, &st) < 0) | |
45 | + return -1; /* should never happen */ | |
46 | + _ptm_major = major(st.st_rdev); | |
47 | + return _ptm_major; | |
48 | +} | |
49 | +/* | |
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. | |
52 | */ | |
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) | |
60 | ||
a5cd208c A |
61 | @@ -100,50 +119,53 @@ |
62 | serrno = errno; | |
63 | ||
64 | if ((slave = ptsname(fildes)) != NULL) { | |
65 | - /* | |
66 | - * Block SIGCHLD. | |
67 | - */ | |
68 | - (void)sigemptyset(&nblock); | |
69 | - (void)sigaddset(&nblock, SIGCHLD); | |
70 | - (void)_sigprocmask(SIG_BLOCK, &nblock, &oblock); | |
71 | - | |
72 | - switch (pid = fork()) { | |
73 | - case -1: | |
74 | - break; | |
75 | - case 0: /* child */ | |
76 | + /* 4430299: if we are root, we don't need to fork/exec */ | |
77 | + if (geteuid() != 0) { | |
78 | /* | |
79 | - * pt_chown expects the master pseudo TTY to be its | |
80 | - * standard input. | |
81 | + * Block SIGCHLD. | |
82 | */ | |
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); | |
87 | - /* NOTREACHED */ | |
88 | - default: /* parent */ | |
89 | + (void)sigemptyset(&nblock); | |
90 | + (void)sigaddset(&nblock, SIGCHLD); | |
91 | + (void)_sigprocmask(SIG_BLOCK, &nblock, &oblock); | |
92 | + | |
93 | + switch (pid = fork()) { | |
94 | + case -1: | |
95 | + break; | |
96 | + case 0: /* child */ | |
97 | + /* | |
98 | + * pt_chown expects the master pseudo TTY to be its | |
99 | + * standard input. | |
100 | + */ | |
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); | |
105 | + /* NOTREACHED */ | |
106 | + default: /* parent */ | |
107 | + /* | |
108 | + * Just wait for the process. Error checking is | |
109 | + * done below. | |
110 | + */ | |
111 | + while ((spid = _waitpid(pid, &status, 0)) == -1 && | |
112 | + (errno == EINTR)) | |
113 | + ; | |
114 | + if (spid != -1 && WIFEXITED(status) && | |
115 | + WEXITSTATUS(status) == EX_OK) | |
116 | + retval = 0; | |
117 | + else | |
118 | + errno = EACCES; | |
119 | + break; | |
120 | + } | |
121 | + | |
122 | /* | |
123 | - * Just wait for the process. Error checking is | |
124 | - * done below. | |
125 | + * Restore process's signal mask. | |
126 | */ | |
127 | - while ((spid = _waitpid(pid, &status, 0)) == -1 && | |
128 | - (errno == EINTR)) | |
129 | - ; | |
130 | - if (spid != -1 && WIFEXITED(status) && | |
131 | - WEXITSTATUS(status) == EX_OK) | |
132 | - retval = 0; | |
133 | - else | |
134 | - errno = EACCES; | |
135 | - break; | |
136 | + (void)_sigprocmask(SIG_SETMASK, &oblock, NULL); | |
137 | } | |
138 | ||
139 | - /* | |
140 | - * Restore process's signal mask. | |
141 | - */ | |
142 | - (void)_sigprocmask(SIG_SETMASK, &oblock, NULL); | |
143 | - | |
144 | if (retval) { | |
145 | /* | |
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. | |
149 | */ | |
150 | gid = (grp = getgrnam("tty")) ? grp->gr_gid : -1; | |
151 | @@ -227,8 +249,8 @@ | |
3d9156a7 A |
152 | errno = EINVAL; |
153 | else { | |
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]); | |
159 | retval = slave; | |
160 | } | |
161 | } |