1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2019 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker */
5*8617a60dSAndroid Build Coastguard Worker
6*8617a60dSAndroid Build Coastguard Worker #include <errno.h>
7*8617a60dSAndroid Build Coastguard Worker #include <fcntl.h>
8*8617a60dSAndroid Build Coastguard Worker #include <stdbool.h>
9*8617a60dSAndroid Build Coastguard Worker #include <stdlib.h>
10*8617a60dSAndroid Build Coastguard Worker #include <string.h>
11*8617a60dSAndroid Build Coastguard Worker #include <sys/wait.h>
12*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
13*8617a60dSAndroid Build Coastguard Worker
14*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
15*8617a60dSAndroid Build Coastguard Worker #include "subprocess.h"
16*8617a60dSAndroid Build Coastguard Worker
17*8617a60dSAndroid Build Coastguard Worker #define MAX_CB_BUF_SIZE 2048
18*8617a60dSAndroid Build Coastguard Worker
init_target_private(struct subprocess_target * target)19*8617a60dSAndroid Build Coastguard Worker static int init_target_private(struct subprocess_target *target)
20*8617a60dSAndroid Build Coastguard Worker {
21*8617a60dSAndroid Build Coastguard Worker switch (target->type) {
22*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER:
23*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER_NULL_TERMINATED:
24*8617a60dSAndroid Build Coastguard Worker case TARGET_CALLBACK:
25*8617a60dSAndroid Build Coastguard Worker return pipe(target->priv.pipefd);
26*8617a60dSAndroid Build Coastguard Worker default:
27*8617a60dSAndroid Build Coastguard Worker return 0;
28*8617a60dSAndroid Build Coastguard Worker }
29*8617a60dSAndroid Build Coastguard Worker }
30*8617a60dSAndroid Build Coastguard Worker
flags_for_fd(int fd)31*8617a60dSAndroid Build Coastguard Worker static int flags_for_fd(int fd)
32*8617a60dSAndroid Build Coastguard Worker {
33*8617a60dSAndroid Build Coastguard Worker switch (fd) {
34*8617a60dSAndroid Build Coastguard Worker case STDIN_FILENO:
35*8617a60dSAndroid Build Coastguard Worker return O_RDONLY;
36*8617a60dSAndroid Build Coastguard Worker case STDOUT_FILENO:
37*8617a60dSAndroid Build Coastguard Worker case STDERR_FILENO:
38*8617a60dSAndroid Build Coastguard Worker return O_WRONLY;
39*8617a60dSAndroid Build Coastguard Worker default:
40*8617a60dSAndroid Build Coastguard Worker return -1;
41*8617a60dSAndroid Build Coastguard Worker }
42*8617a60dSAndroid Build Coastguard Worker }
43*8617a60dSAndroid Build Coastguard Worker
connect_process_target(struct subprocess_target * target,int fd)44*8617a60dSAndroid Build Coastguard Worker static int connect_process_target(struct subprocess_target *target, int fd)
45*8617a60dSAndroid Build Coastguard Worker {
46*8617a60dSAndroid Build Coastguard Worker int target_fd;
47*8617a60dSAndroid Build Coastguard Worker
48*8617a60dSAndroid Build Coastguard Worker switch (target->type) {
49*8617a60dSAndroid Build Coastguard Worker case TARGET_NULL:
50*8617a60dSAndroid Build Coastguard Worker target_fd = open("/dev/null", flags_for_fd(fd));
51*8617a60dSAndroid Build Coastguard Worker break;
52*8617a60dSAndroid Build Coastguard Worker case TARGET_FD:
53*8617a60dSAndroid Build Coastguard Worker target_fd = target->fd;
54*8617a60dSAndroid Build Coastguard Worker break;
55*8617a60dSAndroid Build Coastguard Worker case TARGET_FILE:
56*8617a60dSAndroid Build Coastguard Worker target_fd = fileno(target->file);
57*8617a60dSAndroid Build Coastguard Worker break;
58*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER:
59*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER_NULL_TERMINATED:
60*8617a60dSAndroid Build Coastguard Worker case TARGET_CALLBACK:
61*8617a60dSAndroid Build Coastguard Worker switch (fd) {
62*8617a60dSAndroid Build Coastguard Worker case STDIN_FILENO:
63*8617a60dSAndroid Build Coastguard Worker target_fd = target->priv.pipefd[0];
64*8617a60dSAndroid Build Coastguard Worker close(target->priv.pipefd[1]);
65*8617a60dSAndroid Build Coastguard Worker break;
66*8617a60dSAndroid Build Coastguard Worker case STDOUT_FILENO:
67*8617a60dSAndroid Build Coastguard Worker case STDERR_FILENO:
68*8617a60dSAndroid Build Coastguard Worker target_fd = target->priv.pipefd[1];
69*8617a60dSAndroid Build Coastguard Worker close(target->priv.pipefd[0]);
70*8617a60dSAndroid Build Coastguard Worker break;
71*8617a60dSAndroid Build Coastguard Worker default:
72*8617a60dSAndroid Build Coastguard Worker return -1;
73*8617a60dSAndroid Build Coastguard Worker }
74*8617a60dSAndroid Build Coastguard Worker break;
75*8617a60dSAndroid Build Coastguard Worker default:
76*8617a60dSAndroid Build Coastguard Worker return -1;
77*8617a60dSAndroid Build Coastguard Worker }
78*8617a60dSAndroid Build Coastguard Worker
79*8617a60dSAndroid Build Coastguard Worker return dup2(target_fd, fd);
80*8617a60dSAndroid Build Coastguard Worker }
81*8617a60dSAndroid Build Coastguard Worker
process_target_input_buffer(struct subprocess_target * target)82*8617a60dSAndroid Build Coastguard Worker static int process_target_input_buffer(struct subprocess_target *target)
83*8617a60dSAndroid Build Coastguard Worker {
84*8617a60dSAndroid Build Coastguard Worker ssize_t write_rv;
85*8617a60dSAndroid Build Coastguard Worker size_t bytes_to_write;
86*8617a60dSAndroid Build Coastguard Worker char *buf;
87*8617a60dSAndroid Build Coastguard Worker
88*8617a60dSAndroid Build Coastguard Worker switch (target->type) {
89*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER:
90*8617a60dSAndroid Build Coastguard Worker bytes_to_write = target->buffer.size;
91*8617a60dSAndroid Build Coastguard Worker break;
92*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER_NULL_TERMINATED:
93*8617a60dSAndroid Build Coastguard Worker bytes_to_write = strlen(target->buffer.buf);
94*8617a60dSAndroid Build Coastguard Worker break;
95*8617a60dSAndroid Build Coastguard Worker default:
96*8617a60dSAndroid Build Coastguard Worker return -1;
97*8617a60dSAndroid Build Coastguard Worker }
98*8617a60dSAndroid Build Coastguard Worker
99*8617a60dSAndroid Build Coastguard Worker buf = target->buffer.buf;
100*8617a60dSAndroid Build Coastguard Worker while (bytes_to_write) {
101*8617a60dSAndroid Build Coastguard Worker write_rv = write(target->priv.pipefd[1], buf, bytes_to_write);
102*8617a60dSAndroid Build Coastguard Worker if (write_rv <= 0)
103*8617a60dSAndroid Build Coastguard Worker return -1;
104*8617a60dSAndroid Build Coastguard Worker buf += write_rv;
105*8617a60dSAndroid Build Coastguard Worker bytes_to_write -= write_rv;
106*8617a60dSAndroid Build Coastguard Worker }
107*8617a60dSAndroid Build Coastguard Worker
108*8617a60dSAndroid Build Coastguard Worker return 0;
109*8617a60dSAndroid Build Coastguard Worker }
110*8617a60dSAndroid Build Coastguard Worker
process_target_input_cb(struct subprocess_target * target)111*8617a60dSAndroid Build Coastguard Worker static int process_target_input_cb(struct subprocess_target *target)
112*8617a60dSAndroid Build Coastguard Worker {
113*8617a60dSAndroid Build Coastguard Worker ssize_t write_rv, bytes_to_write;
114*8617a60dSAndroid Build Coastguard Worker char buf[MAX_CB_BUF_SIZE];
115*8617a60dSAndroid Build Coastguard Worker char *bufptr;
116*8617a60dSAndroid Build Coastguard Worker
117*8617a60dSAndroid Build Coastguard Worker for (;;) {
118*8617a60dSAndroid Build Coastguard Worker bytes_to_write = target->callback.cb(buf, MAX_CB_BUF_SIZE,
119*8617a60dSAndroid Build Coastguard Worker target->callback.data);
120*8617a60dSAndroid Build Coastguard Worker if (bytes_to_write < 0 || bytes_to_write > MAX_CB_BUF_SIZE)
121*8617a60dSAndroid Build Coastguard Worker return -1;
122*8617a60dSAndroid Build Coastguard Worker if (bytes_to_write == 0)
123*8617a60dSAndroid Build Coastguard Worker return 0;
124*8617a60dSAndroid Build Coastguard Worker
125*8617a60dSAndroid Build Coastguard Worker bufptr = buf;
126*8617a60dSAndroid Build Coastguard Worker while (bytes_to_write) {
127*8617a60dSAndroid Build Coastguard Worker write_rv = write(target->priv.pipefd[1], bufptr,
128*8617a60dSAndroid Build Coastguard Worker bytes_to_write);
129*8617a60dSAndroid Build Coastguard Worker if (write_rv <= 0)
130*8617a60dSAndroid Build Coastguard Worker return -1;
131*8617a60dSAndroid Build Coastguard Worker bufptr += write_rv;
132*8617a60dSAndroid Build Coastguard Worker bytes_to_write -= write_rv;
133*8617a60dSAndroid Build Coastguard Worker }
134*8617a60dSAndroid Build Coastguard Worker }
135*8617a60dSAndroid Build Coastguard Worker }
136*8617a60dSAndroid Build Coastguard Worker
process_target_input(struct subprocess_target * target)137*8617a60dSAndroid Build Coastguard Worker static int process_target_input(struct subprocess_target *target)
138*8617a60dSAndroid Build Coastguard Worker {
139*8617a60dSAndroid Build Coastguard Worker int rv;
140*8617a60dSAndroid Build Coastguard Worker
141*8617a60dSAndroid Build Coastguard Worker switch (target->type) {
142*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER:
143*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER_NULL_TERMINATED:
144*8617a60dSAndroid Build Coastguard Worker case TARGET_CALLBACK:
145*8617a60dSAndroid Build Coastguard Worker break;
146*8617a60dSAndroid Build Coastguard Worker default:
147*8617a60dSAndroid Build Coastguard Worker return 0;
148*8617a60dSAndroid Build Coastguard Worker }
149*8617a60dSAndroid Build Coastguard Worker
150*8617a60dSAndroid Build Coastguard Worker close(target->priv.pipefd[0]);
151*8617a60dSAndroid Build Coastguard Worker switch (target->type) {
152*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER:
153*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER_NULL_TERMINATED:
154*8617a60dSAndroid Build Coastguard Worker rv = process_target_input_buffer(target);
155*8617a60dSAndroid Build Coastguard Worker break;
156*8617a60dSAndroid Build Coastguard Worker case TARGET_CALLBACK:
157*8617a60dSAndroid Build Coastguard Worker rv = process_target_input_cb(target);
158*8617a60dSAndroid Build Coastguard Worker break;
159*8617a60dSAndroid Build Coastguard Worker default:
160*8617a60dSAndroid Build Coastguard Worker return -1;
161*8617a60dSAndroid Build Coastguard Worker }
162*8617a60dSAndroid Build Coastguard Worker
163*8617a60dSAndroid Build Coastguard Worker close(target->priv.pipefd[1]);
164*8617a60dSAndroid Build Coastguard Worker return rv;
165*8617a60dSAndroid Build Coastguard Worker }
166*8617a60dSAndroid Build Coastguard Worker
process_target_output_buffer(struct subprocess_target * target)167*8617a60dSAndroid Build Coastguard Worker static int process_target_output_buffer(struct subprocess_target *target)
168*8617a60dSAndroid Build Coastguard Worker {
169*8617a60dSAndroid Build Coastguard Worker ssize_t read_rv;
170*8617a60dSAndroid Build Coastguard Worker size_t bytes_remaining;
171*8617a60dSAndroid Build Coastguard Worker
172*8617a60dSAndroid Build Coastguard Worker switch (target->type) {
173*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER:
174*8617a60dSAndroid Build Coastguard Worker bytes_remaining = target->buffer.size;
175*8617a60dSAndroid Build Coastguard Worker break;
176*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER_NULL_TERMINATED:
177*8617a60dSAndroid Build Coastguard Worker if (target->buffer.size == 0)
178*8617a60dSAndroid Build Coastguard Worker return -1;
179*8617a60dSAndroid Build Coastguard Worker bytes_remaining = target->buffer.size - 1;
180*8617a60dSAndroid Build Coastguard Worker break;
181*8617a60dSAndroid Build Coastguard Worker default:
182*8617a60dSAndroid Build Coastguard Worker return 0;
183*8617a60dSAndroid Build Coastguard Worker }
184*8617a60dSAndroid Build Coastguard Worker
185*8617a60dSAndroid Build Coastguard Worker target->buffer.bytes_consumed = 0;
186*8617a60dSAndroid Build Coastguard Worker while (bytes_remaining) {
187*8617a60dSAndroid Build Coastguard Worker read_rv = read(
188*8617a60dSAndroid Build Coastguard Worker target->priv.pipefd[0],
189*8617a60dSAndroid Build Coastguard Worker target->buffer.buf + target->buffer.bytes_consumed,
190*8617a60dSAndroid Build Coastguard Worker bytes_remaining);
191*8617a60dSAndroid Build Coastguard Worker if (read_rv < 0)
192*8617a60dSAndroid Build Coastguard Worker return -1;
193*8617a60dSAndroid Build Coastguard Worker if (read_rv == 0)
194*8617a60dSAndroid Build Coastguard Worker break;
195*8617a60dSAndroid Build Coastguard Worker target->buffer.bytes_consumed += read_rv;
196*8617a60dSAndroid Build Coastguard Worker bytes_remaining -= read_rv;
197*8617a60dSAndroid Build Coastguard Worker }
198*8617a60dSAndroid Build Coastguard Worker
199*8617a60dSAndroid Build Coastguard Worker if (target->type == TARGET_BUFFER_NULL_TERMINATED)
200*8617a60dSAndroid Build Coastguard Worker target->buffer.buf[target->buffer.bytes_consumed] = '\0';
201*8617a60dSAndroid Build Coastguard Worker return 0;
202*8617a60dSAndroid Build Coastguard Worker }
203*8617a60dSAndroid Build Coastguard Worker
process_target_output_cb(struct subprocess_target * target)204*8617a60dSAndroid Build Coastguard Worker static int process_target_output_cb(struct subprocess_target *target)
205*8617a60dSAndroid Build Coastguard Worker {
206*8617a60dSAndroid Build Coastguard Worker char buf[MAX_CB_BUF_SIZE];
207*8617a60dSAndroid Build Coastguard Worker ssize_t rv;
208*8617a60dSAndroid Build Coastguard Worker
209*8617a60dSAndroid Build Coastguard Worker for (;;) {
210*8617a60dSAndroid Build Coastguard Worker rv = read(target->priv.pipefd[0], buf, MAX_CB_BUF_SIZE);
211*8617a60dSAndroid Build Coastguard Worker if (rv < 0)
212*8617a60dSAndroid Build Coastguard Worker return -1;
213*8617a60dSAndroid Build Coastguard Worker if (rv == 0)
214*8617a60dSAndroid Build Coastguard Worker break;
215*8617a60dSAndroid Build Coastguard Worker if (target->callback.cb(buf, rv, target->callback.data) < 0)
216*8617a60dSAndroid Build Coastguard Worker return -1;
217*8617a60dSAndroid Build Coastguard Worker }
218*8617a60dSAndroid Build Coastguard Worker
219*8617a60dSAndroid Build Coastguard Worker return 0;
220*8617a60dSAndroid Build Coastguard Worker }
221*8617a60dSAndroid Build Coastguard Worker
process_target_output(struct subprocess_target * target)222*8617a60dSAndroid Build Coastguard Worker static int process_target_output(struct subprocess_target *target)
223*8617a60dSAndroid Build Coastguard Worker {
224*8617a60dSAndroid Build Coastguard Worker int rv;
225*8617a60dSAndroid Build Coastguard Worker
226*8617a60dSAndroid Build Coastguard Worker switch (target->type) {
227*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER:
228*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER_NULL_TERMINATED:
229*8617a60dSAndroid Build Coastguard Worker case TARGET_CALLBACK:
230*8617a60dSAndroid Build Coastguard Worker break;
231*8617a60dSAndroid Build Coastguard Worker default:
232*8617a60dSAndroid Build Coastguard Worker return 0;
233*8617a60dSAndroid Build Coastguard Worker }
234*8617a60dSAndroid Build Coastguard Worker
235*8617a60dSAndroid Build Coastguard Worker close(target->priv.pipefd[1]);
236*8617a60dSAndroid Build Coastguard Worker switch (target->type) {
237*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER:
238*8617a60dSAndroid Build Coastguard Worker case TARGET_BUFFER_NULL_TERMINATED:
239*8617a60dSAndroid Build Coastguard Worker rv = process_target_output_buffer(target);
240*8617a60dSAndroid Build Coastguard Worker break;
241*8617a60dSAndroid Build Coastguard Worker case TARGET_CALLBACK:
242*8617a60dSAndroid Build Coastguard Worker rv = process_target_output_cb(target);
243*8617a60dSAndroid Build Coastguard Worker break;
244*8617a60dSAndroid Build Coastguard Worker default:
245*8617a60dSAndroid Build Coastguard Worker return -1;
246*8617a60dSAndroid Build Coastguard Worker }
247*8617a60dSAndroid Build Coastguard Worker
248*8617a60dSAndroid Build Coastguard Worker close(target->priv.pipefd[0]);
249*8617a60dSAndroid Build Coastguard Worker return rv;
250*8617a60dSAndroid Build Coastguard Worker }
251*8617a60dSAndroid Build Coastguard Worker
contains_spaces(const char * s)252*8617a60dSAndroid Build Coastguard Worker static bool contains_spaces(const char *s)
253*8617a60dSAndroid Build Coastguard Worker {
254*8617a60dSAndroid Build Coastguard Worker for (size_t i = 0; s[i]; i++) {
255*8617a60dSAndroid Build Coastguard Worker if (isspace(s[i]))
256*8617a60dSAndroid Build Coastguard Worker return true;
257*8617a60dSAndroid Build Coastguard Worker }
258*8617a60dSAndroid Build Coastguard Worker return false;
259*8617a60dSAndroid Build Coastguard Worker }
260*8617a60dSAndroid Build Coastguard Worker
subprocess_log_call(const char * const argv[])261*8617a60dSAndroid Build Coastguard Worker static void subprocess_log_call(const char *const argv[])
262*8617a60dSAndroid Build Coastguard Worker {
263*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Run:");
264*8617a60dSAndroid Build Coastguard Worker
265*8617a60dSAndroid Build Coastguard Worker for (size_t i = 0; argv[i]; i++) {
266*8617a60dSAndroid Build Coastguard Worker if (contains_spaces(argv[i]))
267*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG_RAW(" '%s'", argv[i]);
268*8617a60dSAndroid Build Coastguard Worker else
269*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG_RAW(" %s", argv[i]);
270*8617a60dSAndroid Build Coastguard Worker }
271*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG_RAW("\n");
272*8617a60dSAndroid Build Coastguard Worker }
273*8617a60dSAndroid Build Coastguard Worker
274*8617a60dSAndroid Build Coastguard Worker struct subprocess_target subprocess_null = {
275*8617a60dSAndroid Build Coastguard Worker .type = TARGET_NULL,
276*8617a60dSAndroid Build Coastguard Worker };
277*8617a60dSAndroid Build Coastguard Worker
278*8617a60dSAndroid Build Coastguard Worker struct subprocess_target subprocess_stdin = {
279*8617a60dSAndroid Build Coastguard Worker .type = TARGET_FD,
280*8617a60dSAndroid Build Coastguard Worker .fd = STDIN_FILENO,
281*8617a60dSAndroid Build Coastguard Worker };
282*8617a60dSAndroid Build Coastguard Worker
283*8617a60dSAndroid Build Coastguard Worker struct subprocess_target subprocess_stdout = {
284*8617a60dSAndroid Build Coastguard Worker .type = TARGET_FD,
285*8617a60dSAndroid Build Coastguard Worker .fd = STDOUT_FILENO,
286*8617a60dSAndroid Build Coastguard Worker };
287*8617a60dSAndroid Build Coastguard Worker
288*8617a60dSAndroid Build Coastguard Worker struct subprocess_target subprocess_stderr = {
289*8617a60dSAndroid Build Coastguard Worker .type = TARGET_FD,
290*8617a60dSAndroid Build Coastguard Worker .fd = STDERR_FILENO,
291*8617a60dSAndroid Build Coastguard Worker };
292*8617a60dSAndroid Build Coastguard Worker
293*8617a60dSAndroid Build Coastguard Worker test_mockable
subprocess_run(const char * const argv[],struct subprocess_target * input,struct subprocess_target * output,struct subprocess_target * error)294*8617a60dSAndroid Build Coastguard Worker int subprocess_run(const char *const argv[],
295*8617a60dSAndroid Build Coastguard Worker struct subprocess_target *input,
296*8617a60dSAndroid Build Coastguard Worker struct subprocess_target *output,
297*8617a60dSAndroid Build Coastguard Worker struct subprocess_target *error)
298*8617a60dSAndroid Build Coastguard Worker {
299*8617a60dSAndroid Build Coastguard Worker int status;
300*8617a60dSAndroid Build Coastguard Worker pid_t pid = -1;
301*8617a60dSAndroid Build Coastguard Worker
302*8617a60dSAndroid Build Coastguard Worker subprocess_log_call(argv);
303*8617a60dSAndroid Build Coastguard Worker
304*8617a60dSAndroid Build Coastguard Worker if (!input)
305*8617a60dSAndroid Build Coastguard Worker input = &subprocess_stdin;
306*8617a60dSAndroid Build Coastguard Worker if (!output)
307*8617a60dSAndroid Build Coastguard Worker output = &subprocess_stdout;
308*8617a60dSAndroid Build Coastguard Worker if (!error)
309*8617a60dSAndroid Build Coastguard Worker error = &subprocess_stderr;
310*8617a60dSAndroid Build Coastguard Worker
311*8617a60dSAndroid Build Coastguard Worker if (init_target_private(input) < 0)
312*8617a60dSAndroid Build Coastguard Worker goto fail;
313*8617a60dSAndroid Build Coastguard Worker if (init_target_private(output) < 0)
314*8617a60dSAndroid Build Coastguard Worker goto fail;
315*8617a60dSAndroid Build Coastguard Worker if (init_target_private(error) < 0)
316*8617a60dSAndroid Build Coastguard Worker goto fail;
317*8617a60dSAndroid Build Coastguard Worker
318*8617a60dSAndroid Build Coastguard Worker if ((pid = fork()) < 0)
319*8617a60dSAndroid Build Coastguard Worker goto fail;
320*8617a60dSAndroid Build Coastguard Worker if (pid == 0) {
321*8617a60dSAndroid Build Coastguard Worker /* Child process */
322*8617a60dSAndroid Build Coastguard Worker if (connect_process_target(input, STDIN_FILENO) < 0)
323*8617a60dSAndroid Build Coastguard Worker goto fail;
324*8617a60dSAndroid Build Coastguard Worker if (connect_process_target(output, STDOUT_FILENO) < 0)
325*8617a60dSAndroid Build Coastguard Worker goto fail;
326*8617a60dSAndroid Build Coastguard Worker if (connect_process_target(error, STDERR_FILENO) < 0)
327*8617a60dSAndroid Build Coastguard Worker goto fail;
328*8617a60dSAndroid Build Coastguard Worker execvp(*argv, (char *const *)argv);
329*8617a60dSAndroid Build Coastguard Worker goto fail;
330*8617a60dSAndroid Build Coastguard Worker }
331*8617a60dSAndroid Build Coastguard Worker
332*8617a60dSAndroid Build Coastguard Worker /* Parent process */
333*8617a60dSAndroid Build Coastguard Worker if (process_target_input(input) < 0)
334*8617a60dSAndroid Build Coastguard Worker goto fail;
335*8617a60dSAndroid Build Coastguard Worker if (process_target_output(output) < 0)
336*8617a60dSAndroid Build Coastguard Worker goto fail;
337*8617a60dSAndroid Build Coastguard Worker if (process_target_output(error) < 0)
338*8617a60dSAndroid Build Coastguard Worker goto fail;
339*8617a60dSAndroid Build Coastguard Worker
340*8617a60dSAndroid Build Coastguard Worker if (waitpid(pid, &status, 0) < 0)
341*8617a60dSAndroid Build Coastguard Worker goto fail;
342*8617a60dSAndroid Build Coastguard Worker
343*8617a60dSAndroid Build Coastguard Worker if (WIFEXITED(status))
344*8617a60dSAndroid Build Coastguard Worker return WEXITSTATUS(status);
345*8617a60dSAndroid Build Coastguard Worker
346*8617a60dSAndroid Build Coastguard Worker fail:
347*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Failed to execute external command: %s\n", strerror(errno));
348*8617a60dSAndroid Build Coastguard Worker if (pid == 0)
349*8617a60dSAndroid Build Coastguard Worker exit(127);
350*8617a60dSAndroid Build Coastguard Worker return -1;
351*8617a60dSAndroid Build Coastguard Worker }
352