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
127
128
129
130
|
#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) {
close(p->stdin);
close(p->stdout);
close(p->stderr);
}
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; }
|