/* See LICENSE file for copyright and license details. */
#ifndef LIBEXEC_H
#define LIBEXEC_H
#if defined(__linux__)
# include <linux/openat2.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
/* For internal use only (may be removed in the future) { */
#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_VA_IMPL__(LAST, FUNC, ...)\
int ret;\
va_list args;\
va_start(args, LAST);\
ret = FUNC(__VA_ARGS__, args);\
va_end(args);\
return ret
/* } */
/**
* Used to specify which version of the library
* the application is compiled against, so that
* the library knowns the layout of structures
* that may be modified in future versions
*
* This is currently used for:
* - `struct libexec_command`
*/
#define LIBEXEC_VERSION 0U
/**
* Specifies how an element should be inserted
* into a list
*
* This is currently used for:
* - `libexec_putenv`
* - `libexec_putenvf`
* - `libexec_vputenvf`
* - `libexec_setenv`
* - `libexec_setenvf`
* - `libexec_vsetenvf`
*/
enum libexec_insert_mode {
/**
* Append to list, but if the an element with the same
* key is used, replace the first occurrence of it
*/
LIBEXEC_REPLACE, /* replace existing definition if any */
/**
* Append to list except if the an element with the same
* key is used, then do nothing
*/
LIBEXEC_NOREPLACE,
/**
* Append to list except if the an element with the same
* key is used, then do nothing but indicate fail
*/
LIBEXEC_NOCLOBBER,
/**
* Add to the end of the list regardless of whether
* there already is an element with the same key in he list
*
* If used in `libexec_putenv`, `libexec_putenvf`, or
* `libexec_vputenvf`, that function will accept the
* new element even if it doesn't use a key–value
* construction
*/
LIBEXEC_APPEND,
/**
* Add to the beginning of the list regardless of whether
* there already is an element with the same key in he list
*
* If used in `libexec_putenv`, `libexec_putenvf`, or
* `libexec_vputenvf`, that function will accept the
* new element even if it doesn't use a key–value
* construction
*/
LIBEXEC_PREPEND
#define LIBEXEC_INSERT_MODE__COUNT__ 5 /* For internal use only (may be removed in the future) */
};
/**
* Modification to command's set of file descriptors
*/
enum libexec_pluming_type {
/**
* Perform an openat(3) call, and change the
* number of the new file descriptor to a
* desired number
*/
LIBEXEC_PLUMING_OPENAT,
/**
* Perform an openat2(2) call, and change the
* number of the new file descriptor to a
* desired number
*/
LIBEXEC_PLUMING_OPENAT2,
/**
* Close a specific file descriptor
*/
LIBEXEC_PLUMING_CLOSE,
/**
* Perform an dup2(3) call to duplicate
* a file descriptor
*/
LIBEXEC_PLUMING_DUP2,
/**
* Pass text from the application's memory
* into the child process via a pipe, whose
* read-end will have a selected number;
* the write-end will not be exposed to the
* child process
*/
LIBEXEC_PLUMING_DOCUMENT,
/**
* Expose a file descriptor from the application
* using a selected file descriptor number
*
* Note that unless a file descriptor from the
* application is explicitly close it will
* still be exposed to the child process; this
* merely changes the file descriptor number
*/
LIBEXEC_PLUMING_PIPE
#define LIBEXEC_PLUMING_TYPE__COUNT__ 6 /* For internal use only (may be removed in the future) */
};
/**
* Specifies how two commands shall be connected
*
* The value should be `LIBEXEC_PIPE`, `LIBEXEC_SOCK_STREAM`,
* `LIBEXEC_SOCK_SEQPACKET`, `LIBEXEC_SOCK_DGRAM, or
* `LIBEXEC_DIRECT_PIPE`, optionally OR'ed with
* `LIBEXEC_PIPE_CIRCULARLY`
*/
enum libexec_pipe {
/**
* Use a normal pipe(7) to connect the two commands
*/
LIBEXEC_PIPE = 0,
/**
* Use a unix(7) socketpair(3) with the type `SOCK_STREAM`
*/
LIBEXEC_SOCK_STREAM = 1,
/**
* Use a unix(7) socketpair(3) with the type `SOCK_SEQPACKET`
*/
LIBEXEC_SOCK_SEQPACKET = 2,
/**
* Use a unix(7) socketpair(3) with the type `SOCK_DGRAM`
*/
LIBEXEC_SOCK_DGRAM = 3,
/**
* Use a pipe(7) created with `O_DIRECT` (see pipe2(2))
* to connect the two commands
*/
LIBEXEC_DIRECT_PIPE = 4,
/**
* Pipe the standard output of the last command to
* the standard input of the first command, in addition
* to piping the standard output of each command to
* the standard input of the next command
*/
LIBEXEC_PIPE_CIRCULARLY = 0x8000
#define LIBEXEC_PIPE__COUNT__ 5 /* For internal use only (may be removed in the future) */
};
/**
* Specifies which exec(3) function should be used
*/
enum libexec_locate_method {
/**
* p-class exec(3) function shall be used,
* that is, the executable may either be
* a relative or absolute path, but it may
* also be the name of a program that can
* be found in PATH. PATH is used, if and
* only if, the specified executable contains
* a slash
*/
LIBEXEC_ALLOW_NAME,
/**
* non-p-class exec(3) function shall be used,
* that is, the executable must be a relative
* or absolute path
*/
LIBEXEC_REQUIRE_PATH,
/**
* f-class exec(3) function shall be used,
* that is, a file descriptor to the executable
* is used
*/
LIBEXEC_EXEC_FD,
/**
* at-class exec(3) function shall be used,
* that is, a function like execveat(2),
* where the executable is specified via
* a directory file descriptor (or `AT_FDCWD`)
* paired with a pathname, and AT_-flags,
* is used
*/
LIBEXEC_EXEC_AT
#define LIBEXEC_LOCATE_METHOD__COUNT__ 4 /* For internal use only (may be removed in the future) */
};
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 /* For internal use only (may be removed in the future) */
};
#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;
};
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;
};
#define LIBEXEC_COMMAND_INIT\
((struct libexec_command){LIBEXEC_VERSION, LIBEXEC_ALLOW_NAME, -1, NULL, NULL, 0, NULL, 0, NULL})
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);
inline int libexec_construct_command(struct libexec_command *cmd, const char *fmt, ...)
{ LIBEXEC_VA_IMPL__(fmt, libexec_vconstruct_command, cmd, fmt); }
int libexec_put_argumentsn(struct libexec_command *cmd, const char *const *args, size_t nargs);
inline int libexec_put_arguments(struct libexec_command *cmd, const char *const *args)
{
size_t n = 0;
if (!args) {
errno = EINVAL;
return -1;
}
while (args[n])
n += 1;
return libexec_put_argumentsn(cmd, args, n);
}
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_openat(struct libexec_command *cmd, int fd, int dirfd, const char *file, int flags, mode_t mode);
inline int libexec_open(struct libexec_command *cmd, int fd, const char *file, int flags, mode_t mode)
{ return libexec_openat(cmd, fd, AT_FDCWD, file, flags, 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);
inline int libexec_input_text_copy(struct libexec_command *cmd, int fd, const char *text)
{
if (!text) {
errno = EINVAL;
return -1;
}
return libexec_input_data_copy(cmd, fd, text, strlen(text));
}
inline int libexec_input_text_gift(struct libexec_command *cmd, int fd, char *text)
{
if (!text) {
errno = EINVAL;
return -1;
}
return libexec_input_data_gift(cmd, fd, text, strlen(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) inline int
libexec_putenvf(struct libexec_command *cmd, enum libexec_insert_mode how, const char *fmt, ...)
{ LIBEXEC_VA_IMPL__(fmt, libexec_vputenvf, cmd, how, fmt); }
/**
* 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) inline int
libexec_setenvf(struct libexec_command *cmd, enum libexec_insert_mode how, const char *name, const char *value_fmt, ...)
{ LIBEXEC_VA_IMPL__(value_fmt, libexec_vsetenvf, cmd, how, name, value_fmt); }
/**
* 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
*/
inline int
libexec_putenv_replace(struct libexec_command *cmd, const char *string)
{ return libexec_putenv(cmd, LIBEXEC_REPLACE, string); }
/**
* 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) inline int
libexec_vputenvf_replace(struct libexec_command *cmd, const char *fmt, va_list args)
{ return libexec_vputenvf(cmd, LIBEXEC_REPLACE, fmt, args); }
/**
* 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) inline int
libexec_putenvf_replace(struct libexec_command *cmd, const char *fmt, ...)
{ LIBEXEC_VA_IMPL__(fmt, libexec_vputenvf_replace, cmd, fmt); }
/**
* 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
*/
inline int
libexec_setenv_replace(struct libexec_command *cmd, const char *name, const char *value)
{ return libexec_setenv(cmd, LIBEXEC_REPLACE, name, value); }
/**
* 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) inline int
libexec_vsetenvf_replace(struct libexec_command *cmd, const char *name, const char *value_fmt, va_list args)
{ return libexec_vsetenvf(cmd, LIBEXEC_REPLACE, name, value_fmt, args); }
/**
* 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) inline int
libexec_setenvf_replace(struct libexec_command *cmd, const char *name, const char *value_fmt, ...)
{ LIBEXEC_VA_IMPL__(value_fmt, libexec_vsetenvf_replace, cmd, name, value_fmt); }
/**
* 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
*/
inline int
libexec_putenv_noreplace(struct libexec_command *cmd, const char *string)
{ return libexec_putenv(cmd, LIBEXEC_NOREPLACE, string); }
/**
* 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) inline int
libexec_vputenvf_noreplace(struct libexec_command *cmd, const char *fmt, va_list args)
{ return libexec_vputenvf(cmd, LIBEXEC_NOREPLACE, fmt, args); }
/**
* 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) inline int
libexec_putenvf_noreplace(struct libexec_command *cmd, const char *fmt, ...)
{ LIBEXEC_VA_IMPL__(fmt, libexec_vputenvf_noreplace, cmd, fmt); }
/**
* 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
*/
inline int
libexec_setenv_noreplace(struct libexec_command *cmd, const char *name, const char *value)
{ return libexec_setenv(cmd, LIBEXEC_NOREPLACE, name, value); }
/**
* 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) inline int
libexec_vsetenvf_noreplace(struct libexec_command *cmd, const char *name, const char *value_fmt, va_list args)
{ return libexec_vsetenvf(cmd, LIBEXEC_NOREPLACE, name, value_fmt, args); }
/**
* 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) inline int
libexec_setenvf_noreplace(struct libexec_command *cmd, const char *name, const char *value_fmt, ...)
{ LIBEXEC_VA_IMPL__(value_fmt, libexec_vsetenvf_noreplace, cmd, name, value_fmt); }
/**
* 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
*/
inline int
libexec_putenv_noclobber(struct libexec_command *cmd, const char *string)
{ return libexec_putenv(cmd, LIBEXEC_NOCLOBBER, string); }
/**
* 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) inline int
libexec_vputenvf_noclobber(struct libexec_command *cmd, const char *fmt, va_list args)
{ return libexec_vputenvf(cmd, LIBEXEC_NOCLOBBER, fmt, args); }
/**
* 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) inline int
libexec_putenvf_noclobber(struct libexec_command *cmd, const char *fmt, ...)
{ LIBEXEC_VA_IMPL__(fmt, libexec_vputenvf_noclobber, cmd, fmt); }
/**
* 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
*/
inline int
libexec_setenv_noclobber(struct libexec_command *cmd, const char *name, const char *value)
{ return libexec_setenv(cmd, LIBEXEC_NOCLOBBER, name, value); }
/**
* 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) inline int
libexec_vsetenvf_noclobber(struct libexec_command *cmd, const char *name, const char *value_fmt, va_list args)
{ return libexec_vsetenvf(cmd, LIBEXEC_NOCLOBBER, name, value_fmt, args); }
/**
* 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) inline int
libexec_setenvf_noclobber(struct libexec_command *cmd, const char *name, const char *value_fmt, ...)
{ LIBEXEC_VA_IMPL__(value_fmt, libexec_vsetenvf_noclobber, cmd, name, value_fmt); }
/**
* 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
*/
inline int
libexec_putenv_append(struct libexec_command *cmd, const char *string)
{ return libexec_putenv(cmd, LIBEXEC_APPEND, string); }
/**
* 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) inline int
libexec_vputenvf_append(struct libexec_command *cmd, const char *fmt, va_list args)
{ return libexec_vputenvf(cmd, LIBEXEC_APPEND, fmt, args); }
/**
* 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) inline int
libexec_putenvf_append(struct libexec_command *cmd, const char *fmt, ...)
{ LIBEXEC_VA_IMPL__(fmt, libexec_vputenvf_append, cmd, fmt); }
/**
* 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
*/
inline int
libexec_setenv_append(struct libexec_command *cmd, const char *name, const char *value)
{ return libexec_setenv(cmd, LIBEXEC_APPEND, name, value); }
/**
* 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) inline int
libexec_vsetenvf_append(struct libexec_command *cmd, const char *name, const char *value_fmt, va_list args)
{ return libexec_vsetenvf(cmd, LIBEXEC_APPEND, name, value_fmt, args); }
/**
* 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) inline int
libexec_setenvf_append(struct libexec_command *cmd, const char *name, const char *value_fmt, ...)
{ LIBEXEC_VA_IMPL__(value_fmt, libexec_vsetenvf_append, cmd, name, value_fmt); }
/**
* 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
*/
inline int
libexec_putenv_prepend(struct libexec_command *cmd, const char *string)
{ return libexec_putenv(cmd, LIBEXEC_PREPEND, string); }
/**
* 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) inline int
libexec_vputenvf_prepend(struct libexec_command *cmd, const char *fmt, va_list args)
{ return libexec_vputenvf(cmd, LIBEXEC_PREPEND, fmt, args); }
/**
* 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) inline int
libexec_putenvf_prepend(struct libexec_command *cmd, const char *fmt, ...)
{ LIBEXEC_VA_IMPL__(fmt, libexec_vputenvf_prepend, cmd, fmt); }
/**
* 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
*/
inline int
libexec_setenv_prepend(struct libexec_command *cmd, const char *name, const char *value)
{ return libexec_setenv(cmd, LIBEXEC_PREPEND, name, value); }
/**
* 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) inline int
libexec_vsetenvf_prepend(struct libexec_command *cmd, const char *name, const char *value_fmt, va_list args)
{ return libexec_vsetenvf(cmd, LIBEXEC_PREPEND, name, value_fmt, args); }
/**
* 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) inline int
libexec_setenvf_prepend(struct libexec_command *cmd, const char *name, const char *value_fmt, ...)
{ LIBEXEC_VA_IMPL__(value_fmt, libexec_vsetenvf_prepend, cmd, name, value_fmt); }
/**
* 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, struct libexec_command *const *, size_t);
/**
* 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
*/
inline int
libexec_pipe_commandsv(enum libexec_pipe how, struct libexec_command *const *cmds)
{
size_t n = 0;
if (!cmds) {
errno = EINVAL;
return -1;
}
while (cmds[n])
n++;
return libexec_pipe_commandsvn(how, cmds, 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 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, va_list);
/**
* 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
*/
inline int
libexec_pipe_commands(enum libexec_pipe how, ...)
{ LIBEXEC_VA_IMPL__(how, libexec_vpipe_commands, 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);
inline int libexec_run(struct libexec_result *out, ...)
{ LIBEXEC_VA_IMPL__(out, libexec_vrun, out); }
#endif