diff options
author | Mattias Andrée <maandree@kth.se> | 2024-05-05 10:24:40 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2024-05-05 10:24:40 +0200 |
commit | 3dfd6c11ed5599ab8baf4a6114f4ccb34150de6e (patch) | |
tree | b7717583b99f29028c85c3423cf43b104dfa8943 /libexec.h | |
download | libexec-3dfd6c11ed5599ab8baf4a6114f4ccb34150de6e.tar.gz libexec-3dfd6c11ed5599ab8baf4a6114f4ccb34150de6e.tar.bz2 libexec-3dfd6c11ed5599ab8baf4a6114f4ccb34150de6e.tar.xz |
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'libexec.h')
-rw-r--r-- | libexec.h | 1633 |
1 files changed, 1633 insertions, 0 deletions
diff --git a/libexec.h b/libexec.h new file mode 100644 index 0000000..5f7b2d0 --- /dev/null +++ b/libexec.h @@ -0,0 +1,1633 @@ +/* See LICENSE file for copyright and license details. */ +#ifndef LIBEXEC_H +#define LIBEXEC_H + + +#if defined(__linux__) +# include <linux/openat2.h> +#endif +#include <fcntl.h> +#include <signal.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> + + +/* For internal use only { */ +#if defined(__GNUC__) +# define LIBEXEC_PURE__ __attribute__((__pure__)) +# define LIBEXEC_CONST__ __attribute__((__const__)) +# define LIBEXEC_PRINTF__(FMTIDX) __attribute__((__format__(__gnu_printf__, (FMTIDX), (FMTIDX) + 1))) +# define LIBEXEC_VPRINTF__(FMTIDX) __attribute__((__format__(__gnu_printf__, (FMTIDX), 0))) +#else +# define LIBEXEC_PURE__ +# define LIBEXEC_CONST__ +# define LIBEXEC_PRINTF__(FMTIDX) +# define LIBEXEC_VPRINTF__(FMTIDX) +#endif +/* } */ + + +#define LIBEXEC_VERSION 0U + + +enum libexec_insert_mode { + LIBEXEC_REPLACE, /* replace existing definition if any */ + LIBEXEC_NOREPLACE, /* do nothing if definition already exists */ + LIBEXEC_NOCLOBBER, /* fail if definition already exists an differs */ + LIBEXEC_APPEND, /* add, to end of list, even if definition already exists, but also keep old */ + LIBEXEC_PREPEND /* add, to beginning of list, even if definition already exists, but also keep old */ + /* Either LIBEXEC_APPEND or LIBEXEC_PREPEND is required to put something missing '=' in the environment */ +#define LIBEXEC_INSERT_MODE__COUNT__ 5 +}; + +enum libexec_pluming_type { + LIBEXEC_PLUMING_OPENAT, + LIBEXEC_PLUMING_OPENAT2, + LIBEXEC_PLUMING_CLOSE, + LIBEXEC_PLUMING_DUP2, + LIBEXEC_PLUMING_DOCUMENT, + LIBEXEC_PLUMING_PIPE +#define LIBEXEC_PLUMING_TYPE__COUNT__ 6 +}; + +enum libexec_pipe { + LIBEXEC_PIPE = 0, + LIBEXEC_SOCK_STREAM = 1, + LIBEXEC_SOCK_SEQPACKET = 2, + LIBEXEC_SOCK_DGRAM = 3, + LIBEXEC_DIRECT_PIPE = 4, + LIBEXEC_PIPE_CIRCULARLY = 0x8000 +#define LIBEXEC_PIPE__COUNT__ 5 +}; + +enum libexec_locate_method { + LIBEXEC_ALLOW_NAME, + LIBEXEC_REQUIRE_PATH, + LIBEXEC_EXEC_FD, + LIBEXEC_EXEC_AT +#define LIBEXEC_LOCATE_METHOD__COUNT__ 4 +}; + +enum libexec_run_instruction { + LIBEXEC_RUN_END, /* required to mark end if arguments for libexec_run */ + LIBEXEC_RUN_END_CIRCULAR_PIPE, /* alternative to LIBEXEC_RUN_END */ + LIBEXEC_RUN_PIPE, + LIBEXEC_RUN_SET_EXECUTABLE, + LIBEXEC_RUN_SET_REQUIRE_PATH, + LIBEXEC_RUN_SET_EXEC_FD, + LIBEXEC_RUN_SET_EXEC_PATH, + LIBEXEC_RUN_COPY_ENVIRON, + LIBEXEC_RUN_SET_ENVIRON, + LIBEXEC_RUN_CLEAR_ENVIRON, + LIBEXEC_RUN_UNSETENV, + LIBEXEC_RUN_PUTENV, + LIBEXEC_RUN_SETENV, + LIBEXEC_RUN_PUTENVF, + LIBEXEC_RUN_SETENVF, + LIBEXEC_RUN_OPEN, + LIBEXEC_RUN_OPENAT, + LIBEXEC_RUN_OPENAT2, /* generates ENOSYS unless running on Linux */ + LIBEXEC_RUN_DUP, + LIBEXEC_RUN_CLOSE, + LIBEXEC_RUN_RENUMBER_FD, + LIBEXEC_RUN_INPUT_COPY, + LIBEXEC_RUN_INPUT_GIFT, + LIBEXEC_RUN_ADD_OUTPUT_FD, /* use LIBEXEC_RUN_SET_FD_CALLBACK first */ + LIBEXEC_RUN_ADD_OUTPUT, + LIBEXEC_RUN_SET_SIGMASK, /* use once to configure how libexec_run_pipeline is invoked behind the scenes */ + LIBEXEC_RUN_SET_FD_CALLBACK, /* ditto */ + LIBEXEC_RUN_SET_REAPER, /* ditto */ + LIBEXEC_RUN_SET_ATFORK, /* ditto */ + LIBEXEC_RUN_SET_MUTEX, /* ditto */ + LIBEXEC_RUN_SET_INTERRUPT_CALLBACK /* ditto */ +#define LIBEXEC_RUN_INSTRUCTION__COUNT__ 31 +}; +#define LIBEXEC_RUN_END() LIBEXEC_RUN_END +#define LIBEXEC_RUN_END_CIRCULAR_PIPE(TYPE) LIBEXEC_RUN_END_CIRCULAR_PIPE, TYPE +#define LIBEXEC_RUN_PIPE(TYPE) LIBEXEC_RUN_PIPE, TYPE +#define LIBEXEC_RUN_SET_EXECUTABLE(FILE) LIBEXEC_RUN_SET_EXECUTABLE, FILE +#define LIBEXEC_RUN_SET_REQUIRE_PATH(REQUIRE) LIBEXEC_RUN_SET_REQUIRE_PATH, REQUIRE +#define LIBEXEC_RUN_SET_EXEC_FD(FD) LIBEXEC_RUN_SET_EXEC_FD, FD +#define LIBEXEC_RUN_SET_EXEC_PATH(DIRFD, PATH) LIBEXEC_RUN_SET_EXEC_PATH, DIRFD, PATH +#define LIBEXEC_RUN_COPY_ENVIRON(ENVIRON) LIBEXEC_RUN_COPY_ENVIRON, ENVIRON +#define LIBEXEC_RUN_SET_ENVIRON(ENVIRON) LIBEXEC_RUN_SET_ENVIRON, ENVIRON +#define LIBEXEC_RUN_CLEAR_ENVIRON(ENVIRON) LIBEXEC_RUN_CLEAR_ENVIRON +#define LIBEXEC_RUN_UNSETENV(ENV) LIBEXEC_RUN_UNSETENV, ENV +#define LIBEXEC_RUN_PUTENV(... /* STR, [HOW] */) LIBEXEC_RUN_PUTENV__(__VA_ARGS__, LIBEXEC_REPLACE,) +#define LIBEXEC_RUN_SETENV(... /* ENV, VAL, [HOW] */) LIBEXEC_RUN_PUTENV__(__VA_ARGS__, LIBEXEC_REPLACE,) +#define LIBEXEC_RUN_PUTENV_SAFE(HOW, STR) LIBEXEC_RUN_PUTENV, HOW, STR +#define LIBEXEC_RUN_SETENV_SAFE(HOW, ENV, VAL) LIBEXEC_RUN_SETENV, HOW, ENV, VAL +#define LIBEXEC_RUN_PUTENVF_SAFE(HOW, ...) LIBEXEC_RUN_PUTENV, HOW, __VA_ARGS__ +#define LIBEXEC_RUN_SETENVF_SAFE(HOW, ENV, ...) LIBEXEC_RUN_SETENV, HOW, ENV, __VA_ARGS__ +#define LIBEXEC_RUN_PUTENVF(...) LIBEXEC_RUN_PUTENVF_SAFE(LIBEXEC_REPLACE, __VA_ARGS__) +#define LIBEXEC_RUN_SETENVF(ENV, ...) LIBEXEC_RUN_SETENVF_SAFE(LIBEXEC_REPLACE, ENV, __VA_ARGS__) +#define LIBEXEC_RUN_OPEN(FD, FILE, ... /* FLAGS, [MODE] */) LIBEXEC_RUN_OPEN__(FD, FILE, __VA_ARGS__, 0666,) +#define LIBEXEC_RUN_OPENAT(FD, DIRFD, FILE, ... /* FLAGS, [MODE] */) LIBEXEC_RUN_OPENAT__(FD, DIRFD, FILE, __VA_ARGS__, 0666,) +#define LIBEXEC_RUN_OPENAT2(FD, DIRFD, FILE, ... /* HOW, [SIZE] */)\ + LIBEXEC_RUN_OPENAT2__(FD, DIRFD, FILE, __VA_ARGS__, sizeof(LIBEXEC__FIRST__(__VA_ARGS__,)),) +#define LIBEXEC_RUN_DUP(NEW_FD, OLD_FD) LIBEXEC_RUN_DUP, NEW_FD, OLD_FD +#define LIBEXEC_RUN_CLOSE(FD) LIBEXEC_RUN_CLOSE, FD +#define LIBEXEC_RUN_RENUMBER_FD(NEW_FD, OLD_FD) LIBEXEC_RUN_RENUMBER_FD, NEW_FD, OLD_FD +#define LIBEXEC_RUN_INPUT_COPY(FD, ... /* DATA, [LEN] */)\ + LIBEXEC_RUN_INPUT__(COPY, FD, __VA_ARGS__, strlen(LIBEXEC__FIRST__(__VA_ARGS__)),) +#define LIBEXEC_RUN_INPUT_GIFT(FD, ... /* DATA, [LEN] */)\ + LIBEXEC_RUN_INPUT__(GIFT, FD, __VA_ARGS__, strlen(LIBEXEC__FIRST__(__VA_ARGS__)),) +#define LIBEXEC_RUN_ADD_OUTPUT_FD(FD, WR_FD) LIBEXEC_RUN_ADD_OUTPUT_FD, FD, WR_FD +#define LIBEXEC_RUN_ADD_OUTPUT(FD, OUT) LIBEXEC_RUN_ADD_OUTPUT, FD, OUT +#define LIBEXEC_RUN_SET_SIGMASK(SIGMASK) LIBEXEC_RUN_SET_SIGMASK, SIGMASK +#define LIBEXEC_RUN_SET_FD_CALLBACK(CB, USER) LIBEXEC_RUN_SET_FD_CALLBACK, CB, USER +#define LIBEXEC_RUN_SET_REAPER(CB, USER) LIBEXEC_RUN_SET_REAPER, CB, USER +#define LIBEXEC_RUN_SET_ATFORK(CB, USER) LIBEXEC_RUN_SET_ATFORK, CB, USER +#define LIBEXEC_RUN_SET_MUTEX(CB, USER) LIBEXEC_RUN_SET_MUTEX, CB, USER +#define LIBEXEC_RUN_SET_INTERRUPT_CALLBACK(CB, USER) LIBEXEC_RUN_SET_INTERRUPT_CALLBACK, CB, USER + +#define LIBEXEC__FIRST__(X, ...) X +#define LIBEXEC_RUN_PUTENV__(STR, HOW, ...) LIBEXEC_RUN_PUTENV, HOW, STR +#define LIBEXEC_RUN_SETENV__(ENV, VAL, HOW, ...) LIBEXEC_RUN_SETENV, HOW, ENV, VAL +#define LIBEXEC_RUN_OPEN__(FD, FILE, FLAGS, MODE, ...) LIBEXEC_RUN_OPEN, FD, FILE, FLAGS, MODE +#define LIBEXEC_RUN_OPENAT__(FD, DIRFD, FILE, FLAGS, MODE, ...) LIBEXEC_RUN_OPENAT, FD, DIRFD, FILE, FLAGS, MODE +#define LIBEXEC_RUN_INPUT__(INSTR, FD, DATA, LEN, ...) LIBEXEC_RUN_INPUT_##INSTR, FD, DATA, LEN + +struct libexec_pluming { + int fd; + enum libexec_pluming_type type; + union { + int fd; + struct { + char *file; + int dirfd; + union { + struct { + mode_t mode; + int flags; + }; +#if defined(__linux__) + struct { + struct open_how *how; + size_t how_size; + }; +#endif + }; + }; + struct { + char *text; + size_t len; + }; + } target; +}; + +#define LIBEXEC_COMMAND_INIT\ + ((struct libexec_command){LIBEXEC_VERSION, LIBEXEC_ALLOW_NAME, -1, NULL, NULL, 0, NULL, 0, NULL}) +struct libexec_command { + unsigned library_version; + enum libexec_locate_method exec_how; + int exec_fd; + char *executable; + char **arguments; + size_t narguments; + struct libexec_pluming *plumings; + size_t nplumings; + char **environ; +}; + +struct libexec_document { + unsigned long long int user; + int fd; + char *text; + size_t length; + union { + size_t offset; /* when used for input */ + size_t alloc_size; /* when used for output */ + }; +}; + +struct libexec_result { + int *exit_statuses; + size_t proc_count; + int all_successful; +}; + + +void libexec_init_command(struct libexec_command *cmd); +void libexec_destroy_command(struct libexec_command *cmd); +void libexec_destroy_pluming(struct libexec_pluming *pluming); +int libexec_destroy_document(struct libexec_document *doc); +void libexec_destroy_result(struct libexec_result *result); + +int libexec_vconstruct_command(struct libexec_command *cmd, const char *fmt, va_list args); +int libexec_construct_command(struct libexec_command *cmd, const char *fmt, ...); +int libexec_put_argumentsn(struct libexec_command *cmd, const char *const *args, size_t nargs); +int libexec_put_arguments(struct libexec_command *cmd, const char *const *args); +int libexec_set_executable(struct libexec_command *cmd, const char *executable /* NULL = use first argument in command */); +void libexec_set_require_path(struct libexec_command *cmd, int require); +int libexec_set_exec_fd(struct libexec_command *cmd, int fd); +int libexec_set_exec_path(struct libexec_command *cmd, int dirfd, const char *path /* NULL = use first argument in command */); + +int libexec_add_pluming(struct libexec_command *cmd, const struct libexec_pluming *pluming); +int libexec_open(struct libexec_command *cmd, int fd, const char *file, int flags, mode_t mode); +int libexec_openat(struct libexec_command *cmd, int fd, int dirfd, const char *file, int flags, mode_t mode); +#if defined(__linux__) +int libexec_openat2(struct libexec_command *cmd, int fd, int dirfd, const char *file, struct open_how *how, size_t size); +#endif +int libexec_dup(struct libexec_command *cmd, int fd, int old_fd); +int libexec_close(struct libexec_command *cmd, int fd); +int libexec_renumber_fd(struct libexec_command *cmd, int fd, int old_fd); +int libexec_input_data_copy(struct libexec_command *cmd, int fd, const char *data, size_t len); +int libexec_input_data_gift(struct libexec_command *cmd, int fd, char *data, size_t len); +int libexec_input_text_copy(struct libexec_command *cmd, int fd, const char *text); +int libexec_input_text_gift(struct libexec_command *cmd, int fd, char *text); +int libexec_add_output_fd(struct libexec_command *cmd, int fd, int wr_fd); +int libexec_add_output_document(struct libexec_command *cmd, int fd, struct libexec_document *doc /* .fd will be set */, int flags); + + +/** + * The the value of an environment variable in a command + * + * If command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment is inspected + * + * In the event that the environment contains multiple + * definitions of the same variable, the first definition + * is used + * + * @param cmd The command whose environment shall be inspected + * @param name The name of the environment variable to read + * @return The value of the environment variable, or NULL + * on failure or if the environment variable was + * not found + * + * @throws (unmodified) The environment variable does not exist + * @throws EINVAL Invalid argument input + */ +LIBEXEC_PURE__ const char *libexec_getenv(struct libexec_command *, const char *); + +/** + * The the value of an environment variable in a command + * + * If command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment is inspected + * + * In the event that the environment contains multiple + * definitions of the same variable, the last definition + * is used + * + * @param cmd The command whose environment shall be inspected + * @param name The name of the environment variable to read + * @return The value of the environment variable, or NULL + * on failure or if the environment variable was + * not found + * + * @throws (unmodified) The environment variable does not exist + * @throws EINVAL Invalid argument input + */ +LIBEXEC_PURE__ const char *libexec_getenv_last(struct libexec_command *, const char *); + + +/** + * Copy a list of environment variables and used it for a command + * + * @param cmd The command whose environment shall be set + * @param env The environment (will be copied), if NULL, the + * calling process's environment will be (copied + * and) used for the command + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_copy_environ(struct libexec_command *, const char *const *); + +/** + * Set the command's environment to a prebuilt list of + * environment variables + * + * @param cmd The command whose environment shall be set + * @param env The environment; the ownership of the input + * pointer and all pointers stored in it will be + * transfered to `cmd`, meaning that they will be + * deallocated using free(3) when they are removed + * or when `cmd` is destructed. If NULL, the + * commands environment will be reset to its default + * state, meaning that the calling process's environment + * (it will not be copied into `cmd`) will be used + * when running the command + */ +void libexec_set_environ(struct libexec_command *, char **); + +/** + * Clear a command's environment, removing all it's environment variables + * + * Even if the command's environment is in its default state (to + * use the calling process's environment), and calling process's + * environment is void of variables, the command's environment + * will be put in a non-default state, meaning that future changes + * to the calling process's environments variable will not affect + * the command's environment + * + * @param cmd The command whose environment shall be modified + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_clear_environ(struct libexec_command *); + +/** + * Remove all occurences of an environment variable + * in a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will be copied and set as the + * command's environment once the variable is found; however + * if the variable is not found within the environment, the + * command's environment will remain in its default state + * + * @param cmd The command whose environment shall be modified + * @param name The name of the variable to remove from the environment + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_unsetenv(struct libexec_command *, const char *); + +/** + * Remove the first occurence of an environment variable + * in a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will be copied and set as the + * command's environment once the variable is found; however + * if the variable is not found within the environment, the + * command's environment will remain in its default state + * + * @param cmd The command whose environment shall be modified + * @param name The name of the variable to remove from the environment + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_unsetenv_first(struct libexec_command *, const char *); + +/** + * Remove the last occurence of an environment variable + * in a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will be copied and set as the + * command's environment once the variable is found; however + * if the variable is not found within the environment, the + * command's environment will remain in its default state + * + * @param cmd The command whose environment shall be modified + * @param name The name of the variable to remove from the environment + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_unsetenv_last(struct libexec_command *, const char *); + + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * @param cmd The command whose environment shall be modified + * @param how Must be one of the following values: + * - LIBEXEC_REPLACE: + * If the environment already contains the + * variable, replace its first definition in + * the environment + * - LIBEXEC_NOREPLACE: + * Do not replacing already existing definition + * of the environment variable + * - LIBEXEC_NOCLOBBER: + * Fail if the environment already contains the + * variable, but has a different value + * - LIBEXEC_APPEND: + * Always the string to the end of the environment + * - LIBEXEC_PREPEND: + * Always the string to the beginning of the environment + * @param string The environment variable that should be put into + * the environment, unless `how` is `LIBEXEC_APPEND` + * or `LIBEXEC_PREPEND`, it must be in the form + * `"%s=%s", name, value` (where `name` does not + * contain an equal sign) + * @return 0 on success, -1 on failure + * + * @throws (unmodified) The environment variable already exists + * (Only if `how` is `LIBEXEC_NOCLOBBER`) + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_putenv(struct libexec_command *, enum libexec_insert_mode, const char *); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * @param cmd The command whose environment shall be modified + * @param how Must be one of the following values: + * - LIBEXEC_REPLACE: + * If the environment already contains the + * variable, replace its first definition in + * the environment + * - LIBEXEC_NOREPLACE: + * Do not replacing already existing definition + * of the environment variable + * - LIBEXEC_NOCLOBBER: + * Fail if the environment already contains the + * variable, but has a different value + * - LIBEXEC_APPEND: + * Always the string to the end of the environment + * - LIBEXEC_PREPEND: + * Always the string to the beginning of the environment + * @param fmt Formatting string, following the rules of printf(3), + * for the environment variable that should be put + * into the environment, unless `how` is `LIBEXEC_APPEND` + * or `LIBEXEC_PREPEND`, the resulting string must + * be in the form `"%s=%s", name, value` (where `name` + * does not contain an equal sign) + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + * + * @throws (unmodified) The environment variable already exists + * (Only if `how` is `LIBEXEC_NOCLOBBER`) + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_VPRINTF__(3) int libexec_vputenvf(struct libexec_command *, enum libexec_insert_mode, const char *, va_list); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * @param cmd The command whose environment shall be modified + * @param how Must be one of the following values: + * - LIBEXEC_REPLACE: + * If the environment already contains the + * variable, replace its first definition in + * the environment + * - LIBEXEC_NOREPLACE: + * Do not replacing already existing definition + * of the environment variable + * - LIBEXEC_NOCLOBBER: + * Fail if the environment already contains the + * variable, but has a different value + * - LIBEXEC_APPEND: + * Always the string to the end of the environment + * - LIBEXEC_PREPEND: + * Always the string to the beginning of the environment + * @param fmt Formatting string, following the rules of printf(3), + * for the environment variable that should be put + * into the environment, unless `how` is `LIBEXEC_APPEND` + * or `LIBEXEC_PREPEND`, the resulting string must + * be in the form `"%s=%s", name, value` (where `name` + * does not contain an equal sign) + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + * + * @throws (unmodified) The environment variable already exists + * (Only if `how` is `LIBEXEC_NOCLOBBER`) + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_PRINTF__(3) int libexec_putenvf(struct libexec_command *, enum libexec_insert_mode, const char *, ...); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * @param cmd The command whose environment shall be modified + * @param how Must be one of the following values: + * - LIBEXEC_REPLACE: + * If the environment already contains the + * variable, replace its first definition in + * the environment + * - LIBEXEC_NOREPLACE: + * Do not replacing already existing definition + * of the environment variable + * - LIBEXEC_NOCLOBBER: + * Fail if the environment already contains the + * variable, but has a different value + * - LIBEXEC_APPEND: + * Always the string to the end of the environment + * - LIBEXEC_PREPEND: + * Always the string to the beginning of the environment + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value The value that shall be associated with the + * environment variable + * @return 0 on success, -1 on failure + * + * @throws (unmodified) The environment variable already exists + * (Only if `how` is `LIBEXEC_NOCLOBBER`) + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_setenv(struct libexec_command *, enum libexec_insert_mode, const char *, const char *); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * @param cmd The command whose environment shall be modified + * @param how Must be one of the following values: + * - LIBEXEC_REPLACE: + * If the environment already contains the + * variable, replace its first definition in + * the environment + * - LIBEXEC_NOREPLACE: + * Do not replacing already existing definition + * of the environment variable + * - LIBEXEC_NOCLOBBER: + * Fail if the environment already contains the + * variable, but has a different value + * - LIBEXEC_APPEND: + * Always the string to the end of the environment + * - LIBEXEC_PREPEND: + * Always the string to the beginning of the environment + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value_fmt Formatting string, following the rules of printf(3), + * for the environment variable's value + * @param args Arguments for `value_fmt` + * @return 0 on success, -1 on failure + * + * @throws (unmodified) The environment variable already exists + * (Only if `how` is `LIBEXEC_NOCLOBBER`) + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_VPRINTF__(4) int libexec_vsetenvf(struct libexec_command *, enum libexec_insert_mode, const char *, const char *, va_list); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * @param cmd The command whose environment shall be modified + * @param how Must be one of the following values: + * - LIBEXEC_REPLACE: + * If the environment already contains the + * variable, replace its first definition in + * the environment + * - LIBEXEC_NOREPLACE: + * Do not replacing already existing definition + * of the environment variable + * - LIBEXEC_NOCLOBBER: + * Fail if the environment already contains the + * variable, but has a different value + * - LIBEXEC_APPEND: + * Always the string to the end of the environment + * - LIBEXEC_PREPEND: + * Always the string to the beginning of the environment + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value_fmt Formatting string, following the rules of printf(3), + * for the environment variable's value + * @param ... Arguments for `value_fmt` + * @return 0 on success, -1 on failure + * + * @throws (unmodified) The environment variable already exists + * (Only if `how` is `LIBEXEC_NOCLOBBER`) + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_PRINTF__(4) int libexec_setenvf(struct libexec_command *, enum libexec_insert_mode, const char *, const char *, ...); + + +/** + * Put an environment variable into a command's environment, + * replacing the first already existing definition of the + * variable if there is one + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_putenv(cmd, LIBEXEC_REPLACE, string)` + * + * @param cmd The command whose environment shall be modified + * @param string The environment variable that should be put into the + * environment, it must be in the form `"%s=%s", name, value` + * (where `name` does not contain an equal sign) + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_putenv_replace(struct libexec_command *, const char *); + +/** + * Put an environment variable into a command's environment, + * replacing the first already existing definition of the + * variable if there is one + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_vputenvf(cmd, LIBEXEC_REPLACE, fmt, args)` + * + * @param cmd The command whose environment shall be modified + * @param fmt Formatting string, following the rules of printf(3), + * for the environment variable that should be put + * into the environment, the resulting string must + * be in the form `"%s=%s", name, value` (where `name` + * does not contain an equal sign) + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_VPRINTF__(2) int libexec_vputenvf_replace(struct libexec_command *, const char *, va_list); + +/** + * Put an environment variable into a command's environment, + * replacing the first already existing definition of the + * variable if there is one + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_putenvf(cmd, LIBEXEC_REPLACE, fmt, ...)` + * + * @param cmd The command whose environment shall be modified + * @param fmt Formatting string, following the rules of printf(3), + * for the environment variable that should be put + * into the environment, the resulting string must + * be in the form `"%s=%s", name, value` (where `name` + * does not contain an equal sign) + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_PRINTF__(2) int libexec_putenvf_replace(struct libexec_command *, const char *, ...); + +/** + * Put an environment variable into a command's environment, + * replacing the first already existing definition of the + * variable if there is one + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_setenv(cmd, LIBEXEC_REPLACE, name, value)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value The value that shall be associated with the + * environment variable + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_setenv_replace(struct libexec_command *, const char *, const char *); + +/** + * Put an environment variable into a command's environment, + * replacing the first already existing definition of the + * variable if there is one + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_vsetenvf(cmd, LIBEXEC_REPLACE, name, value_fmt, args)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value_fmt Formatting string, following the rules of printf(3), + * for the environment variable's value + * @param args Arguments for `value_fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_VPRINTF__(3) int libexec_vsetenvf_replace(struct libexec_command *, const char *, const char *, va_list); + +/** + * Put an environment variable into a command's environment, + * replacing the first already existing definition of the + * variable if there is one + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_setenvf(cmd, LIBEXEC_REPLACE, name, value_fmt, ...)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value_fmt Formatting string, following the rules of printf(3), + * for the environment variable's value + * @param ... Arguments for `value_fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_PRINTF__(3) int libexec_setenvf_replace(struct libexec_command *, const char *, const char *, ...); + + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * If the environment variable already exists in the command's + * environment, the command's environment variable will not + * be modified, except that initialisation from default state + * as describe above will take place + * + * Equivalent to `libexec_putenv(cmd, LIBEXEC_NOREPLACE, string)` + * + * @param cmd The command whose environment shall be modified + * @param string The environment variable that should be put into the + * environment, it must be in the form `"%s=%s", name, value` + * (where `name` does not contain an equal sign) + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_putenv_noreplace(struct libexec_command *, const char *); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * If the environment variable already exists in the command's + * environment, the command's environment variable will not + * be modified, except that initialisation from default state + * as describe above will take place + * + * Equivalent to `libexec_vputenvf(cmd, LIBEXEC_NOREPLACE, fmt, args)` + * + * @param cmd The command whose environment shall be modified + * @param fmt Formatting string, following the rules of printf(3), + * for the environment variable that should be put + * into the environment, the resulting string must + * be in the form `"%s=%s", name, value` (where `name` + * does not contain an equal sign) + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_VPRINTF__(2) int libexec_vputenvf_noreplace(struct libexec_command *, const char *, va_list); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * If the environment variable already exists in the command's + * environment, the command's environment variable will not + * be modified, except that initialisation from default state + * as describe above will take place + * + * Equivalent to `libexec_putenvf(cmd, LIBEXEC_NOREPLACE, fmt, ...)` + * + * @param cmd The command whose environment shall be modified + * @param fmt Formatting string, following the rules of printf(3), + * for the environment variable that should be put + * into the environment, the resulting string must + * be in the form `"%s=%s", name, value` (where `name` + * does not contain an equal sign) + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_PRINTF__(2) int libexec_putenvf_noreplace(struct libexec_command *, const char *, ...); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * If the environment variable already exists in the command's + * environment, the command's environment variable will not + * be modified, except that initialisation from default state + * as describe above will take place + * + * Equivalent to `libexec_setenv(cmd, LIBEXEC_NOREPLACE, name, value)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value The value that shall be associated with the + * environment variable + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_setenv_noreplace(struct libexec_command *, const char *, const char *); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * If the environment variable already exists in the command's + * environment, the command's environment variable will not + * be modified, except that initialisation from default state + * as describe above will take place + * + * Equivalent to `libexec_vsetenvf(cmd, LIBEXEC_NOREPLACE, name, value_fmt, args)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value_fmt Formatting string, following the rules of printf(3), + * for the environment variable's value + * @param args Arguments for `value_fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_VPRINTF__(3) int libexec_vsetenvf_noreplace(struct libexec_command *, const char *, const char *, va_list); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * If the environment variable already exists in the command's + * environment, the command's environment variable will not + * be modified, except that initialisation from default state + * as describe above will take place + * + * Equivalent to `libexec_setenvf(cmd, LIBEXEC_NOREPLACE, name, value_fmt, ...)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value_fmt Formatting string, following the rules of printf(3), + * for the environment variable's value + * @param ... Arguments for `value_fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_PRINTF__(3) int libexec_setenvf_noreplace(struct libexec_command *, const char *, const char *, ...); + + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * If the environment variable already exists in the command's + * environment, but has a different value, the function will + * fail without side effects + * + * Equivalent to `libexec_putenv(cmd, LIBEXEC_NOCLOBBER, string)` + * + * @param cmd The command whose environment shall be modified + * @param string The environment variable that should be put into the + * environment, it must be in the form `"%s=%s", name, value` + * (where `name` does not contain an equal sign) + * @return 0 on success, -1 on failure + * + * @throws (unmodified) The environment variable already exists + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_putenv_noclobber(struct libexec_command *, const char *); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * If the environment variable already exists in the command's + * environment, but has a different value, the function will + * fail without side effects + * + * Equivalent to `libexec_vputenvf(cmd, LIBEXEC_NOCLOBBER, fmt, args)` + * + * @param cmd The command whose environment shall be modified + * @param fmt Formatting string, following the rules of printf(3), + * for the environment variable that should be put + * into the environment, the resulting string must + * be in the form `"%s=%s", name, value` (where `name` + * does not contain an equal sign) + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + * + * @throws (unmodified) The environment variable already exists + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_VPRINTF__(2) int libexec_vputenvf_noclobber(struct libexec_command *, const char *, va_list); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * If the environment variable already exists in the command's + * environment, but has a different value, the function will + * fail without side effects + * + * Equivalent to `libexec_putenvf(cmd, LIBEXEC_NOCLOBBER, fmt, ...)` + * + * @param cmd The command whose environment shall be modified + * @param fmt Formatting string, following the rules of printf(3), + * for the environment variable that should be put + * into the environment, the resulting string must + * be in the form `"%s=%s", name, value` (where `name` + * does not contain an equal sign) + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + * + * @throws (unmodified) The environment variable already exists + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_PRINTF__(2) int libexec_putenvf_noclobber(struct libexec_command *, const char *, ...); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * If the environment variable already exists in the command's + * environment, but has a different value, the function will + * fail without side effects + * + * Equivalent to `libexec_setenv(cmd, LIBEXEC_NOCLOBBER, name, value)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value The value that shall be associated with the + * environment variable + * @return 0 on success, -1 on failure + * + * @throws (unmodified) The environment variable already exists + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_setenv_noclobber(struct libexec_command *, const char *, const char *); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * If the environment variable already exists in the command's + * environment, but has a different value, the function will + * fail without side effects + * + * Equivalent to `libexec_vsetenvf(cmd, LIBEXEC_NOCLOBBER, name, value_fmt, args)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value_fmt Formatting string, following the rules of printf(3), + * for the environment variable's value + * @param args Arguments for `value_fmt` + * @return 0 on success, -1 on failure + * + * @throws (unmodified) The environment variable already exists + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_VPRINTF__(3) int libexec_vsetenvf_noclobber(struct libexec_command *, const char *, const char *, va_list); + +/** + * Put an environment variable into a command's environment + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * If the environment variable already exists in the command's + * environment, but has a different value, the function will + * fail without side effects + * + * Equivalent to `libexec_setenvf(cmd, LIBEXEC_NOCLOBBER, name, value_fmt, ...)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value_fmt Formatting string, following the rules of printf(3), + * for the environment variable's value + * @param ... Arguments for `value_fmt` + * @return 0 on success, -1 on failure + * + * @throws (unmodified) The environment variable already exists + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_PRINTF__(3) int libexec_setenvf_noclobber(struct libexec_command *, const char *, const char *, ...); + + +/** + * Put an environment variable into a command's environment, + * adding it to the end of the environment regardless of + * whether the variable already exists + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_putenv(cmd, LIBEXEC_APPEND, string)` + * + * @param cmd The command whose environment shall be modified + * @param string The environment variable that should be put into the + * environment; there is no requirement that it contains + * an equal sign + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_putenv_append(struct libexec_command *, const char *); + +/** + * Put an environment variable into a command's environment, + * adding it to the end of the environment regardless of + * whether the variable already exists + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_vputenvf(cmd, LIBEXEC_APPEND, fmt, args)` + * + * @param cmd The command whose environment shall be modified + * @param fmt Formatting string, following the rules of printf(3), + * for the environment variable that should be put + * into the environment; there is no requirement that + * the resulting string contains an equal sign + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_VPRINTF__(2) int libexec_vputenvf_append(struct libexec_command *, const char *, va_list); + +/** + * Put an environment variable into a command's environment, + * adding it to the end of the environment regardless of + * whether the variable already exists + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_putenvf(cmd, LIBEXEC_APPEND, fmt, ...)` + * + * @param cmd The command whose environment shall be modified + * @param fmt Formatting string, following the rules of printf(3), + * for the environment variable that should be put + * into the environment; there is no requirement that + * the resulting string contains an equal sign + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_PRINTF__(2) int libexec_putenvf_append(struct libexec_command *, const char *, ...); + +/** + * Put an environment variable into a command's environment, + * adding it to the end of the environment regardless of + * whether the variable already exists + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_setenv(cmd, LIBEXEC_APPEND, name, value)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value The value that shall be associated with the + * environment variable + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_setenv_append(struct libexec_command *, const char *, const char *); + +/** + * Put an environment variable into a command's environment, + * adding it to the end of the environment regardless of + * whether the variable already exists + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_vsetenvf(cmd, LIBEXEC_APPEND, name, value_fmt, args)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value_fmt Formatting string, following the rules of printf(3), + * for the environment variable's value + * @param args Arguments for `value_fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_VPRINTF__(3) int libexec_vsetenvf_append(struct libexec_command *, const char *, const char *, va_list); + +/** + * Put an environment variable into a command's environment, + * adding it to the end of the environment regardless of + * whether the variable already exists + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_setenvf(cmd, LIBEXEC_APPEND, name, value_fmt, ...)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value_fmt Formatting string, following the rules of printf(3), + * for the environment variable's value + * @param ... Arguments for `value_fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_PRINTF__(3) int libexec_setenvf_append(struct libexec_command *, const char *, const char *, ...); + + +/** + * Put an environment variable into a command's environment, + * adding it to the beginning of the environment regardless + * of whether the variable already exists + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_putenv(cmd, LIBEXEC_PREPEND, string)` + * + * @param cmd The command whose environment shall be modified + * @param string The environment variable that should be put into the + * environment; there is no requirement that it contains + * an equal sign + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_putenv_prepend(struct libexec_command *, const char *); + +/** + * Put an environment variable into a command's environment, + * adding it to the beginning of the environment regardless + * of whether the variable already exists + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_vputenvf(cmd, LIBEXEC_PREPEND, fmt, args)` + * + * @param cmd The command whose environment shall be modified + * @param fmt Formatting string, following the rules of printf(3), + * for the environment variable that should be put + * into the environment; there is no requirement that + * the resulting string contains an equal sign + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_VPRINTF__(2) int libexec_vputenvf_prepend(struct libexec_command *, const char *, va_list); + +/** + * Put an environment variable into a command's environment, + * adding it to the beginning of the environment regardless + * of whether the variable already exists + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_putenvf(cmd, LIBEXEC_PREPEND, fmt, ...)` + * + * @param cmd The command whose environment shall be modified + * @param fmt Formatting string, following the rules of printf(3), + * for the environment variable that should be put + * into the environment; there is no requirement that + * the resulting string contains an equal sign + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_PRINTF__(2) int libexec_putenvf_prepend(struct libexec_command *, const char *, ...); + +/** + * Put an environment variable into a command's environment, + * adding it to the beginning of the environment regardless + * of whether the variable already exists + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_setenv(cmd, LIBEXEC_PREPEND, name, value)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value The value that shall be associated with the + * environment variable + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + */ +int libexec_setenv_prepend(struct libexec_command *, const char *, const char *); + +/** + * Put an environment variable into a command's environment, + * adding it to the beginning of the environment regardless + * of whether the variable already exists + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_vsetenvf(cmd, LIBEXEC_PREPEND, name, value_fmt, args)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value_fmt Formatting string, following the rules of printf(3), + * for the environment variable's value + * @param args Arguments for `value_fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_VPRINTF__(3) int libexec_vsetenvf_prepend(struct libexec_command *, const char *, const char *, va_list); + +/** + * Put an environment variable into a command's environment, + * adding it to the beginning of the environment regardless + * of whether the variable already exists + * + * If the command's environment is in its default state (to + * use the calling process's environment), the calling + * process's environment will first be copied and set as the + * command's environment + * + * Equivalent to `libexec_setenvf(cmd, LIBEXEC_PREPEND, name, value_fmt, ...)` + * + * @param cmd The command whose environment shall be modified + * @param name The name of the environment variable, must not + * contain an equal sign + * @param value_fmt Formatting string, following the rules of printf(3), + * for the environment variable's value + * @param ... Arguments for `value_fmt` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory to modify the command's environment + * @throws EILSEQ According to printf(3) + * @throws EOVERFLOW According to printf(3) + */ +LIBEXEC_PRINTF__(3) int libexec_setenvf_prepend(struct libexec_command *, const char *, const char *, ...); + + +/** + * Put a series of commands in a pipeline, piping each's + * standard output to the next's (when there is one) + * standard input + * + * Pluming data added to the commands will prefix any + * already existing pluming information + * + * @param how Which type of file should be used to pipe + * together commands, and additional options. + * Must be one of the following values: + * - LIBEXEC_PIPE: + * Use a normal pipe(7) + * - LIBEXEC_SOCK_STREAM + * Use a unix(7) socketpair(3) with the type SOCK_STREAM + * - LIBEXEC_SOCK_SEQPACKET + * Use a unix(7) socketpair(3) with the type SOCK_SEQPACKET + * - LIBEXEC_SOCK_DGRAM + * Use a unix(7) socketpair(3) with the type SOCK_DGRAM + * - LIBEXEC_DIRECT_PIPE + * Use an O_DIRECT pipe(7) (see pipe2(2)) + * Optionally, the file type may be OR'ed with + * LIBEXEC_PIPE_CIRCULARLY to pipe the last + * command's standard output to the first command's + * standard input. + * @param cmds List of commands to put in a pipeline + * @param n The number of elements in `cmds` + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory + */ +int libexec_pipe_commandsvn(enum libexec_pipe how, struct libexec_command *const *cmds, size_t n); + +/** + * Put a series of commands in a pipeline, piping each's + * standard output to the next's (when there is one) + * standard input + * + * Pluming data added to the commands will prefix any + * already existing pluming information + * + * @param how Which type of file should be used to pipe + * together commands, and additional options. + * Must be one of the following values: + * - LIBEXEC_PIPE: + * Use a normal pipe(7) + * - LIBEXEC_SOCK_STREAM + * Use a unix(7) socketpair(3) with the type SOCK_STREAM + * - LIBEXEC_SOCK_SEQPACKET + * Use a unix(7) socketpair(3) with the type SOCK_SEQPACKET + * - LIBEXEC_SOCK_DGRAM + * Use a unix(7) socketpair(3) with the type SOCK_DGRAM + * - LIBEXEC_DIRECT_PIPE + * Use an O_DIRECT pipe(7) (see pipe2(2)) + * Optionally, the file type may be OR'ed with + * LIBEXEC_PIPE_CIRCULARLY to pipe the last + * command's standard output to the first command's + * standard input. + * @param cmds `NULL` terminated list of commands to put in a pipeline + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory + */ +int libexec_pipe_commandsv(enum libexec_pipe how, struct libexec_command *const *cmds); + +/** + * Put a series of commands in a pipeline, piping each's + * standard output to the next's (when there is one) + * standard input + * + * Pluming data added to the commands will prefix any + * already existing pluming information + * + * @param how Which type of file should be used to pipe + * together commands, and additional options. + * Must be one of the following values: + * - LIBEXEC_PIPE: + * Use a normal pipe(7) + * - LIBEXEC_SOCK_STREAM + * Use a unix(7) socketpair(3) with the type SOCK_STREAM + * - LIBEXEC_SOCK_SEQPACKET + * Use a unix(7) socketpair(3) with the type SOCK_SEQPACKET + * - LIBEXEC_SOCK_DGRAM + * Use a unix(7) socketpair(3) with the type SOCK_DGRAM + * - LIBEXEC_DIRECT_PIPE + * Use an O_DIRECT pipe(7) (see pipe2(2)) + * Optionally, the file type may be OR'ed with + * LIBEXEC_PIPE_CIRCULARLY to pipe the last + * command's standard output to the first command's + * standard input. + * @param args `NULL` terminated list of commands to put in a pipeline + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory + */ +int libexec_vpipe_commands(enum libexec_pipe how, va_list args); + +/** + * Put a series of commands in a pipeline, piping each's + * standard output to the next's (when there is one) + * standard input + * + * Pluming data added to the commands will prefix any + * already existing pluming information + * + * @param how Which type of file should be used to pipe + * together commands, and additional options. + * Must be one of the following values: + * - LIBEXEC_PIPE: + * Use a normal pipe(7) + * - LIBEXEC_SOCK_STREAM + * Use a unix(7) socketpair(3) with the type SOCK_STREAM + * - LIBEXEC_SOCK_SEQPACKET + * Use a unix(7) socketpair(3) with the type SOCK_SEQPACKET + * - LIBEXEC_SOCK_DGRAM + * Use a unix(7) socketpair(3) with the type SOCK_DGRAM + * - LIBEXEC_DIRECT_PIPE + * Use an O_DIRECT pipe(7) (see pipe2(2)) + * Optionally, the file type may be OR'ed with + * LIBEXEC_PIPE_CIRCULARLY to pipe the last + * command's standard output to the first command's + * standard input. + * @param ... `NULL` terminated list of commands to put in a pipeline + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid argument input + * @throws ENOMEM Failed to allocate enough memory + */ +int libexec_pipe_commands(enum libexec_pipe how, ...); + + +int libexec_get_documents(struct libexec_command *cmd, struct libexec_document **docsp, size_t *ndocsp, int flags); +int libexec_exec(struct libexec_command *cmd); +int libexec_spawn(pid_t *out, struct libexec_command *cmd, + int (*after_fork)(struct libexec_command *cmd, int new_fd, void *user), + void *user, struct libexec_document **docsp, size_t *ndocsp, int doc_fd_flags); +int libexec_send_document(struct libexec_document *doc); +int libexec_recv_document(struct libexec_document *doc); + +/* TODO maybe its better to have `struct libexec_run_how` */ +int libexec_run_pipeline(int (*on_alien_epoll)(int alien_epoll, uint32_t events, void *user1), int alien_epoll, void *user1, + int (*on_alien_child_death)(pid_t pid, void *user2), void *user2, + int (*after_fork)(struct libexec_command *cmd, int new_fd, void *user3), void *user3, + int (*reap_mutex_control)(int action /* -1 = acquire, +1 = release */, void *user4), void *user4, + int (*on_interrupt)(void *user5), void *user5, + const sigset_t *sigmask /* nullable */, + struct libexec_document *const *docs, size_t ndocs, int docs_1_level, + struct libexec_command *const *cmds, int *exit_statuses_out /* nullable */, size_t ncmds); +#define LIBEXEC_RUN_PIPELINE_NO_EPOLL NULL, -1, NULL +#define LIBEXEC_RUN_PIPELINE_NO_CHILDREN NULL, NULL +#define LIBEXEC_RUN_PIPELINE_NO_AFTER_FORK NULL, NULL +#define LIBEXEC_RUN_PIPELINE_NO_THREADING NULL, NULL +#define LIBEXEC_RUN_PIPELINE_NO_INTERRUPT NULL, NULL +#define LIBEXEC_RUN_PIPELINE_NO_SIGMASK NULL +#define LIBEXEC_RUN_PIPELINE_NO_OUTPUT NULL, 0, 0 +#define LIBEXEC_RUN_PIPELINE_ONLY_OUTPUT\ + LIBEXEC_RUN_PIPELINE_NO_EPOLL,\ + LIBEXEC_RUN_PIPELINE_NO_CHILDREN,\ + LIBEXEC_RUN_PIPELINE_NO_AFTER_FORK,\ + LIBEXEC_RUN_PIPELINE_NO_THREADING,\ + LIBEXEC_RUN_PIPELINE_NO_INTERRUPT +#define LIBEXEC_RUN_PIPELINE_NOTHING\ + LIBEXEC_RUN_PIPELINE_ONLY_OUTPUT,\ + LIBEXEC_RUN_PIPELINE_NO_OUTPUT + +int libexec_vrun(struct libexec_result *out, va_list args); +int libexec_run(struct libexec_result *out, ...); + + +#endif |