1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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; }
|