OLD | NEW |
1 #include <pty.h> | 1 #include <pty.h> |
2 #include <utmp.h> | 2 #include <utmp.h> |
3 #include <unistd.h> | 3 #include <unistd.h> |
4 #include <errno.h> | 4 #include <errno.h> |
5 #include <fcntl.h> | 5 #include <fcntl.h> |
6 #include <sys/wait.h> | 6 #include <sys/wait.h> |
7 #include <pthread.h> | 7 #include <pthread.h> |
8 | 8 |
9 int forkpty(int *pm, char *name, const struct termios *tio, const struct winsize
*ws) | 9 int forkpty(int* pm, |
10 { | 10 char* name, |
11 » int m, s, ec=0, p[2], cs; | 11 const struct termios* tio, |
12 » pid_t pid=-1; | 12 const struct winsize* ws) { |
13 » sigset_t set, oldset; | 13 int m, s, ec = 0, p[2], cs; |
| 14 pid_t pid = -1; |
| 15 sigset_t set, oldset; |
14 | 16 |
15 » if (openpty(&m, &s, name, tio, ws) < 0) return -1; | 17 if (openpty(&m, &s, name, tio, ws) < 0) |
| 18 return -1; |
16 | 19 |
17 » sigfillset(&set); | 20 sigfillset(&set); |
18 » pthread_sigmask(SIG_BLOCK, &set, &oldset); | 21 pthread_sigmask(SIG_BLOCK, &set, &oldset); |
19 » pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); | 22 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); |
20 | 23 |
21 » if (pipe2(p, O_CLOEXEC)) { | 24 if (pipe2(p, O_CLOEXEC)) { |
22 » » close(s); | 25 close(s); |
23 » » goto out; | 26 goto out; |
24 » } | 27 } |
25 | 28 |
26 » pid = fork(); | 29 pid = fork(); |
27 » if (!pid) { | 30 if (!pid) { |
28 » » close(m); | 31 close(m); |
29 » » close(p[0]); | 32 close(p[0]); |
30 » » if (login_tty(s)) { | 33 if (login_tty(s)) { |
31 » » » write(p[1], &errno, sizeof errno); | 34 write(p[1], &errno, sizeof errno); |
32 » » » _exit(127); | 35 _exit(127); |
33 » » } | 36 } |
34 » » close(p[1]); | 37 close(p[1]); |
35 » » pthread_setcancelstate(cs, 0); | 38 pthread_setcancelstate(cs, 0); |
36 » » pthread_sigmask(SIG_SETMASK, &oldset, 0); | 39 pthread_sigmask(SIG_SETMASK, &oldset, 0); |
37 » » return 0; | 40 return 0; |
38 » } | 41 } |
39 » close(s); | 42 close(s); |
40 » close(p[1]); | 43 close(p[1]); |
41 » if (read(p[0], &ec, sizeof ec) > 0) { | 44 if (read(p[0], &ec, sizeof ec) > 0) { |
42 » » int status; | 45 int status; |
43 » » waitpid(pid, &status, 0); | 46 waitpid(pid, &status, 0); |
44 » » pid = -1; | 47 pid = -1; |
45 » » errno = ec; | 48 errno = ec; |
46 » } | 49 } |
47 » close(p[0]); | 50 close(p[0]); |
48 | 51 |
49 out: | 52 out: |
50 » if (pid > 0) *pm = m; | 53 if (pid > 0) |
51 » else close(m); | 54 *pm = m; |
| 55 else |
| 56 close(m); |
52 | 57 |
53 » pthread_setcancelstate(cs, 0); | 58 pthread_setcancelstate(cs, 0); |
54 » pthread_sigmask(SIG_SETMASK, &oldset, 0); | 59 pthread_sigmask(SIG_SETMASK, &oldset, 0); |
55 | 60 |
56 » return pid; | 61 return pid; |
57 } | 62 } |
OLD | NEW |