void abort() { struct sigaction act; /* * POSIX requires we flush stdio buffers on abort. * XXX ISO C requires that abort() be async-signal-safe. */ if (__cleanup) (*__cleanup)(); sigfillset(&act.sa_mask); /* * Don't block SIGABRT to give any handler a chance; we ignore * any errors -- ISO C doesn't allow abort to return anyway. */ sigdelset(&act.sa_mask, SIGABRT); (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL); (void)raise(SIGABRT); /* * If SIGABRT was ignored, or caught and the handler returns, do * it again, only harder. */ act.sa_handler = SIG_DFL; act.sa_flags = 0; sigfillset(&act.sa_mask); (void)_sigaction(SIGABRT, &act, NULL); sigdelset(&act.sa_mask, SIGABRT); (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL); (void)raise(SIGABRT); exit(1); }
int ucbsigblock(int mask) { sigset_t oset; sigset_t nset; (void) _sigprocmask(0, (sigset_t *)0, &nset); mask2set(mask, &nset); (void) _sigprocmask(SIG_BLOCK, &nset, &oset); return (set2mask(&oset)); }
int ucbsigpause(int mask) { sigset_t set, oset; int ret; (void) _sigprocmask(0, (sigset_t *)0, &set); oset = set; mask2set(mask, &set); ret = sigsuspend(&set); (void) _sigprocmask(SIG_SETMASK, &oset, (sigset_t *)0); return (ret); }
/* * Save the calling context in (oucp) then switch to (ucp). * * Block all signals while switching contexts. get_mcontext() returns zero * when retrieving a context. * * When some other thread calls set_mcontext() to resume our thread, * the resume point causes get_mcontext() to return non-zero to us. * Signals will be blocked and we must restore the signal mask before * returning. */ int _swapcontext(ucontext_t *oucp, const ucontext_t *ucp) { int ret; ret = _sigprocmask(SIG_BLOCK, &sigset_block_all, &oucp->uc_sigmask); if (ret == 0) { if (get_mcontext(&oucp->uc_mcontext) == 0) { ret = set_mcontext(&ucp->uc_mcontext); } else { ret = _sigprocmask(SIG_SETMASK, &oucp->uc_sigmask, NULL); } } return(ret); }
int __system(const char *command) { pid_t pid, savedpid; int pstat; struct sigaction ign, intact, quitact; sigset_t newsigblock, oldsigblock; if (!command) /* just checking... */ return(1); (void)sigemptyset(&newsigblock); (void)sigaddset(&newsigblock, SIGCHLD); (void)sigaddset(&newsigblock, SIGINT); (void)sigaddset(&newsigblock, SIGQUIT); (void)_sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock); switch(pid = vfork()) { case -1: /* error */ (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); return (-1); case 0: /* child */ /* * Restore original signal dispositions and exec the command. */ (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL); _exit(127); } /* * If we are running means that the child has either completed * its execve, or has failed. * Block SIGINT/QUIT because sh -c handles it and wait for * it to clean up. */ memset(&ign, 0, sizeof(ign)); ign.sa_handler = SIG_IGN; (void)sigemptyset(&ign.sa_mask); (void)_sigaction(SIGINT, &ign, &intact); (void)_sigaction(SIGQUIT, &ign, &quitact); savedpid = pid; do { pid = _wait4(savedpid, &pstat, 0, (struct rusage *)0); } while (pid == -1 && errno == EINTR); (void)_sigaction(SIGINT, &intact, NULL); (void)_sigaction(SIGQUIT, &quitact, NULL); (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); return(pid == -1 ? -1 : pstat); }
int __system(const char *command) { pid_t pid, savedpid; int pstat; struct sigaction ign, intact, quitact; sigset_t newsigblock, oldsigblock; if (!command) /* just checking... */ return(1); /* * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save * existing signal dispositions. */ ign.sa_handler = SIG_IGN; (void)sigemptyset(&ign.sa_mask); ign.sa_flags = 0; (void)_sigaction(SIGINT, &ign, &intact); (void)_sigaction(SIGQUIT, &ign, &quitact); (void)sigemptyset(&newsigblock); (void)sigaddset(&newsigblock, SIGCHLD); (void)_sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock); switch(pid = fork()) { case -1: /* error */ break; case 0: /* child */ /* * Restore original signal dispositions and exec the command. */ (void)_sigaction(SIGINT, &intact, NULL); (void)_sigaction(SIGQUIT, &quitact, NULL); (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL); _exit(127); default: /* parent */ savedpid = pid; do { pid = _wait4(savedpid, &pstat, 0, (struct rusage *)0); } while (pid == -1 && errno == EINTR); break; } (void)_sigaction(SIGINT, &intact, NULL); (void)_sigaction(SIGQUIT, &quitact, NULL); (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); return(pid == -1 ? -1 : pstat); }
/* * Backwards compatible pause. */ int __pause() { sigset_t oset; if (_sigprocmask(SIG_BLOCK, NULL, &oset) == -1) return (-1); return (_sigsuspend(&oset)); }
FILE * tmpfile() { sigset_t set, oset; FILE *fp; int fd, sverrno; #define TRAILER "tmp.XXXXXX" char *buf; const char *tmpdir; tmpdir = NULL; if (issetugid() == 0) tmpdir = getenv("TMPDIR"); if (tmpdir == NULL) tmpdir = _PATH_TMP; (void)asprintf(&buf, "%s%s%s", tmpdir, (tmpdir[strlen(tmpdir) - 1] == '/') ? "" : "/", TRAILER); if (buf == NULL) return (NULL); sigfillset(&set); (void)_sigprocmask(SIG_BLOCK, &set, &oset); fd = mkstemp(buf); if (fd != -1) (void)unlink(buf); free(buf); (void)_sigprocmask(SIG_SETMASK, &oset, NULL); if (fd == -1) return (NULL); if ((fp = fdopen(fd, "w+")) == NULL) { sverrno = errno; (void)_close(fd); errno = sverrno; return (NULL); } return (fp); }
/* * Switch to the target context. The current signal mask is saved in ucp * and all signals are blocked. The call to set_mcontext() causes the * specified context to be switched to (usually resuming as a return from * the get_mcontext() procedure). The current context is thrown away. * * The target context being resumed is responsible for restoring the * signal mask appropriate for the target context. */ int _setcontext(ucontext_t *ucp) { int ret; ret = _sigprocmask(SIG_BLOCK, &sigset_block_all, &ucp->uc_sigmask); if (ret == 0) ret = set_mcontext(&ucp->uc_mcontext); return(ret); }
static int tmp(void) { sigset_t set, oset; int fd, len; char *envtmp = NULL; char path[MAXPATHLEN]; if (issetugid() == 0) envtmp = getenv("TMPDIR"); len = snprintf(path, sizeof(path), "%s/bt.XXXXXXXXXX", envtmp ? envtmp : "/tmp"); if (len < 0 || len >= (int)sizeof(path)) { errno = ENAMETOOLONG; return(-1); } (void)sigfillset(&set); (void)_sigprocmask(SIG_BLOCK, &set, &oset); if ((fd = mkostemp(path, O_CLOEXEC)) != -1) (void)unlink(path); (void)_sigprocmask(SIG_SETMASK, &oset, NULL); return(fd); }
static void __fail(const char *msg) { struct sigaction sa; sigset_t mask; /* Immediately block all signal handlers from running code */ sigfillset(&mask); sigdelset(&mask, SIGABRT); _sigprocmask(SIG_BLOCK, &mask, NULL); /* This may fail on a chroot jail... */ syslog(LOG_CRIT, "%s", msg); bzero(&sa, sizeof(struct sigaction)); sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = SIG_DFL; __sys_sigaction(SIGABRT, &sa, NULL); kill(getpid(), SIGABRT); _exit(127); }
int rcmd_af(char **ahost, int rport, const char *locuser, const char *remuser, const char *cmd, int *fd2p, int af) { struct addrinfo hints, *res, *ai; struct sockaddr_storage from; fd_set reads; sigset_t oldmask, newmask; pid_t pid; int s, aport, lport, timo, error; char c, *p; int refused, nres; char num[8]; static char canonnamebuf[MAXDNAME]; /* is it proper here? */ /* call rcmdsh() with specified remote shell if appropriate. */ if (!issetugid() && (p = getenv("RSH"))) { struct servent *sp = getservbyname("shell", "tcp"); if (sp && sp->s_port == rport) return (rcmdsh(ahost, rport, locuser, remuser, cmd, p)); } /* use rsh(1) if non-root and remote port is shell. */ if (geteuid()) { struct servent *sp = getservbyname("shell", "tcp"); if (sp && sp->s_port == rport) return (rcmdsh(ahost, rport, locuser, remuser, cmd, NULL)); } pid = getpid(); memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; snprintf(num, sizeof(num), "%d", ntohs(rport)); error = getaddrinfo(*ahost, num, &hints, &res); if (error) { fprintf(stderr, "rcmd: getaddrinfo: %s\n", gai_strerror(error)); if (error == EAI_SYSTEM) fprintf(stderr, "rcmd: getaddrinfo: %s\n", strerror(errno)); return (-1); } if (res->ai_canonname && strlen(res->ai_canonname) + 1 < sizeof(canonnamebuf)) { strncpy(canonnamebuf, res->ai_canonname, sizeof(canonnamebuf)); *ahost = canonnamebuf; } nres = 0; for (ai = res; ai; ai = ai->ai_next) nres++; ai = res; refused = 0; sigemptyset(&newmask); sigaddset(&newmask, SIGURG); _sigprocmask(SIG_BLOCK, (const sigset_t *)&newmask, &oldmask); for (timo = 1, lport = IPPORT_RESERVED - 1;;) { s = rresvport_af(&lport, ai->ai_family); if (s < 0) { if (errno != EAGAIN && ai->ai_next) { ai = ai->ai_next; continue; } if (errno == EAGAIN) fprintf(stderr, "rcmd: socket: All ports in use\n"); else fprintf(stderr, "rcmd: socket: %s\n", strerror(errno)); freeaddrinfo(res); _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL); return (-1); } _fcntl(s, F_SETOWN, pid); if (_connect(s, ai->ai_addr, ai->ai_addrlen) >= 0) break; _close(s); if (errno == EADDRINUSE) { lport--; continue; } if (errno == ECONNREFUSED) refused = 1; if (ai->ai_next == NULL && (!refused || timo > 16)) { fprintf(stderr, "%s: %s\n", *ahost, strerror(errno)); freeaddrinfo(res); _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL); return (-1); } if (nres > 1) { int oerrno = errno; getnameinfo(ai->ai_addr, ai->ai_addrlen, paddr, sizeof(paddr), NULL, 0, NI_NUMERICHOST); fprintf(stderr, "connect to address %s: ", paddr); errno = oerrno; perror(0); } if ((ai = ai->ai_next) == NULL) { /* refused && timo <= 16 */ struct timespec time_to_sleep, time_remaining; time_to_sleep.tv_sec = timo; time_to_sleep.tv_nsec = 0; _nanosleep(&time_to_sleep, &time_remaining); timo *= 2; ai = res; refused = 0; } if (nres > 1) { getnameinfo(ai->ai_addr, ai->ai_addrlen, paddr, sizeof(paddr), NULL, 0, NI_NUMERICHOST); fprintf(stderr, "Trying %s...\n", paddr); } } lport--; if (fd2p == 0) { _write(s, "", 1); lport = 0; } else { int s2 = rresvport_af(&lport, ai->ai_family), s3; socklen_t len = ai->ai_addrlen; int nfds; if (s2 < 0) goto bad; _listen(s2, 1); snprintf(num, sizeof(num), "%d", lport); if (_write(s, num, strlen(num)+1) != strlen(num)+1) { fprintf(stderr, "rcmd: write (setting up stderr): %s\n", strerror(errno)); _close(s2); goto bad; } nfds = max(s, s2)+1; if(nfds > FD_SETSIZE) { fprintf(stderr, "rcmd: too many files\n"); _close(s2); goto bad; } again: FD_ZERO(&reads); FD_SET(s, &reads); FD_SET(s2, &reads); errno = 0; if (_select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){ if (errno != 0) fprintf(stderr, "rcmd: select (setting up stderr): %s\n", strerror(errno)); else fprintf(stderr, "select: protocol failure in circuit setup\n"); _close(s2); goto bad; } s3 = _accept(s2, (struct sockaddr *)&from, &len); switch (from.ss_family) { case AF_INET: aport = ntohs(((struct sockaddr_in *)&from)->sin_port); break; #ifdef INET6 case AF_INET6: aport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port); break; #endif default: aport = 0; /* error */ break; } /* * XXX careful for ftp bounce attacks. If discovered, shut them * down and check for the real auxiliary channel to connect. */ if (aport == 20) { _close(s3); goto again; } _close(s2); if (s3 < 0) { fprintf(stderr, "rcmd: accept: %s\n", strerror(errno)); lport = 0; goto bad; } *fd2p = s3; if (aport >= IPPORT_RESERVED || aport < IPPORT_RESERVED / 2) { fprintf(stderr, "socket: protocol failure in circuit setup.\n"); goto bad2; } } _write(s, locuser, strlen(locuser)+1); _write(s, remuser, strlen(remuser)+1); _write(s, cmd, strlen(cmd)+1); if (_read(s, &c, 1) != 1) { fprintf(stderr, "rcmd: %s: %s\n", *ahost, strerror(errno)); goto bad2; } if (c != 0) { while (_read(s, &c, 1) == 1) { _write(STDERR_FILENO, &c, 1); if (c == '\n') break; } goto bad2; } _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL); freeaddrinfo(res); return (s); bad2: if (lport) _close(*fd2p); bad: _close(s); _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL); freeaddrinfo(res); return (-1); }
int rcmd_af(char **ahost, unsigned short rport, const char *locuser, const char *remuser, const char *cmd, int *fd2p, int af) { int s, timo = 1; ssize_t retval; pid_t pid; struct sockaddr_storage caddr, faddr; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; struct addrinfo hints; struct addrinfo *res, *resp; size_t addrlen; int rc; #define MAX_SHORTSTRLEN 6 char aport[MAX_SHORTSTRLEN]; char c; int lport = 0; #ifdef SYSV sigset_t oldmask; sigset_t newmask; struct sigaction oldaction; struct sigaction newaction; #else int oldmask; #endif /* SYSV */ fd_set fdset; int selret; char *addr; static char hostname[MAXHOSTNAMELEN]; socklen_t len; char abuf[INET6_ADDRSTRLEN]; if (!(af == AF_INET || af == AF_INET6 || af == AF_UNSPEC)) { errno = EAFNOSUPPORT; return (-1); } pid = getpid(); memset(&hints, 0, sizeof (hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; if (af == AF_INET6) { hints.ai_flags |= AI_V4MAPPED; hints.ai_family = AF_UNSPEC; } else { hints.ai_family = af; } (void) snprintf(aport, MAX_SHORTSTRLEN, "%u", ntohs(rport)); rc = getaddrinfo(*ahost, aport, &hints, &res); if (rc != 0) { (void) fprintf(stderr, _dgettext(TEXT_DOMAIN, "%s: unknown host%s\n"), *ahost, rc == EAI_AGAIN ? " (try again later)" : ""); return (-1); } resp = res; (void) strlcpy(hostname, res->ai_canonname, MAXHOSTNAMELEN); *ahost = hostname; #ifdef SYSV /* ignore SIGPIPE */ bzero((char *)&newaction, sizeof (newaction)); newaction.sa_handler = SIG_IGN; (void) _sigaction(SIGPIPE, &newaction, &oldaction); /* block SIGURG */ bzero((char *)&newmask, sizeof (newmask)); (void) _sigaddset(&newmask, SIGURG); (void) _sigprocmask(SIG_BLOCK, &newmask, &oldmask); #else oldmask = _sigblock(sigmask(SIGURG)); #endif /* SYSV */ for (;;) { s = rresvport_af(&lport, res->ai_family); if (s < 0) { int af = res->ai_family; /* * See if we have any addresses of a different type * to try. */ while (res != NULL && res->ai_family == af) res = res->ai_next; if (res != NULL) continue; if (errno == EAGAIN) (void) fprintf(stderr, _dgettext(TEXT_DOMAIN, "socket: All ports in use\n")); else perror("rcmd: socket"); #ifdef SYSV /* restore original SIGPIPE handler */ (void) _sigaction(SIGPIPE, &oldaction, (struct sigaction *)0); /* restore original signal mask */ (void) _sigprocmask(SIG_SETMASK, &oldmask, (sigset_t *)0); #else sigsetmask(oldmask); #endif /* SYSV */ freeaddrinfo(resp); return (-1); } bzero((char *)&caddr, sizeof (caddr)); bcopy(res->ai_addr, &caddr, res->ai_addrlen); addrlen = res->ai_addrlen; if (af == AF_INET6 && res->ai_addr->sa_family == AF_INET) { struct in6_addr ia6; struct sockaddr_in6 *in6addr; IN6_INADDR_TO_V4MAPPED(&((struct sockaddr_in *) res->ai_addr)->sin_addr, &ia6); in6addr = (struct sockaddr_in6 *)&caddr; in6addr->sin6_addr = ia6; in6addr->sin6_family = AF_INET6; addrlen = sizeof (struct sockaddr_in6); } (void) _fcntl(s, F_SETOWN, pid); if (connect(s, (struct sockaddr *)&caddr, addrlen) >= 0) break; (void) close(s); if (errno == EADDRINUSE) { lport = 0; continue; } if (errno == ECONNREFUSED && timo <= 16) { (void) sleep(timo); timo *= 2; continue; } if (res->ai_next != NULL) { int oerrno = errno; if (res->ai_addr->sa_family == AF_INET6) addr = (char *)&((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; else addr = (char *)&((struct sockaddr_in *) res->ai_addr)->sin_addr; (void) fprintf(stderr, _dgettext(TEXT_DOMAIN, "connect to address %s: "), inet_ntop(res->ai_addr->sa_family, addr, abuf, sizeof (abuf))); errno = oerrno; perror(0); res = res->ai_next; if (res->ai_addr->sa_family == AF_INET6) addr = (char *)&((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; else addr = (char *)&((struct sockaddr_in *) res->ai_addr)->sin_addr; (void) fprintf(stderr, _dgettext(TEXT_DOMAIN, "Trying %s...\n"), inet_ntop(res->ai_addr->sa_family, addr, abuf, sizeof (abuf))); continue; } perror(*ahost); freeaddrinfo(resp); #ifdef SYSV /* restore original SIGPIPE handler */ (void) _sigaction(SIGPIPE, &oldaction, (struct sigaction *)0); /* restore original signal mask */ (void) _sigprocmask(SIG_SETMASK, &oldmask, (sigset_t *)0); #else sigsetmask(oldmask); #endif /* SYSV */ return (-1); } lport = 0; if (fd2p == 0) { (void) write(s, "", 1); } else { int s2 = rresvport_af(&lport, res->ai_family), s3; len = (socklen_t)sizeof (faddr); if (s2 < 0) goto bad; (void) listen(s2, 1); (void) snprintf(aport, MAX_SHORTSTRLEN, "%d", lport); if (write(s, aport, strlen(aport)+1) != strlen(aport)+1) { perror(_dgettext(TEXT_DOMAIN, "write: setting up stderr")); (void) close(s2); goto bad; } FD_ZERO(&fdset); FD_SET(s, &fdset); FD_SET(s2, &fdset); while ((selret = select(FD_SETSIZE, &fdset, (fd_set *)0, (fd_set *)0, (struct timeval *)0)) > 0) { if (FD_ISSET(s, &fdset)) { /* * Something's wrong: we should get no * data on this connection at this point, * so we assume that the connection has * gone away. */ (void) close(s2); goto bad; } if (FD_ISSET(s2, &fdset)) { /* * We assume this is an incoming connect * request and proceed normally. */ s3 = accept(s2, (struct sockaddr *)&faddr, &len); FD_CLR(s2, &fdset); (void) close(s2); if (s3 < 0) { perror("accept"); lport = 0; goto bad; } else break; } } if (selret == -1) { /* * This should not happen, and we treat it as * a fatal error. */ (void) close(s2); goto bad; } *fd2p = s3; switch (faddr.ss_family) { case AF_INET: sin = (struct sockaddr_in *)&faddr; if (ntohs(sin->sin_port) >= IPPORT_RESERVED) { (void) fprintf(stderr, _dgettext(TEXT_DOMAIN, "socket: protocol failure in circuit " "setup.\n")); goto bad2; } break; case AF_INET6: sin6 = (struct sockaddr_in6 *)&faddr; if (ntohs(sin6->sin6_port) >= IPPORT_RESERVED) { (void) fprintf(stderr, _dgettext(TEXT_DOMAIN, "socket: protocol failure in circuit " "setup.\n")); goto bad2; } break; default: (void) fprintf(stderr, _dgettext(TEXT_DOMAIN, "socket: protocol failure in circuit setup.\n")); goto bad2; } } (void) write(s, locuser, strlen(locuser)+1); (void) write(s, remuser, strlen(remuser)+1); (void) write(s, cmd, strlen(cmd)+1); retval = read(s, &c, 1); if (retval != 1) { if (retval == 0) { (void) fprintf(stderr, _dgettext(TEXT_DOMAIN, "Protocol error, %s closed connection\n"), *ahost); } else if (retval < 0) { perror(*ahost); } else { (void) fprintf(stderr, _dgettext(TEXT_DOMAIN, "Protocol error, %s sent %d bytes\n"), *ahost, retval); } goto bad2; } if (c != 0) { while (read(s, &c, 1) == 1) { (void) write(2, &c, 1); if (c == '\n') break; } goto bad2; } #ifdef SYSV /* restore original SIGPIPE handler */ (void) _sigaction(SIGPIPE, &oldaction, (struct sigaction *)0); /* restore original signal mask */ (void) _sigprocmask(SIG_SETMASK, &oldmask, (sigset_t *)0); #else sigsetmask(oldmask); #endif /* SYSV */ freeaddrinfo(resp); return (s); bad2: if (lport) (void) close(*fd2p); bad: (void) close(s); #ifdef SYSV /* restore original SIGPIPE handler */ (void) _sigaction(SIGPIPE, &oldaction, (struct sigaction *)0); /* restore original signal mask */ (void) _sigprocmask(SIG_SETMASK, &oldmask, (sigset_t *)0); #else sigsetmask(oldmask); #endif /* SYSV */ freeaddrinfo(resp); return (-1); }
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); }
void __oldsigset(sigset_t *p) { _sigprocmask(SIG_SETMASK, p, NULL); }
void __newsigset(sigset_t *p) { /* The SIG_SETMASK is not significant */ _sigprocmask(SIG_SETMASK, NULL, p); }