summaryrefslogtreecommitdiffstats
path: root/src/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exec.c')
-rw-r--r--src/exec.c123
1 files changed, 74 insertions, 49 deletions
diff --git a/src/exec.c b/src/exec.c
index fabe757..5691c75 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -5,6 +5,7 @@
#include <string.h>
#include <errno.h>
#include <fcntl.h>
+#include <sys/stat.h>
#include <libdaemon/dlog.h>
@@ -187,42 +188,38 @@ static void *oop_read_cb(oop_source *source, int fd, oop_event event, void *user
}
static void pipe_close(int fds[]) {
- close(fds[0]);
- close(fds[1]);
+ if (fds[0] >= 0)
+ close(fds[0]);
+ if (fds[1] >= 0)
+ close(fds[1]);
}
-pid_t child_process_create(const char *file, char *const argv[], int *ifd, int *ofd, process_exit_cb_t cb, void *user) {
+pid_t child_process_create(const char *file, char *const argv[], int *ifd, int *ofd, process_exit_cb_t cb, void *user, int pipe_hack) {
pid_t pid;
- int stdin_fds[2];
- int stdout_fds[2];
- int stderr_fds[2];
+ int stdin_fds[2] = { -1, -1 };
+ int stdout_fds[2] = { -1, -1 };
+ int stderr_fds[2] = { -1, -1 };
daemon_log(LOG_INFO, "Executing child process '%s'.", file);
- if (pipe(stdin_fds) < 0) {
+ if (ofd && pipe(stdin_fds) < 0) {
daemon_log(LOG_ERR, "pipe() failed: %s", strerror(errno));
- return -1;
+ goto fail;
}
- if (pipe(stdout_fds) < 0) {
+ if (ifd && pipe(stdout_fds) < 0) {
daemon_log(LOG_ERR, "pipe() failed: %s", strerror(errno));
- pipe_close(stdin_fds);
- return -1;
+ goto fail;
}
if (pipe(stderr_fds) < 0) {
daemon_log(LOG_ERR, "pipe() failed: %s", strerror(errno));
- pipe_close(stdin_fds);
- pipe_close(stdout_fds);
- return -1;
+ goto fail;
}
if ((pid = fork()) < 0) {
daemon_log(LOG_ERR, "fork() failed: %s", strerror(errno));
- pipe_close(stdin_fds);
- pipe_close(stdout_fds);
- pipe_close(stderr_fds);
- return -1;
+ goto fail;
}
if (pid) {
@@ -240,17 +237,15 @@ pid_t child_process_create(const char *file, char *const argv[], int *ifd, int *
p->stderr_pipe = stderr_fds[0];
close(stderr_fds[1]);
- if (ifd)
+ if (ifd) {
*ifd = stdout_fds[0];
- else
- close(stdout_fds[0]);
- close(stdout_fds[1]);
+ close(stdout_fds[1]);
+ }
- if (ofd)
+ if (ofd) {
*ofd = stdin_fds[1];
- else
- close(stdin_fds[1]);
- close(stdin_fds[0]);
+ close(stdin_fds[0]);
+ }
assert(event_source && event_source->on_fd);
event_source->on_fd(event_source, p->stderr_pipe, OOP_READ, oop_read_cb, p);
@@ -261,48 +256,78 @@ pid_t child_process_create(const char *file, char *const argv[], int *ifd, int *
} else {
/* child */
- int fd;
+ int fd, efd;
close(stderr_fds[0]);
- close(stdout_fds[0]);
- close(stdin_fds[1]);
+ if (ifd) {
+ if (pipe_hack) {
+ /* This might get a problem in the future, when more tahn 127 fds have been allocated */
+ struct stat s;
+ assert(fstat(128, &s) < 0 && errno == EBADF);
+
+
+ if (dup2(stdout_fds[0], 128) < 0) {
+ daemon_log(LOG_ERR, "dup2() failed: %s", strerror(errno));
+ exit(1);
+ }
+ }
+ close(stdout_fds[0]);
+ }
+ if (ofd)
+ close(stdin_fds[1]);
- for (fd = 0; fd <= 2; fd++) {
- if (fd != stderr_fds[1] && fd != stdout_fds[1] && fd != stdin_fds[0])
+ for (fd = 0; fd <= 127; fd++) {
+ if (fd != stderr_fds[1] && (!ifd || fd != stdout_fds[1]) && (!ofd || fd != stdin_fds[0]))
close(fd);
}
- if ((stdin_fds[0] != 0 && dup2(stdin_fds[0], 0) < 0) ||
- (stdout_fds[1] != 1 && dup2(stdout_fds[1], 1) < 0) ||
- (stderr_fds[1] != 2 && dup2(stderr_fds[1], 2) < 0)) {
- daemon_log(LOG_ERR, "dup2() failed: %s", strerror(errno));
- exit(1);
+ if (ofd) {
+ if (stdin_fds[0] != 0) {
+ if (dup2(stdin_fds[0], 0) < 0) {
+ daemon_log(LOG_ERR, "dup2() failed: %s", strerror(errno));
+ exit(1);
+ }
+ close(stdin_fds[0]);
+ }
+ } else {
+ close(0);
+ if (open("/dev/null", O_RDONLY) != 0) {
+ daemon_log(LOG_ERR, "open(\"/dev/null\") != 0: %s", strerror(errno));
+ exit(1);
+ }
}
- if (stdin_fds[0] > 2) close(stdin_fds[0]);
- if (stdout_fds[1] > 2) close(stdout_fds[1]);
- if (stderr_fds[1] > 2) close(stderr_fds[1]);
-
- if (!ifd) {
- close(1);
- if (open("/dev/null", O_WRONLY) != 1) {
- daemon_log(LOG_ERR, "open(\"/dev/null\") failed: %s", strerror(errno));
+ efd = ifd ? stdout_fds[1] : stderr_fds[1];
+ if (efd != 1) {
+ if (dup2(efd, 1) < 0) {
+ daemon_log(LOG_ERR, "dup2() failed: %s", strerror(errno));
exit(1);
}
- }
- if (!ofd) {
- close(0);
- if (open("/dev/null", O_RDONLY) != 0) {
- daemon_log(LOG_ERR, "open(\"/dev/null\") failed: %s", strerror(errno));
+ if (ifd)
+ close(stdout_fds[1]);
+ }
+
+ if (stderr_fds[1] != 2){
+ if (dup2(stderr_fds[1], 2) < 0) {
+ daemon_log(LOG_ERR, "dup2() failed: %s", strerror(errno));
exit(1);
}
+
+ close(stderr_fds[1]);
}
execvp(file, argv);
daemon_log(LOG_ERR, "exec('%s', ...) failed: %s", file, strerror(errno));
exit(1);
}
+
+fail:
+ pipe_close(stdin_fds);
+ pipe_close(stdout_fds);
+ pipe_close(stderr_fds);
+
+ return (pid_t) -1;
}