* Initial function signatur and struct for `RzPty` API
* Change type annotation to borrow
* Implement `rz_subprocess_login_tty`
* Add fork mode enum and move pty struct; restructure ifdef guards
* Add rough implementation of forkpty
* Add `rz_sys` versions for `forkpty` family of functions
* Add forkpty code; Make changes according to review
* Implement forkpty properly and add unit test
* Add `test_interactive_pty`
* Add documentation
* Remove const in function argument
* Apparently, MacOS as non-const arguments for `openpty` and `forkpty`
* Add more tests for subprocess forkin using forkpty
* `test_interactive_pipe_pty`: Create pipes between the slave's PTY
and master and use them
* `test_interactive_custom_pty`: Use a custom PTY for the slave
* Add PTY functions exist checks for unit tests
* Move terminal param code inside the forkpty branch
* Add comment about why we need to check `n_bytes = 0` in `subprocess_wait`
* Remove forkpty with a specified `RzPTY`
* Also, no piping done in forkpty
* Add checks to disallow using `forkpty` with piping
* Make changes according to review
* No need to check proc file descriptors for -1 in `forkpty` mode, since
they *will* be -1
* No need to check `n_bytes == 0` in for `std{out,err}_pty`
* Extract pipe initialization code in `init_pipes` function
* Allow using custom PTY for `rz_subprocess_forkpty`
* Remove const qualifiers for termios and winsize arguments
* This makes the build pass on MacOS, which does accepts non-const
arguments
* Change `pid_t` to int so that it compiles on Windows
* Add empty implementation for PTY API for Windows
* Update function signature for `rz_subprocess_start_opt` for Windows
* Re-add `#define` for `pid_t` in `librz/socket/run.c`
* Move functions to remove duplicate definitions
* Allow specifying piping options even in `forkpty` mode
* Only expose the master fd for the streams which have pipe create
as their piping option
* Add comment about not using `master_fd` directly
* Fix types in definition for Windows
* Free the allocated `RzPTY` object
* Add const qualifiers for `RzPTY` argument
* Assign `fork_mode` and `pty` in all instances of subprocess opt start
* for good measure
* Compare master fd with -1, not 0
* Remove stray file
* Add second comment about the terminal attribute
* Overhaul the whole PTY implementation
* Now the caller can either use a pipe or PTY to send and receive
data from any of the streams
* Extra option `make_raw` to use the slave PTY in raw mode
* Add documentation for all the new functions
* Fix UAF bug
* Add error handling for `tcgetattr`
* Move the term param setting code
* Add documentation for the subprocess API and sys API
* Format according to clang-format
124 lines
4.8 KiB
C
124 lines
4.8 KiB
C
// SPDX-FileCopyrightText: Florian Märkl <info@florianmaerkl.de>, Riccardo Schirone <sirmy15@gmail.com>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#ifndef RZ_UTIL_SUBPROCESS_H
|
|
#define RZ_UTIL_SUBPROCESS_H
|
|
|
|
#include <rz_types.h>
|
|
#include <rz_util/rz_strbuf.h>
|
|
|
|
/**
|
|
* Enum used to determine how pipes should be created, if at all, in the
|
|
* subprocess.
|
|
*/
|
|
typedef enum rz_subprocess_pipe_create_t {
|
|
///< No pipe should be created. It can be used for stdin, stdout and stderr.
|
|
RZ_SUBPROCESS_PIPE_NONE,
|
|
///< A new pipe should be created. It can be used for stdin, stdout and stderr.
|
|
RZ_SUBPROCESS_PIPE_CREATE,
|
|
///< A new PTY should be created. It can be used for stdin, stdout and stderr.
|
|
RZ_SUBPROCESS_PIPE_PTY,
|
|
///< Re-use the same pipe/PTY as stdout. It can be used for stderr only.
|
|
RZ_SUBPROCESS_PIPE_STDOUT,
|
|
} RzSubprocessPipeCreate;
|
|
|
|
/**
|
|
* Values passed to rz_subprocess API to mention stdin, stdout, stderr or a combination of those
|
|
*/
|
|
#define RZ_SUBPROCESS_STDIN (1 << 0)
|
|
#define RZ_SUBPROCESS_STDOUT (1 << 1)
|
|
#define RZ_SUBPROCESS_STDERR (1 << 2)
|
|
|
|
typedef enum rz_process_wait_reason_t {
|
|
RZ_SUBPROCESS_DEAD,
|
|
RZ_SUBPROCESS_TIMEDOUT,
|
|
RZ_SUBPROCESS_BYTESREAD,
|
|
} RzSubprocessWaitReason;
|
|
|
|
typedef enum rz_subprocess_fork_mode_t {
|
|
RZ_SUBPROCESS_FORK,
|
|
RZ_SUBPROCESS_FORKPTY,
|
|
} RzSubprocessForkMode;
|
|
|
|
/**
|
|
* Provide results from running a sub-process, like output, return value, etc.
|
|
*/
|
|
typedef struct rz_process_output_t {
|
|
///< Output generated by the process
|
|
ut8 *out;
|
|
///< Number of bytes in the \p out field
|
|
int out_len;
|
|
///< Error generated by the process
|
|
ut8 *err;
|
|
///< Number of bytes in the \p err field
|
|
int err_len;
|
|
///< Return value (exit code) of the sub-process
|
|
int ret;
|
|
///< True if the process has exited because of a timeout
|
|
bool timeout;
|
|
} RzSubprocessOutput;
|
|
|
|
typedef struct rz_pty_t {
|
|
int master_fd;
|
|
int slave_fd;
|
|
char *name;
|
|
} RzPty;
|
|
|
|
/**
|
|
* Specify how the new subprocess should be created.
|
|
*/
|
|
typedef struct rz_subprocess_opt_t {
|
|
///< Name of the executable to run. It is searched also in PATH
|
|
const char *file;
|
|
///< Arguments to pass to the subprocess. These are just the arguments and do not include the program name (aka argv[0])
|
|
const char **args;
|
|
///< Number of arguments in \p args array
|
|
size_t args_size;
|
|
///< Names of environment variables that subprocess should have differently from parent
|
|
const char **envvars;
|
|
///< Values of environment variables that subprocess should have differently from parent
|
|
const char **envvals;
|
|
///< Number of elements contained in both \p envvars and \p envvals
|
|
size_t env_size;
|
|
///< Specify how to deal with subprocess stdin
|
|
RzSubprocessPipeCreate stdin_pipe;
|
|
///< Specify how to deal with subprocess stdout
|
|
RzSubprocessPipeCreate stdout_pipe;
|
|
///< Specify how to deal with subprocess stderr
|
|
RzSubprocessPipeCreate stderr_pipe;
|
|
|
|
/* Both the following fields only matter when using PTY in the pipe options */
|
|
///< Provide the PTY to use (if NULL, then a new one will be created, if required)
|
|
///< No need to close the PTY once it has been used, you can free it directly
|
|
RzPty *pty;
|
|
///< Use raw mode for the created PTY (disable echo, control characters, etc.)
|
|
///< If you don't know what to put here, put true here.
|
|
bool make_raw;
|
|
} RzSubprocessOpt;
|
|
|
|
typedef struct rz_subprocess_t RzSubprocess;
|
|
|
|
RZ_API bool rz_subprocess_init(void);
|
|
RZ_API void rz_subprocess_fini(void);
|
|
RZ_API RzSubprocess *rz_subprocess_start(
|
|
const char *file, const char *args[], size_t args_size,
|
|
const char *envvars[], const char *envvals[], size_t env_size);
|
|
RZ_API RZ_OWN RzSubprocess *rz_subprocess_start_opt(RZ_NONNULL const RzSubprocessOpt *opt);
|
|
RZ_API void rz_subprocess_free(RzSubprocess *proc);
|
|
RZ_API RzSubprocessWaitReason rz_subprocess_wait(RzSubprocess *proc, ut64 timeout_ms);
|
|
RZ_API void rz_subprocess_kill(RzSubprocess *proc);
|
|
RZ_API int rz_subprocess_ret(RzSubprocess *proc);
|
|
RZ_API ut8 *rz_subprocess_out(RzSubprocess *proc, int *length);
|
|
RZ_API ut8 *rz_subprocess_err(RzSubprocess *proc, int *length);
|
|
RZ_API ssize_t rz_subprocess_stdin_write(RzSubprocess *proc, const ut8 *buf, size_t buf_size);
|
|
RZ_API RzStrBuf *rz_subprocess_stdout_read(RzSubprocess *proc, size_t n, ut64 timeout_ms);
|
|
RZ_API RZ_BORROW RzStrBuf *rz_subprocess_stdout_readline(RzSubprocess *proc, ut64 timeout_ms);
|
|
RZ_API RzSubprocessOutput *rz_subprocess_drain(RzSubprocess *proc);
|
|
RZ_API void rz_subprocess_output_free(RzSubprocessOutput *out);
|
|
|
|
RZ_API RZ_OWN RzPty *rz_subprocess_openpty(RZ_BORROW RZ_NULLABLE char *slave_name, RZ_NULLABLE void /* const struct termios */ *term_params, RZ_NULLABLE void /* const struct winsize */ *win_params);
|
|
RZ_API void rz_subprocess_close_pty(RZ_BORROW RZ_NONNULL const RzPty *pty);
|
|
RZ_API bool rz_subprocess_login_tty(RZ_BORROW RZ_NONNULL const RzPty *pty);
|
|
RZ_API void rz_subprocess_pty_free(RZ_OWN RzPty *pty);
|
|
|
|
#endif // RZ_UTIL_SUBPROCESS_H
|