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 9int 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 49out: 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} 58