#include "process.h"
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
* variable to find the program to execute.
*
* All file descriptors are closed before executing the subprocess, except for
- * fds 0, 1, and 2 and the 'n_keep_fds' fds listed in 'keep_fds'.
+ * fds 0, 1, and 2 and the 'n_keep_fds' fds listed in 'keep_fds'. Also, any of
+ * the 'n_null_fds' fds listed in 'null_fds' are replaced by /dev/null.
*
* Returns 0 if successful, otherwise a positive errno value indicating the
* error. If successful, '*pp' is assigned a new struct process that may be
* used to query the process's status. On failure, '*pp' is set to NULL. */
int
-process_start(char **argv, const int keep_fds[], size_t n_keep_fds,
+process_start(char **argv,
+ const int keep_fds[], size_t n_keep_fds,
+ const int null_fds[], size_t n_null_fds,
struct process **pp)
{
sigset_t oldsigs;
int fd;
unblock_sigchld(&oldsigs);
- for (fd = 3; fd < fd_max; fd++) {
- if (!is_member(fd, keep_fds, n_keep_fds)) {
+ for (fd = 0; fd < fd_max; fd++) {
+ if (is_member(fd, null_fds, n_null_fds)) {
+ int nullfd = open("/dev/null", O_RDWR);
+ dup2(nullfd, fd);
+ close(nullfd);
+ } else if (fd >= 3 && !is_member(fd, keep_fds, n_keep_fds)) {
close(fd);
}
}
}
int
-process_run(char **argv, int *status)
+process_run(char **argv,
+ const int keep_fds[], size_t n_keep_fds,
+ const int null_fds[], size_t n_null_fds,
+ int *status)
{
struct process *p;
int retval;
- retval = process_start(argv, NULL, 0, &p);
+ retval = process_start(argv, keep_fds, n_keep_fds, null_fds, n_null_fds,
+ &p);
if (retval) {
*status = 0;
return retval;
struct process;
void process_init(void);
-int process_start(char **argv, const int *keep_fds, size_t n_keep_fds,
+int process_start(char **argv,
+ const int *keep_fds, size_t n_keep_fds,
+ const int *null_fds, size_t n_null_fds,
struct process **);
void process_destroy(struct process *);
int process_kill(const struct process *, int signr);
-int process_run(char **argv, int *status);
+int process_run(char **argv,
+ const int *keep_fds, size_t n_keep_fds,
+ const int *null_fds, size_t n_null_fds,
+ int *status);
pid_t process_pid(const struct process *);
const char *process_name(const struct process *);
/* Start secchan. */
if (!br->controller) {
- retval = process_start(argv.names, &sockets[1], 1, &br->secchan);
+ retval = process_start(argv.names, &sockets[1], 1, NULL, 0,
+ &br->secchan);
close(sockets[1]);
} else {
- retval = process_start(argv.names, NULL, 0, &br->secchan);
+ retval = process_start(argv.names, NULL, 0, NULL, 0, &br->secchan);
}
svec_destroy(&argv);
if (retval) {