xref: /aosp_15_r20/external/vboot_reference/host/lib/include/subprocess.h (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2019 The ChromiumOS Authors
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * Library for creating subprocesses in a high level manner.
6  */
7 
8 #ifndef VBOOT_REFERENCE_SUBPROCESS_H_
9 #define VBOOT_REFERENCE_SUBPROCESS_H_
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 
14 /**
15  * subprocess_target is the "mini language" of the subprocess
16  * library. It describes where to read or write data from the process.
17  *
18  * There are currently five target of targets:
19  *
20  * - TARGET_NULL: /dev/null, no need to describe any other fields.
21  *
22  * - TARGET_FD: file descriptor, put the fd in the fd field.
23  *
24  * - TARGET_FILE: FILE *, put the FILE pointer in the file field.
25  *
26  * - TARGET_BUFFER: read to, or write from, a buffer. Fields:
27  *   - buffer->buf: the buffer
28  *   - buffer->size: the size of that buffer
29  *   - buffer->bytes_consumed: do not fill out this field.
30  *     subprocess_run will set it to the number of bytes read from the
31  *     process (if writing to a buffer). Goes unused when reading from
32  *     a buffer.
33  *
34  * - TARGET_BUFFER_NULL_TERMINATED: when reading from a buffer, don't
35  *   fill out the size field and subprocess_run will strlen for you.
36  *   When writing to a buffer, subprocess_run will reserve one byte of
37  *   the size for a null terminator and guarantee that the output is
38  *   always NULL terminated.
39  *
40  * - TARGET_CALLBACK: when the target is provided as an input to a
41  *   process, the callback will be called occasionally to provide
42  *   input to the process. The callback should fill buf with up to
43  *   buf_sz bytes of data, and return the number of bytes
44  *   written, or negative values on error. When the target is provided
45  *   as an output to a process, the callback will be called
46  *   occasionally with buf_sz bytes of data from the output put into
47  *   buf. In this case, the return value from the callback is
48  *   ignored except for errors. The data field is for application use
49  *   and will always be passed to the data parameter of the callback
50  *   function.
51  */
52 struct subprocess_target {
53 	enum {
54 		TARGET_NULL,
55 		TARGET_FD,
56 		TARGET_FILE,
57 		TARGET_BUFFER,
58 		TARGET_BUFFER_NULL_TERMINATED,
59 		TARGET_CALLBACK,
60 	} type;
61 	union {
62 		int fd;
63 		FILE *file;
64 		struct {
65 			char *buf;
66 			size_t size;
67 
68 			/*
69 			 * This variable is the output of the number of bytes
70 			 * read or written. It should be read by the caller, not
71 			 * set.
72 			 */
73 			size_t bytes_consumed;
74 		} buffer;
75 		struct {
76 			ssize_t (*cb)(char *buf, size_t buf_sz, void *data);
77 			void *data;
78 		} callback;
79 	};
80 	struct {
81 		int pipefd[2];
82 	} priv;
83 };
84 
85 /**
86  * A convenience subprocess target which uses TARGET_NULL.
87  */
88 extern struct subprocess_target subprocess_null;
89 
90 /**
91  * A convenience subprocess target which uses TARGET_FD to STDIN_FILENO.
92  */
93 extern struct subprocess_target subprocess_stdin;
94 
95 /**
96  * A convenience subprocess target which uses TARGET_FD to STDOUT_FILENO.
97  */
98 extern struct subprocess_target subprocess_stdout;
99 
100 /**
101  * A convenience subprocess target which uses TARGET_FD to STDERR_FILENO.
102  */
103 extern struct subprocess_target subprocess_stderr;
104 
105 /**
106  * Call a process and run until completion.
107  *
108  * @param argv          A NULL-terminated list of arguments describing
109  *                      the program to run.
110  * @param input         The subprocess_target connected to stdin.
111  * @param output        The subprocess_target connected to stdout.
112  * @param error         The subprocess_target connected to stderr.
113  *
114  * If either input, output, or error are set to NULL, they will be
115  * &subprocess_stdin, &subprocess_stdout, or &subprocess_stderr
116  * respectively.
117  *
118  * @return The exit status on success, or negative values on error.
119  */
120 int subprocess_run(const char *const argv[],
121 		   struct subprocess_target *input,
122 		   struct subprocess_target *output,
123 		   struct subprocess_target *error);
124 
125 #endif  /* VBOOT_REFERENCE_SUBPROCESS_H_ */
126