github.com/afumu/libc@v0.0.6/musl/src/misc/forkpty.c (about)

     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  }