1570af302Sopenharmony_ci#include <pty.h> 2570af302Sopenharmony_ci#include <utmp.h> 3570af302Sopenharmony_ci#include <unistd.h> 4570af302Sopenharmony_ci#include <errno.h> 5570af302Sopenharmony_ci#include <fcntl.h> 6570af302Sopenharmony_ci#include <sys/wait.h> 7570af302Sopenharmony_ci#include <pthread.h> 8570af302Sopenharmony_ci 9570af302Sopenharmony_ciint forkpty(int *pm, char *name, const struct termios *tio, const struct winsize *ws) 10570af302Sopenharmony_ci{ 11570af302Sopenharmony_ci int m, s, ec=0, p[2], cs; 12570af302Sopenharmony_ci pid_t pid=-1; 13570af302Sopenharmony_ci sigset_t set, oldset; 14570af302Sopenharmony_ci 15570af302Sopenharmony_ci if (openpty(&m, &s, name, tio, ws) < 0) return -1; 16570af302Sopenharmony_ci 17570af302Sopenharmony_ci sigfillset(&set); 18570af302Sopenharmony_ci pthread_sigmask(SIG_BLOCK, &set, &oldset); 19570af302Sopenharmony_ci pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); 20570af302Sopenharmony_ci 21570af302Sopenharmony_ci if (pipe2(p, O_CLOEXEC)) { 22570af302Sopenharmony_ci close(s); 23570af302Sopenharmony_ci goto out; 24570af302Sopenharmony_ci } 25570af302Sopenharmony_ci 26570af302Sopenharmony_ci pid = fork(); 27570af302Sopenharmony_ci if (!pid) { 28570af302Sopenharmony_ci close(m); 29570af302Sopenharmony_ci close(p[0]); 30570af302Sopenharmony_ci if (login_tty(s)) { 31570af302Sopenharmony_ci write(p[1], &errno, sizeof errno); 32570af302Sopenharmony_ci _exit(127); 33570af302Sopenharmony_ci } 34570af302Sopenharmony_ci close(p[1]); 35570af302Sopenharmony_ci pthread_setcancelstate(cs, 0); 36570af302Sopenharmony_ci pthread_sigmask(SIG_SETMASK, &oldset, 0); 37570af302Sopenharmony_ci return 0; 38570af302Sopenharmony_ci } 39570af302Sopenharmony_ci close(s); 40570af302Sopenharmony_ci close(p[1]); 41570af302Sopenharmony_ci if (read(p[0], &ec, sizeof ec) > 0) { 42570af302Sopenharmony_ci int status; 43570af302Sopenharmony_ci waitpid(pid, &status, 0); 44570af302Sopenharmony_ci pid = -1; 45570af302Sopenharmony_ci errno = ec; 46570af302Sopenharmony_ci } 47570af302Sopenharmony_ci close(p[0]); 48570af302Sopenharmony_ci 49570af302Sopenharmony_ciout: 50570af302Sopenharmony_ci if (pid > 0) *pm = m; 51570af302Sopenharmony_ci else close(m); 52570af302Sopenharmony_ci 53570af302Sopenharmony_ci pthread_setcancelstate(cs, 0); 54570af302Sopenharmony_ci pthread_sigmask(SIG_SETMASK, &oldset, 0); 55570af302Sopenharmony_ci 56570af302Sopenharmony_ci return pid; 57570af302Sopenharmony_ci} 58