diff options
Diffstat (limited to 'src/dged/process-posix.c')
| -rw-r--r-- | src/dged/process-posix.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/src/dged/process-posix.c b/src/dged/process-posix.c new file mode 100644 index 0000000..94ceb5f --- /dev/null +++ b/src/dged/process-posix.c @@ -0,0 +1,126 @@ +#include "process.h" + +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/wait.h> + +static int create_pipe(int *read_end, int *write_end, bool read_nonblock, + bool write_nonblock) { + int pipes[2] = {0}; + if (pipe(pipes) < 0) { + return -1; + } + + if (write_nonblock) { + int flags = fcntl(pipes[1], F_GETFL, 0); + if (flags < 0) { + return -1; + } + + flags |= O_NONBLOCK; + if (fcntl(pipes[1], F_SETFL, flags) < 0) { + return -1; + } + } + + if (read_nonblock) { + int flags = fcntl(pipes[0], F_GETFL, 0); + if (flags < 0) { + return -1; + } + + flags |= O_NONBLOCK; + if (fcntl(pipes[0], F_SETFL, flags) < 0) { + return -1; + } + } + + *read_end = pipes[0]; + *write_end = pipes[1]; + + return 0; +} + +struct process_create_result process_create(char *const command[], + struct process *result) { + + int stdin_read, stdin_write; + if (create_pipe(&stdin_read, &stdin_write, false, true) < 0) { + return (struct process_create_result){ + .ok = false, + .error_message = strerror(errno), + }; + } + + int stdout_read, stdout_write; + if (create_pipe(&stdout_read, &stdout_write, true, false) < 0) { + return (struct process_create_result){ + .ok = false, + .error_message = strerror(errno), + }; + } + + int stderr_read, stderr_write; + if (create_pipe(&stderr_read, &stderr_write, true, false) < 0) { + return (struct process_create_result){ + .ok = false, + .error_message = strerror(errno), + }; + } + + pid_t pid = fork(); + if (pid == -1) { + return (struct process_create_result){ + .ok = false, + .error_message = strerror(errno), + }; + } else if (pid == 0) { + close(stdin_write); + close(stdout_read); + close(stderr_read); + + if (dup2(stdin_read, STDIN_FILENO) < 0) { + exit(16); + } + + if (dup2(stdout_write, STDOUT_FILENO) < 0) { + exit(16); + } + + if (dup2(stderr_write, STDERR_FILENO) < 0) { + exit(16); + } + + if (execvp(command[0], command) < 0) { + exit(16); + } + } else { + close(stdin_read); + close(stdout_write); + close(stderr_write); + + result->stdin = stdin_write; + result->stdout = stdout_read; + result->stderr = stderr_read; + result->id = (fd_t)pid; + result->impl = NULL; + } + + return (struct process_create_result){ + .ok = true, + }; +} + +void process_destroy(struct process *p) { (void)p; } + +bool process_running(const struct process *p) { + return waitpid(p->id, NULL, WNOHANG) == 0; +} + +bool process_kill(const struct process *p) { return kill(p->id, SIGTERM) == 0; } |
