int waitpid(int pid, int *status, int options) { int noptions, ret; int nstatus; if ((int)status == -1) { errno = EFAULT; return (-1); } /* * BSD's wait* routines only support WNOHANG & WUNTRACED */ if (options & ~(WNOHANG|WUNTRACED)) return (EINVAL); noptions = (N_WEXITED|N_WTRAPPED); if (options & WNOHANG) noptions |= N_WNOHANG; if (options & WUNTRACED) noptions |= N_WUNTRACED; /* == N_WSTOPPED */ ret = _waitpid(pid, &nstatus, noptions); if (status) mapstatus(status, nstatus); return (ret); }
int lms_finish_slave(struct pinfo *pinfo, int (*finish)(const struct fds *fds)) { int r; if (pinfo->child <= 0) return 0; r = finish(&pinfo->master); if (r == 0) r = _waitpid(pinfo->child); else { r = kill(pinfo->child, SIGKILL); if (r < 0) perror("kill"); else r =_waitpid(pinfo->child); } pinfo->child = 0; return r; }
int grantpt(int fildes) { int retval, serrno, status; pid_t pid, spid; gid_t gid; char* slave; sigset_t oblock, nblock; struct group* grp; retval = -1; serrno = errno; if ((slave = ptsname(fildes)) != NULL) { /* * Block SIGCHLD. */ (void)sigemptyset(&nblock); (void)sigaddset(&nblock, SIGCHLD); (void)_sigprocmask(SIG_BLOCK, &nblock, &oblock); switch (pid = fork()) { case -1: break; case 0: /* child */ /* * pt_chown expects the master pseudo TTY to be its * standard input. */ (void)_dup2(fildes, STDIN_FILENO); (void)_sigprocmask(SIG_SETMASK, &oblock, NULL); execl(_PATH_PTCHOWN, _PATH_PTCHOWN, (char*)NULL); _exit(EX_UNAVAILABLE); /* NOTREACHED */ default: /* parent */ /* * Just wait for the process. Error checking is * done below. */ while ((spid = _waitpid(pid, &status, 0)) == -1 && (errno == EINTR)) ; if (spid != -1 && WIFEXITED(status) && WEXITSTATUS(status) == EX_OK) { retval = 0; } else { errno = EACCES; } break; } /* * Restore process's signal mask. */ (void)_sigprocmask(SIG_SETMASK, &oblock, NULL); if (retval) { /* * pt_chown failed. Try to manually change the * permissions for the slave. */ gid = (grp = getgrnam("tty")) ? grp->gr_gid : -1; if (chown(slave, getuid(), gid) == -1 || chmod(slave, S_IRUSR | S_IWUSR | S_IWGRP) == -1) { errno = EACCES; } else { retval = 0; } } } if (!retval) { errno = serrno; } return (retval); }