/* See LICENSE file for copyright and license details. */ #ifndef LIBEXEC_H #define LIBEXEC_H #if defined(__linux__) # include #endif #include #include #include #include #include #include #include /* 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