2020-07-15 12:39:10 +02:00
|
|
|
#include "spawn.h"
|
|
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
|
|
#define LOG_MODULE "spawn"
|
|
|
|
|
#define LOG_ENABLE_DBG 0
|
|
|
|
|
#include "log.h"
|
2021-01-15 20:39:45 +00:00
|
|
|
#include "debug.h"
|
2020-07-15 12:39:10 +02:00
|
|
|
|
|
|
|
|
bool
|
2020-07-15 13:33:56 +02:00
|
|
|
spawn(struct reaper *reaper, const char *cwd, char *const argv[],
|
|
|
|
|
int stdin_fd, int stdout_fd, int stderr_fd)
|
2020-07-15 12:39:10 +02:00
|
|
|
{
|
|
|
|
|
int pipe_fds[2] = {-1, -1};
|
|
|
|
|
if (pipe2(pipe_fds, O_CLOEXEC) < 0) {
|
|
|
|
|
LOG_ERRNO("failed to create pipe");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pid_t pid = fork();
|
|
|
|
|
if (pid < 0) {
|
|
|
|
|
LOG_ERRNO("failed to fork");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pid == 0) {
|
|
|
|
|
/* Child */
|
|
|
|
|
close(pipe_fds[0]);
|
2020-07-15 13:33:56 +02:00
|
|
|
|
|
|
|
|
if ((stdin_fd >= 0 && (dup2(stdin_fd, STDIN_FILENO) < 0 || close(stdin_fd) < 0)) ||
|
|
|
|
|
(stdout_fd >= 0 && (dup2(stdout_fd, STDOUT_FILENO) < 0 || close(stdout_fd) < 0)) ||
|
|
|
|
|
(stderr_fd >= 0 && (dup2(stderr_fd, STDERR_FILENO) < 0 || close(stderr_fd) < 0)) ||
|
|
|
|
|
(cwd != NULL && chdir(cwd) < 0) ||
|
2020-07-15 12:39:10 +02:00
|
|
|
execvp(argv[0], argv) < 0)
|
|
|
|
|
{
|
|
|
|
|
(void)!write(pipe_fds[1], &errno, sizeof(errno));
|
|
|
|
|
_exit(errno);
|
|
|
|
|
}
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(false);
|
2020-07-15 12:39:10 +02:00
|
|
|
_exit(errno);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parent */
|
|
|
|
|
close(pipe_fds[1]);
|
|
|
|
|
|
|
|
|
|
int _errno;
|
|
|
|
|
static_assert(sizeof(_errno) == sizeof(errno), "errno size mismatch");
|
|
|
|
|
|
|
|
|
|
ssize_t ret = read(pipe_fds[0], &_errno, sizeof(_errno));
|
|
|
|
|
close(pipe_fds[0]);
|
|
|
|
|
|
|
|
|
|
if (ret == 0) {
|
2020-12-26 01:26:54 +01:00
|
|
|
reaper_add(reaper, pid, NULL, NULL);
|
2020-07-15 12:39:10 +02:00
|
|
|
return true;
|
|
|
|
|
} else if (ret < 0) {
|
|
|
|
|
LOG_ERRNO("failed to read from pipe");
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
2020-08-23 07:44:02 +02:00
|
|
|
LOG_ERRNO_P(_errno, "%s: failed to spawn", argv[0]);
|
2020-07-15 12:39:10 +02:00
|
|
|
errno = _errno;
|
|
|
|
|
waitpid(pid, NULL, 0);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
if (pipe_fds[0] != -1)
|
|
|
|
|
close(pipe_fds[0]);
|
|
|
|
|
if (pipe_fds[1] != -1)
|
|
|
|
|
close(pipe_fds[1]);
|
|
|
|
|
return false;
|
|
|
|
|
}
|