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