ATF_TC_BODY(closefrom_buffer, tc) { int buf[16], cur, half; size_t i; /* * Open a buffer of descriptors, close the half of * these and verify that the result is consistent. */ ATF_REQUIRE(closefrom(STDERR_FILENO + 1) == 0); cur = fcntl(0, F_MAXFD); ATF_REQUIRE(cur == STDERR_FILENO); for (i = 0; i < __arraycount(buf); i++) { buf[i] = open(path, O_RDWR | O_CREAT, 0600); ATF_REQUIRE(buf[i] >= 0); } cur = fcntl(0, F_MAXFD); ATF_REQUIRE(cur == __arraycount(buf) + STDERR_FILENO); half = STDERR_FILENO + __arraycount(buf) / 2; ATF_REQUIRE(closefrom(half) == 0); cur = fcntl(0, F_MAXFD); ATF_REQUIRE(cur == half - 1); for (i = 0; i < __arraycount(buf); i++) (void)close(buf[i]); }
/* * Test that closefrom does the right thing in a threaded programs, * specifically that it doesn't kill the thread kernel signal pipe. */ int main(int argc, char *argv[]) { pthread_t thread; void *status; int fd; int result; /* close files above stderr. The kernel pipes shouldn't be touched */ fd = STDERR_FILENO + 1; result = closefrom(fd); printf("closefrom(%d) == %d/%d\n", fd, result, errno); /* do it again: make sure that the result is -1/EBADF */ result = closefrom(fd); printf("closefrom(%d) == %d/%d\n", fd, result, errno); ASSERT(result == -1 && errno == EBADF); /* start a thread to verify the thread kernel is working */ CHECKr(pthread_create(&thread, NULL, dummy_thread, NULL)); CHECKr(pthread_join(thread, &status)); printf("dummy thread exited with status %p\n", status); SUCCEED; return 0; }
int main(void) { int i, max, fds[NUM_OPENS]; char buf[512]; for (i = 0; i < NUM_OPENS; i++) if ((fds[i] = open("/dev/null", O_RDONLY)) == -1) exit(0); /* can't test */ max = i - 1; /* should close last fd only */ closefrom(fds[max]); if (close(fds[max]) != -1) fail("failed to close highest fd"); /* make sure we can still use remaining descriptors */ for (i = 0; i < max; i++) if (read(fds[i], buf, sizeof(buf)) == -1) fail("closed descriptors it should not have"); /* should close all fds */ closefrom(fds[0]); for (i = 0; i < NUM_OPENS; i++) if (close(fds[i]) != -1) fail("failed to close from lowest fd"); }
/* * detach from tty */ static void detachfromtty(void) { nscd_rc_t rc; char *me = "detachfromtty"; if (_logfd > 0) { int i; for (i = 0; i < _logfd; i++) (void) close(i); closefrom(_logfd + 1); } else closefrom(0); (void) chdir("/"); switch (fork1()) { case (pid_t)-1: _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "unable to fork: pid = %d, %s\n", getpid(), strerror(errno)); exit(1); break; case 0: /* start the forker nscd if so configured */ _nscd_start_forker(saved_execname, saved_argc, saved_argv); break; default: exit(0); } (void) setsid(); (void) open("/dev/null", O_RDWR, 0); (void) dup(0); if (_logfd != 2) (void) dup(0); /* * start monitoring the states of the name service clients */ rc = _nscd_init_smf_monitor(); if (rc != NSCD_SUCCESS) { _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "unable to start the SMF monitor (rc = %d)\n", rc); exit(-1); } }
__dead void ctl_openconsole(const char *name) { closefrom(STDERR_FILENO + 1); execl(VMCTL_CU, VMCTL_CU, "-l", name, "-s", "9600", NULL); err(1, "failed to open the console"); }
ATF_TC_BODY(closefrom_one, tc) { pid_t pid; int sta; pid = fork(); ATF_REQUIRE(pid >= 0); if (pid == 0) { if (closefrom(1) != 0) _exit(10); _exit(fcntl(0, F_MAXFD)); } (void)wait(&sta); /* * STDIN_FILENO sould still be open; WEXITSTATUS(1) == 0. */ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != 0) atf_tc_fail("not all descriptors were closed"); }
__dead void shell_exec(const char *shell, const char *shellcmd) { const char *shellname, *ptr; char *argv0; ptr = strrchr(shell, '/'); if (ptr != NULL && *(ptr + 1) != '\0') shellname = ptr + 1; else shellname = shell; if (login_shell) xasprintf(&argv0, "-%s", shellname); else xasprintf(&argv0, "%s", shellname); setenv("SHELL", shell, 1); setblocking(STDIN_FILENO, 1); setblocking(STDOUT_FILENO, 1); setblocking(STDERR_FILENO, 1); closefrom(STDERR_FILENO + 1); execl(shell, argv0, "-c", shellcmd, (char *) NULL); fatal("execl failed"); }
__dead void shell_exec(const char *shell, const char *shellcmd) { const char *shellname, *ptr; char *argv0; int mode; ptr = strrchr(shell, '/'); if (ptr != NULL && *(ptr + 1) != '\0') shellname = ptr + 1; else shellname = shell; if (login_shell) xasprintf(&argv0, "-%s", shellname); else xasprintf(&argv0, "%s", shellname); setenv("SHELL", shell, 1); if ((mode = fcntl(STDIN_FILENO, F_GETFL)) != -1) fcntl(STDIN_FILENO, F_SETFL, mode & ~O_NONBLOCK); if ((mode = fcntl(STDOUT_FILENO, F_GETFL)) != -1) fcntl(STDOUT_FILENO, F_SETFL, mode & ~O_NONBLOCK); if ((mode = fcntl(STDERR_FILENO, F_GETFL)) != -1) fcntl(STDERR_FILENO, F_SETFL, mode & ~O_NONBLOCK); closefrom(STDERR_FILENO + 1); execl(shell, argv0, "-c", shellcmd, (char *) NULL); fatal("execl failed"); }
static int daemonize_self(void) { pid_t pid; int fd; (void) close(STDIN_FILENO); if ((fd = open(DEV_NULL, O_RDONLY)) == -1) { (void) printf("Could not open /dev/null: %s\n", strerror(errno)); } else if (fd != STDIN_FILENO) { (void) dup2(fd, STDIN_FILENO); (void) close(fd); } (void) dup2(STDERR_FILENO, STDOUT_FILENO); closefrom(3); if ((pid = fork1()) < 0) { (void) printf("fork() failed: %s\n", strerror(errno)); return (1); } if (pid != 0) exit(0); (void) setsid(); (void) chdir("/"); return (0); }
static int has_fs(char *prog, char *slice) { pid_t pid; int loc; mode_t mode = S_IRUSR | S_IWUSR; switch ((pid = fork1())) { case 0: /* child process */ closefrom(1); (void) open("/dev/null", O_WRONLY, mode); (void) open("/dev/null", O_WRONLY, mode); (void) execl(prog, "fstyp", slice, NULL); _exit(1); break; case -1: return (0); default: /* parent process */ break; } (void) waitpid(pid, &loc, 0); if (WIFEXITED(loc) && WEXITSTATUS(loc) == 0) { return (1); } return (0); }
/* * close_all_beyond() * * Close all file descriptors after the given keep_fd, which is the * highest fd to keep open. See * * http://stackoverflow.com/questions/899038/getting-the-highest-allocated-file-descriptor */ void close_all_beyond( int keep_fd ) { # ifdef HAVE_CLOSEFROM closefrom(keep_fd + 1); # elif defined(F_CLOSEM) /* * From 'Writing Reliable AIX Daemons,' SG24-4946-00, * by Eric Agar (saves us from doing 32767 system * calls) */ if (fcntl(keep_fd + 1, F_CLOSEM, 0) == -1) msyslog(LOG_ERR, "F_CLOSEM(%d): %m", keep_fd + 1); # else /* !HAVE_CLOSEFROM && !F_CLOSEM follows */ int fd; int max_fd; /* includes POSIX case */ max_fd = GETDTABLESIZE(); for (fd = keep_fd + 1; fd < max_fd; fd++) close(fd); # endif /* !HAVE_CLOSEFROM && !F_CLOSEM */ }
int mproc_fork(struct mproc *p, const char *path, char *argv[]) { int sp[2]; if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0) return (-1); io_set_nonblocking(sp[0]); io_set_nonblocking(sp[1]); if ((p->pid = fork()) == -1) goto err; if (p->pid == 0) { /* child process */ dup2(sp[0], STDIN_FILENO); if (closefrom(STDERR_FILENO + 1) < 0) exit(1); execv(path, argv); err(1, "execv: %s", path); } /* parent process */ close(sp[0]); mproc_init(p, sp[1]); return (0); err: log_warn("warn: Failed to start process %s, instance of %s", argv[0], path); close(sp[0]); close(sp[1]); return (-1); }
// A wsh client will need lots of fds gint wsh_client_init_fds(GError **err) { g_assert(err != NULL); g_assert(*err == NULL); WSH_CLIENT_ERROR = g_quark_from_static_string("wsh_client_error"); struct rlimit rlp; if (getrlimit(RLIMIT_NOFILE, &rlp)) { *err = g_error_new(WSH_CLIENT_ERROR, WSH_CLIENT_RLIMIT_ERR, "getrlimit: %s", strerror(errno)); return 1; } // Raise rlimits to max allowed for user rlp.rlim_cur = rlp.rlim_max - 1; if (setrlimit(RLIMIT_NOFILE, &rlp)) { *err = g_error_new(WSH_CLIENT_ERROR, WSH_CLIENT_RLIMIT_ERR, "setrlimit: %s", strerror(errno)); return 2; } (void) closefrom(STDERR_FILENO + 1); return 0; }
static void * closer(void *arg) { pthread_mutex_lock(&closermtx); while (!quit) { while (!riseandwhine) pthread_cond_wait(&closercv, &closermtx); riseandwhine = 0; pthread_mutex_unlock(&closermtx); /* try to catch a random slot */ usleep(random() % 100000); /* * wide-angle disintegration beam, but takes care * of the client rumpkernel communication socket. */ closefrom(3); pthread_mutex_lock(&closermtx); } pthread_mutex_unlock(&closermtx); return NULL; }
static int pipeline(char **ppargv, char **asargv) { int pipedes[4]; int active = 0; int rval = 0; pid_t pid_pp, pid_f, pid_as; if (pipe(pipedes) == -1 || pipe(pipedes + 2) == -1) { perror("pipe"); return (4); } if ((pid_pp = invoke(ppargv, -1, pipedes[0])) > 0) active++; if (verbose) (void) fprintf(stderr, "| "); if ((pid_f = filter(pipedes[1], pipedes[2])) > 0) active++; if (verbose) (void) fprintf(stderr, "| "); if ((pid_as = invoke(asargv, pipedes[3], -1)) > 0) active++; if (verbose) { (void) fprintf(stderr, "\n"); (void) fflush(stderr); } closefrom(3); if (active != 3) return (5); while (active != 0) { pid_t pid; int stat; if ((pid = wait(&stat)) == -1) { rval++; break; } if (!WIFEXITED(stat)) continue; if (pid == pid_pp || pid == pid_f || pid == pid_as) { active--; if (WEXITSTATUS(stat) != 0) rval++; } } return (rval); }
struct sandbox * startChild(void *data) { int procd, pid, sv[2]; struct sandbox *newsandbox; if ((newsandbox = malloc(sizeof (struct sandbox))) == NULL) err(1, "Couldn't allocate memory for sandbox"); sv[0] = sv[1] = 0; if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) < 0 ) err(1, "zcaplib: socketpair()"); pid = pdfork(&procd, 0); if (pid == 0 ) { cap_rights_t stdin_cap; cap_rights_t stdout_cap; cap_rights_t stderr_cap; cap_rights_t socket_cap; cap_rights_init(&stdin_cap, CAP_READ); cap_rights_init(&stderr_cap, CAP_WRITE, CAP_FSTAT); cap_rights_init(&stdout_cap, CAP_WRITE); if (dup2(sv[0], 3) != 3) err(1, "Couldn't duplicate fd"); closefrom(4); cap_rights_init(&socket_cap, CAP_WRITE, CAP_READ, CAP_POLL_EVENT); if (cap_rights_limit(STDIN_FILENO, &stdin_cap) < 0) err(1, "Couldn't limit stdin"); if (cap_rights_limit(STDOUT_FILENO, &stdout_cap) < 0) err(1, "Couldn't limit stdout"); if (cap_rights_limit(STDERR_FILENO, &stderr_cap) < 0) err(1, "Couldn't limit stderr"); if (cap_rights_limit(3, &socket_cap) < 0) err(1, "Couldn't limit sandbox socket"); /* execl() zlibworker */ if ( execl("/usr/libexec/zlibworker", "zlibworker", NULL) < 0) err(1, "Couldn't find zlibworker."); exit(0); } else if (pid == -1) { err(1, "Couldn't fork"); } else { signal(SIGCHLD, suicide); atexit(killChild); newsandbox->dataptr = data; newsandbox->pd = procd; newsandbox->socket = sv[1]; debug("DEBUG: We have started a new sandbox.\n"); debug("\tdata: %p pd: %d, socket: %d\n", data, newsandbox->pd, newsandbox->socket); } return (newsandbox); }
static int queue_proc_init(struct passwd *pw, int server) { int sp[2]; uint32_t version; errno = 0; if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0) { log_warn("warn: queue-proc: socketpair"); return (0); } if ((pid = fork()) == -1) { log_warn("warn: queue-proc: fork"); goto err; } if (pid == 0) { /* child process */ dup2(sp[0], STDIN_FILENO); if (closefrom(STDERR_FILENO + 1) < 0) exit(1); execl(execpath, "queue_ramproc", NULL); err(1, "execl"); } /* parent process */ close(sp[0]); imsg_init(&ibuf, sp[1]); version = PROC_QUEUE_API_VERSION; imsg_compose(&ibuf, PROC_QUEUE_INIT, 0, 0, -1, &version, sizeof(version)); queue_api_on_message_create(queue_proc_message_create); queue_api_on_message_commit(queue_proc_message_commit); queue_api_on_message_delete(queue_proc_message_delete); queue_api_on_message_fd_r(queue_proc_message_fd_r); queue_api_on_message_corrupt(queue_proc_message_corrupt); queue_api_on_envelope_create(queue_proc_envelope_create); queue_api_on_envelope_delete(queue_proc_envelope_delete); queue_api_on_envelope_update(queue_proc_envelope_update); queue_api_on_envelope_load(queue_proc_envelope_load); queue_api_on_envelope_walk(queue_proc_envelope_walk); queue_proc_call(); queue_proc_end(); return (1); err: close(sp[0]); close(sp[1]); return (0); }
static int xorg_backtrace_pstack(void) { pid_t kidpid; int pipefd[2]; if (pipe(pipefd) != 0) { return -1; } kidpid = fork1(); if (kidpid == -1) { /* ERROR */ return -1; } else if (kidpid == 0) { /* CHILD */ char parent[16]; seteuid(0); close(STDIN_FILENO); close(STDOUT_FILENO); dup2(pipefd[1], STDOUT_FILENO); closefrom(STDERR_FILENO); snprintf(parent, sizeof(parent), "%d", getppid()); execle("/usr/bin/pstack", "pstack", parent, NULL); exit(1); } else { /* PARENT */ char btline[256]; int kidstat; int bytesread; int done = 0; close(pipefd[1]); while (!done) { bytesread = read(pipefd[0], btline, sizeof(btline) - 1); if (bytesread > 0) { btline[bytesread] = 0; ErrorFSigSafe("%s", btline); } else if ((bytesread < 0) || ((errno != EINTR) && (errno != EAGAIN))) done = 1; } close(pipefd[0]); waitpid(kidpid, &kidstat, 0); if (kidstat != 0) return -1; } return 0; }
int isc_priv_init(int lstderr) { int i, socks[2], cmd; logmsg(LOG_NOTICE, "Starting privilege separation"); log_stderr = lstderr; /* Create sockets */ if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, socks) == -1) fatal("socketpair() failed"); switch (child_pid = fork()) { case -1: fatal("failed to fork() for privsep"); case 0: close(socks[0]); priv_fd = socks[1]; return (0); default: break; } for (i = 1; i < _NSIG; i++) signal(i, SIG_DFL); signal(SIGALRM, sig_pass_to_chld); signal(SIGTERM, sig_pass_to_chld); signal(SIGHUP, sig_pass_to_chld); signal(SIGINT, sig_pass_to_chld); signal(SIGCHLD, sig_got_chld); /* Father - close unneeded sockets */ for (i = STDERR_FILENO + 1; i < socks[0]; i++) close(i); closefrom(socks[0] + 1); setproctitle("[priv]"); while (cur_state != STATE_QUIT) { if (may_read(socks[0], &cmd, sizeof(int))) break; switch (cmd) { case PRIV_BIND: parent_bind(socks[0]); break; default: logmsg(LOG_ERR, "[priv]: unknown command %d", cmd); _exit(1); /* NOTREACHED */ } } _exit(0); }
pid_t process_spawn_pipe(FILE *inout[2], const char *command) { pid_t pid; int pipes[4]; char *argv[4]; /* Parent read/child write pipe */ if (pipe(&pipes[0]) == -1) return (-1); /* Child read/parent write pipe */ if (pipe(&pipes[2]) == -1) { close(pipes[0]); close(pipes[1]); return (-1); } argv[0] = __DECONST(char *, "sh"); argv[1] = __DECONST(char *, "-c"); argv[2] = __DECONST(char *, command); argv[3] = NULL; pid = fork(); if (pid > 0) { /* Parent process */ inout[0] = fdopen(pipes[0], "r"); inout[1] = fdopen(pipes[3], "w"); close(pipes[1]); close(pipes[2]); return (pid); } else if (pid == 0) { close(pipes[0]); close(pipes[3]); if (pipes[1] != STDOUT_FILENO) { dup2(pipes[1], STDOUT_FILENO); close(pipes[1]); } if (pipes[2] != STDIN_FILENO) { dup2(pipes[2], STDIN_FILENO); close(pipes[2]); } closefrom(STDERR_FILENO + 1); execve(_PATH_BSHELL, argv, environ); exit(127); } return (-1); /* ? */ }
int main(int argc, char *argv[]) { const char *file = "/dev/null"; int i, n, fds[10]; struct sigaction act; if (argc > 1) { (void) fprintf(stderr, "Usage: %s\n", argv[0]); return (EXIT_FAILURE); } act.sa_handler = interrupt; act.sa_flags = 0; (void) sigemptyset(&act.sa_mask); (void) sigaction(SIGUSR1, &act, NULL); closefrom(0); n = 0; /* * With all of our file descriptors closed, wait here spinning in bogus * ioctl() calls until DTrace hits us with a SIGUSR1 to start the test. */ if (sigsetjmp(env, 1) == 0) { for (;;) (void) ioctl(-1, 0, NULL); } /* * To test the fds[] array, we open /dev/null (a file with reliable * pathname and properties) using various flags and seek offsets. */ fds[n++] = open(file, O_RDONLY); fds[n++] = open(file, O_WRONLY); fds[n++] = open(file, O_RDWR); fds[n++] = open(file, O_RDWR | O_APPEND | O_CREAT | O_NOCTTY | O_NONBLOCK | O_NDELAY | O_SYNC | O_TRUNC | 0666); fds[n++] = open(file, O_RDWR); (void) lseek(fds[n - 1], 123, SEEK_SET); /* * Once we have all the file descriptors in the state we want to test, * issue a bogus ioctl() on each fd with cmd 0 and arg NULL to whack * our DTrace script into recording the content of the fds[] array. */ for (i = 0; i < n; i++) (void) ioctl(fds[i], 0, NULL); assert(n <= sizeof (fds) / sizeof (fds[0])); exit(0); }
int start_daemon(void) { closefrom(0); (void) open("/dev/null", O_RDONLY); (void) open("/dev/null", O_WRONLY); (void) dup(1); (void) setsid(); return (execl(_PATH_KCFD, _PATH_KCFD, (char *)0)); }
ATF_TC_BODY(closefrom_basic, tc) { int fd, cur1, cur2; (void)closefrom(STDERR_FILENO + 1); fd = open(path, O_RDONLY | O_CREAT, 0400); ATF_REQUIRE(fd >= 0); cur1 = fcntl(0, F_MAXFD); ATF_REQUIRE(cur1 == STDERR_FILENO + 1); ATF_REQUIRE(closefrom(cur1) == 0); cur2 = fcntl(0, F_MAXFD); ATF_REQUIRE(cur1 - 1 == cur2); ATF_REQUIRE(close(fd) == -1); ATF_REQUIRE(unlink(path) == 0); }
static void * table_proc_open(struct table *table) { int sp[2]; struct table_proc_priv *priv; char *environ_new[2]; struct table_open_params op; errno = 0; if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0) { log_warn("warn: table-proc: socketpair"); return (NULL); } priv = xcalloc(1, sizeof(*priv), "table_proc_open"); if ((priv->pid = fork()) == -1) { log_warn("warn: table-proc: fork"); goto err; } if (priv->pid == 0) { /* child process */ dup2(sp[0], STDIN_FILENO); if (closefrom(STDERR_FILENO + 1) < 0) exit(1); environ_new[0] = "PATH=" _PATH_DEFPATH; environ_new[1] = (char *)NULL; environ = environ_new; execle("/bin/sh", "/bin/sh", "-c", table->t_config, (char *)NULL, environ_new); fatal("execl"); } /* parent process */ close(sp[0]); imsg_init(&priv->ibuf, sp[1]); memset(&op, 0, sizeof op); op.version = PROC_TABLE_API_VERSION; (void)strlcpy(op.name, table->t_name, sizeof op.name); imsg_compose(&priv->ibuf, PROC_TABLE_OPEN, 0, 0, -1, &op, sizeof op); table_proc_call(priv); table_proc_end(); return (priv); err: free(priv); close(sp[0]); close(sp[1]); return (NULL); }
/* * Close all descriptors, startfd and higher except those listed * in pfds. */ void closefrom_except(int startfd, struct preserved_fd_list *pfds) { int debug_fd, fd, lastfd = -1; struct preserved_fd *pfd, *pfd_next; fd_set *fdsp; debug_decl(closefrom_except, SUDO_DEBUG_UTIL) debug_fd = sudo_debug_fd_get(); /* First, relocate preserved fds to be as contiguous as possible. */ TAILQ_FOREACH_REVERSE_SAFE(pfd, pfds, preserved_fd_list, entries, pfd_next) { if (pfd->highfd < startfd) continue; fd = dup(pfd->highfd); if (fd == -1) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, "dup %d", pfd->highfd); if (errno == EBADF) { TAILQ_REMOVE(pfds, pfd, entries); continue; } /* NOTE: still need to adjust lastfd below with unchanged lowfd. */ } else if (fd < pfd->highfd) { pfd->lowfd = fd; fd = pfd->highfd; if (fd == debug_fd) debug_fd = sudo_debug_fd_set(pfd->lowfd); sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "dup %d -> %d", pfd->highfd, pfd->lowfd); } if (fd != -1) (void) close(fd); if (pfd->lowfd > lastfd) lastfd = pfd->lowfd; /* highest (relocated) preserved fd */ } if (lastfd == -1) { /* No fds to preserve. */ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "closefrom(%d)", startfd); closefrom(startfd); debug_return; } /* Create bitmap of preserved (relocated) fds. */ fdsp = ecalloc(howmany(lastfd + 1, NFDBITS), sizeof(fd_mask)); TAILQ_FOREACH(pfd, pfds, entries) { FD_SET(pfd->lowfd, fdsp); }
/* * Invoked in the child's child to initialize the slave side of the pty and set * of file descriptors for forking the child. */ static int ps_init_slavepty(int mfd) { char *slavename; int sfd, setup; if ((slavename = ptsname(mfd)) == NULL) { perror("child's child: ptsname"); return (-1); } (void) close(mfd); if ((sfd = open(slavename, O_RDWR)) < 0) { perror("child's child: open pty"); return (-1); } if ((setup = ioctl(sfd, I_FIND, "ldterm")) < 0) { perror("child's child: ioctl(I_FIND, \"ldterm\")"); return (-1); } if (setup == 0) { if (ioctl(sfd, I_PUSH, "ptem") < 0) { perror("child's child: ioctl(I_PUSH, \"ptem\")"); return (-1); } if (ioctl(sfd, I_PUSH, "ldterm") < 0) { perror("child's child: ioctl(I_PUSH, \"ldterm\")"); return (-1); } if (ioctl(sfd, I_PUSH, "ttcompat") < 0) { perror("child's child: ioctl(I_PUSH, \"ttcompat\")"); return (-1); } } if (dup2(sfd, STDIN_FILENO) != STDIN_FILENO || dup2(sfd, STDOUT_FILENO) != STDOUT_FILENO || dup2(sfd, STDERR_FILENO) != STDERR_FILENO) { perror("child's child: dup2"); return (-1); } closefrom(STDERR_FILENO + 1); return (0); }
static int scheduler_proc_init(void) { int sp[2], r; uint32_t version; errno = 0; if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0) { log_warn("warn: scheduler-proc: socketpair"); goto err; } if ((pid = fork()) == -1) { log_warn("warn: scheduler-proc: fork"); goto err; } if (pid == 0) { /* child process */ dup2(sp[0], STDIN_FILENO); if (closefrom(STDERR_FILENO + 1) < 0) exit(1); execl(execpath, "scheduler-proc", NULL); err(1, "execl"); } /* parent process */ close(sp[0]); imsg_init(&ibuf, sp[1]); version = PROC_SCHEDULER_API_VERSION; imsg_compose(&ibuf, PROC_SCHEDULER_INIT, 0, 0, -1, &version, sizeof(version)); scheduler_proc_call(); scheduler_proc_read(&r, sizeof(r)); scheduler_proc_end(); return (r); err: close(sp[0]); close(sp[1]); fatalx("scheduler-proc: exiting"); return (0); }
void VSUB_closefrom(int fd) { assert(fd >= 0); #ifdef HAVE_CLOSEFROM closefrom(fd); #else int i = sysconf(_SC_OPEN_MAX); assert(i > 0); for (; i > fd; i--) (void)close(i); #endif }
static inline bool try_close_from(const int first_fd) { #if defined(F_CLOSEM) return -1 != fcntl(first_fd, F_CLOSEM); #elif defined(HAS_CLOSEFROM) /* Returns nothing on Solaris; NetBSD has F_CLOSEM and closefrom() * equivalent to the above. Thus prefer F_CLOSEM due to potential * error. */ closefrom(first_fd); return TRUE; #else (void) first_fd; return FALSE; #endif /* HAS_CLOSEFROM */ }
/* * call-seq: * IO.closefrom(lowfd) * * Close all open file descriptors (associated with the current process) that * are greater than or equal to +lowfd+. * * This method uses your system's builtin closefrom() function, if supported. * Otherwise, it uses a manual, and (probably) less efficient approach. * *-- * The manual approach was copied from the closefrom() man page on Solaris 9. */ static VALUE io_closefrom(VALUE klass, VALUE v_low_fd){ #if defined(HAVE_CLOSEFROM) && !defined(HAVE_RB_RESERVED_FD_P) /* we can't safely use closefrom() if the RubyVM reserves FDs */ closefrom(NUM2INT(v_low_fd)); #else int i, lowfd; int maxfd = open_max(); lowfd = NUM2INT(v_low_fd); for(i = lowfd; i < maxfd; i++) { if(!RB_RESERVED_FD_P(i)) close(i); } #endif return klass; }