File: process.h

package info (click to toggle)
bpfilter 0.5.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,076 kB
  • sloc: ansic: 30,397; sh: 1,383; cpp: 959; python: 495; yacc: 385; lex: 194; makefile: 9
file content (149 lines) | stat: -rw-r--r-- 5,277 bytes parent folder | download
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
 */

#pragma once

#include <stddef.h>
#include <sys/types.h>

/**
 * @file process.h
 *
 * The functions defined in this file are used to manage an external process.
 * They are inspired by the Python `subprocess` module.
 *
 * `bf_test_process` represents the process to manipulate, it must
 * be initialized using `bf_test_process_init()` with the correct command and
 * arguments.
 *
 * `bf_test_process_start()` will fork the current process, and run the
 * pre-defined command in the new thread. Two file descriptors will be available
 * to read the forked process' `stdout` and `stderr` streams (use
 * `bf_test_process_stdout()` and `bf_test_process_stderr()` to do so).
 *
 * The forked process can terminate by itself, in which case you need to wait
 * for it anyway using `bf_test_process_wait()`. You can also kill the process
 * manually by calling `bf_test_process_kill()` to send a `SIGTERM` signal,
 * then calling `bf_test_process_wait()`. The last option is to call
 * `bf_test_process_stop()` which will kill it and wait.
 *
 * Lastly, cleanup the resources allocated for the process with
 * `bf_test_process_clean()`.
 */

struct bf_test_process
{
    /// Command to run in the process.
    const char *cmd;
    /// Array of arguments as `char` pointers.
    char **args;
    /// Number of arguments in `args`.
    size_t nargs;
    /// PID of the process, only valid while the process is alive.
    pid_t pid;
    /// File descriptor of the process' `stdout` stream.
    int out_fd;
    /// File descriptor of the process' `stderr` stream.
    int err_fd;
};

#define _clean_bf_test_process_                                                \
    __attribute__((__cleanup__(bf_test_process_clean)))

#define bft_process_default()                                                  \
    {                                                                          \
        .out_fd = -1,                                                          \
        .err_fd = -1,                                                          \
    }

int bf_test_process_init(struct bf_test_process *process, const char *cmd,
                         char **args, size_t nargs);
void bf_test_process_clean(struct bf_test_process *process);

/**
 * Start the process.
 *
 * Fork the current process to start the requested process. Open two file
 * descriptor to communicate with the forked process (`stdout` and `stderr`).
 * Once started, the process can be waited on, killed, or stopped. Use
 * `bf_test_process_stdout()` and `bf_test_process_stderr()` to access it
 * standard output and error buffers.
 *
 * If this function succeeds, `bf_test_process_wait()` or
 * `bf_test_process_stop()` must called before cleaning the process.
 *
 * @param process The process to start. Can't be `NULL`.
 * @return 0 on success, or a negative errno value on error.
 */

int bf_test_process_start(struct bf_test_process *process);

/**
 * Wait for the process to terminate.
 *
 * This function will hang until the process has completed.
 *
 * @param process The process to wait on. Can't be NULL.
 * @return The return code of the process as a non-negative integer, or a
 *         negative errno value on error.
 */
int bf_test_process_wait(struct bf_test_process *process);

/**
 * Kill the process by sending `SIGTERM`.
 *
 * @param process The process to kill. Can't be `NULL`.
 * @return 0 on success, or a negative errno value on error.
 */
int bf_test_process_kill(struct bf_test_process *process);

/**
 * Force the process to stop and wait for it.
 *
 * This function is equivalent to calling `bf_test_process_kill()` then
 * `bf_test_process_wait()`.
 *
 * @param process The process to stop. Can't be `NULL`.
 * @return The return code of the process as a non-negative integer, or a
 *         negative errno value on error.
 */
int bf_test_process_stop(struct bf_test_process *process);

/**
 * Run a command in a forked process.
 *
 * This function won't kill the process but only wait on it. If you call
 * `bf_run()` with a command that doesn't return, this function will hang
 * indefinitely.
 *
 * @param cmd Command to run in the process.
 * @param args Array of arguments to provide to the process.
 * @param nargs Number of arguments in @p args.
 * @return The return code of the process as a non-negative integer, or a
 *         negative errno value on error.
 */
int bf_run(const char *cmd, char **args, size_t nargs);

/**
 * Read the process' `stdout` stream.
 *
 * The buffer returned by `bf_test_process_stdout()` is dynamically allocated
 * and is owned by the caller.
 *
 * @param process Process to read the `stdout` stream from.
 * @return Buffer containing the process' `stdout` stream, or `NULL` on error.
 */
const char *bf_test_process_stdout(struct bf_test_process *process);

/**
 * Read the process' `stderr` stream.
 *
 * The buffer returned by `bf_test_process_stderr()` is dynamically allocated
 * and is owned by the caller.
 *
 * @param process Process to read the `stderr` stream from.
 * @return Buffer containing the process' `stderr` stream, or `NULL` on error.
 */
const char *bf_test_process_stderr(struct bf_test_process *process);