#include "exec.h" #if HAVE_STDBOOL_H #include #endif #include "fs.h" #include "../log.h" #include #include #if HAVE_LINUX_LIMITS_H #include #endif #include static int max_fd() { int fd_max = 0; #ifdef NR_OPEN /* from */ fd_max = NR_OPEN; if (0 < fd_max) return fd_max; #endif #ifdef _SC_OPEN_MAX /* from */ fd_max = sysconf(_SC_OPEN_MAX); if (0 < fd_max) return fd_max; #endif #ifdef _POSIX_OPEN_MAX /* from */ fd_max = _POSIX_OPEN_MAX; if (0 < fd_max) return fd_max; #endif return 256; /* random guess falllback value */ } pid_t exec_subcmd( char *const argv[], int stdin, int stdout, int stderr, bool close_fds, const char *cwd, envp_t *const envp) { pid_t pid = fork(); if (0 != pid) { /* parent */ return pid; } /* child */ /* replace "standard" FDs */ if (-1 == dup2(stdin, 0)) { sk_error("failed to replace stdin for subcmd: %s", strerror(errno)); return -1; } if (-1 == dup2(stdout, 1)) { sk_error("failed to replace stdout for subcmd: %s", strerror(errno)); return -1; } if (-1 == dup2(stderr, 2)) { sk_error("failed to replace stderr for subcmd: %s", strerror(errno)); return -1; } if (close_fds) { /* close all "non-standard" FDs */ for (int i = 3, m = max_fd(); i < m; ++i) { (void)close(i); } } /* chdir */ if (NULL != cwd) { if (-1 == chdir(cwd)) { sk_error( "error in subcommand execution: chdir(%s) failed: %s", cwd, strerror(errno)); exit(-1); } } char executable[PATH_MAX+1]; which(argv[0], executable, envp_get(envp, "PATH")); if (is_empty_string(executable)) { /* no such command found */ /* TODO: handle error */ exit(-1); } if (NULL != envp) { execve(executable, argv, *envp); } else { execv(executable, argv); } exit(-1); }