The execute "as" additions are very much incomplete as of this commit.
F_block_not,
F_bound,
F_bound_not,
+ F_capability,
+ F_capability_not,
F_child,
F_child_not,
F_complete,
F_complete_not,
F_connected,
F_connected_not,
+ F_container,
+ F_container_not,
F_critical,
F_critical_not,
F_deadlock,
F_fork_not,
F_found,
F_found_not,
+ F_group,
+ F_group_not,
+ F_ignore,
+ F_ignore_not,
F_input,
F_input_not,
F_input_output,
F_mount_not,
F_name,
F_name_not,
+ F_nice,
+ F_nice_not,
F_optional,
F_optional_not,
F_output,
F_resource_not,
F_search,
F_search_not,
+ F_schedule,
+ F_schedule_not,
F_signal,
F_signal_not,
F_space,
F_supported_not,
F_syntax,
F_syntax_not,
+ F_user,
+ F_user_not,
F_utf,
F_utf_not,
F_valid,
F_wait_not,
F_warn,
F_warn_not,
+ F_world,
+ F_world_not,
F_write,
F_write_not,
F_write_only,
set.data = 0;
#endif // _di_fl_execute_parameter_t_
+/**
+ * A structure representing an array of group ids.
+ *
+ * groups: a pointer to an array of groups.
+ * size: the length of the array of groups.
+ */
+#ifndef _di_fl_execute_groups_t_
+ typedef struct {
+ gid_t *groups;
+ f_array_length_t size;
+ } fl_execute_groups_t;
+
+ #define fl_execute_groups_t_initialize { 0, 0 }
+
+ #define fl_macro_execute_groups_t_initialize(groups, size) { groups, size }
+
+ #define fl_execute_groups_t_clear(structure) \
+ structure.groups = 0; \
+ structure.size = 0;
+#endif // _di_fl_execute_groups_t_
+
+/**
+ * A structure representing a scheduler and its parameters for execution.
+ *
+ * policy: the scheduler policy.
+ * parameter: a pointer to the scheduler parameters;
+ */
+#ifndef _di_fl_execute_scheduler_t_
+ typedef struct {
+ int policy;
+ const struct sched_param *parameter;
+ } fl_execute_scheduler_t;
+
+ #define fl_execute_scheduler_t_initialize { 0, 0 }
+
+ #define fl_macro_execute_scheduler_t_initialize(policy, parameter) { policy, parameter }
+
+ #define fl_execute_scheduler_t_clear(scheduler) \
+ scheduler.policy = 0; \
+ scheduler.parameter = 0;
+#endif // _di_fl_execute_scheduler_t_
+
+/**
+ * A structure for containing identity and access related parameters for the execute functions that call the execv() family of functions.
+ *
+ * There are likely many more identity and access related things that can be done but this focuses on a small core set of those.
+ *
+ * Note: Containers, or cgroups, exist here as a full file path in which the PID of a child process is to be written to.
+ * This may change as more is learned about using cgroups, but it is not known if there are any functions available like set_cgroup(..).
+ *
+ * nice: the niceness value to assign the child process to, set to 0 to not use.
+ * id_user: the id of the user to assign the child process to, set to 0 to not use.
+ * id_group: the id of the group to assign the child process to, set to 0 to not use.
+ * capability: all of the capabilities to assign the child process to, set to 0 to not use.
+ * ids_group: the ids of each supplemental group to assign the child process to, set to 0 to not use.
+ * scheduler: the scheduler to assign the child process to, set to 0 to not use.
+ * containers: an array of cgroups (container groups) to assign the child PID to, set to 0 to not use.
+ */
+#ifndef _di_fl_execute_as_t_
+ typedef struct {
+ const int *nice;
+ const uid_t *id_user;
+ const gid_t *id_group;
+ //const cap_t *capability; // @todo
+
+ const fl_execute_groups_t *ids_group;
+ const fl_execute_scheduler_t *scheduler;
+ const f_string_dynamics_t *containers;
+ } fl_execute_as_t;
+
+ #define fl_execute_as_t_initialize { 0, 0, 0, /*0,*/ fl_execute_groups_t_initialize, fl_execute_scheduler_t_initialize, f_string_dynamics_t_initialize }
+
+ #define fl_macro_execute_as_t_initialize(nice, id_user, id_group, /*capability,*/ id_groups, scheduler, containers) { nice, id_user, id_group, /*capability,*/ id_groups, scheduler, containers }
+
+ #define fl_execute_as_t_clear(as) \
+ as.nice = 0; \
+ as.id_user = 0; \
+ as.id_group = 0; \
+ /*as.capability = 0;*/ \
+ as.id_groups = 0; \
+ as.scheduler = 0; \
+ as.containers = 0;
+#endif // _di_fl_execute_as_t_
+
#ifdef __cplusplus
} // extern "C"
#endif
* Licenses: lgplv2.1
*
* Provides execute processing functionality.
+ *
+ * This utilizes setgroups() to set multiple supplementary groups.
+ * It appears that POSIX failed to provide this (despite providing getgroups()).
+ * There may be compatibility issues as a result of supporting setgroups().
*/
#ifndef _FL_execute_h
#define _FL_execute_h
// libc includes
+#include <grp.h>
+#include <sched.h>
+//#include <sys/capability.h> // @todo
// fll-0 includes
#include <level_0/type.h>
case F_bound_not:
*string = FL_status_string_bound_not;
break;
+ case F_capability:
+ *string = FL_status_string_capability;
+ break;
+ case F_capability_not:
+ *string = FL_status_string_capability_not;
+ break;
case F_child:
*string = FL_status_string_child;
break;
case F_connected_not:
*string = FL_status_string_connected_not;
break;
+ case F_container:
+ *string = FL_status_string_container;
+ break;
+ case F_container_not:
+ *string = FL_status_string_container_not;
+ break;
case F_critical:
*string = FL_status_string_critical;
break;
case F_found_not:
*string = FL_status_string_found_not;
break;
+ case F_group:
+ *string = FL_status_string_group;
+ break;
+ case F_group_not:
+ *string = FL_status_string_group_not;
+ break;
+ case F_ignore:
+ *string = FL_status_string_ignore;
+ break;
+ case F_ignore_not:
+ *string = FL_status_string_ignore_not;
+ break;
case F_input:
*string = FL_status_string_input;
break;
case F_name_not:
*string = FL_status_string_name_not;
break;
+ case F_nice:
+ *string = FL_status_string_nice;
+ break;
+ case F_nice_not:
+ *string = FL_status_string_nice_not;
+ break;
case F_optional:
*string = FL_status_string_optional;
break;
case F_search_not:
*string = FL_status_string_search_not;
break;
+ case F_schedule:
+ *string = FL_status_string_schedule;
+ break;
+ case F_schedule_not:
+ *string = FL_status_string_schedule_not;
+ break;
case F_signal:
*string = FL_status_string_signal;
break;
case F_supported_not:
*string = FL_status_string_supported_not;
break;
+ case F_user:
+ *string = FL_status_string_user;
+ break;
+ case F_user_not:
+ *string = FL_status_string_user_not;
+ break;
case F_utf:
*string = FL_status_string_utf;
break;
case F_warn_not:
*string = FL_status_string_warn_not;
break;
+ case F_world:
+ *string = FL_status_string_world;
+ break;
+ case F_world_not:
+ *string = FL_status_string_world_not;
+ break;
case F_write:
*string = FL_status_string_write;
break;
#define FL_status_string_block_not "F_block_not"
#define FL_status_string_bound "F_bound"
#define FL_status_string_bound_not "F_bound_not"
+ #define FL_status_string_capability "F_capability"
+ #define FL_status_string_capability_not "F_capability_not"
#define FL_status_string_child "F_child"
#define FL_status_string_child_not "F_child_not"
#define FL_status_string_complete "F_complete"
#define FL_status_string_complete_not "F_complete_not"
#define FL_status_string_connected "F_connected"
#define FL_status_string_connected_not "F_connected_not"
+ #define FL_status_string_container "F_container"
+ #define FL_status_string_container_not "F_container_not"
#define FL_status_string_critical "F_critical"
#define FL_status_string_critical_not "F_critical_not"
#define FL_status_string_deadlock "F_deadlock"
#define FL_status_string_fork_not "F_fork_not"
#define FL_status_string_found "F_found"
#define FL_status_string_found_not "F_found_not"
+ #define FL_status_string_group "F_group"
+ #define FL_status_string_group_not "F_group_not"
+ #define FL_status_string_ignore "F_ignore"
+ #define FL_status_string_ignore_not "F_ignore_not"
#define FL_status_string_input "F_input"
#define FL_status_string_input_not "F_input_not"
#define FL_status_string_input_output "F_input_output"
#define FL_status_string_mount_not "F_mount_not"
#define FL_status_string_name "F_name"
#define FL_status_string_name_not "F_name_not"
+ #define FL_status_string_nice "F_nice"
+ #define FL_status_string_nice_not "F_nice_not"
#define FL_status_string_optional "F_optional"
#define FL_status_string_optional_not "F_optional_not"
#define FL_status_string_output "F_output"
#define FL_status_string_resource_not "F_resource_not"
#define FL_status_string_search "F_search"
#define FL_status_string_search_not "F_search_not"
+ #define FL_status_string_schedule "F_schedule"
+ #define FL_status_string_schedule_not "F_schedule_not"
#define FL_status_string_signal "F_signal"
#define FL_status_string_signal_not "F_signal_not"
#define FL_status_string_space "F_space"
#define FL_status_string_syntax_not "F_syntax_not"
#define FL_status_string_supported "F_supported"
#define FL_status_string_supported_not "F_supported_not"
+ #define FL_status_string_user "F_user"
+ #define FL_status_string_user_not "F_user_not"
#define FL_status_string_utf "F_utf"
#define FL_status_string_utf_not "F_utf_not"
#define FL_status_string_valid "F_valid"
#define FL_status_string_wait_not "F_wait_not"
#define FL_status_string_warn "F_warn"
#define FL_status_string_warn_not "F_warn_not"
+ #define FL_status_string_world "F_world"
+ #define FL_status_string_world_not "F_world_not"
#define FL_status_string_write "F_write"
#define FL_status_string_write_not "F_write_not"
#define FL_status_string_write_only "F_write_only"
#define FL_status_string_block_not_length 11
#define FL_status_string_bound_length 7
#define FL_status_string_bound_not_length 11
+ #define FL_status_string_capability_length 12
+ #define FL_status_string_capability_not_length 16
#define FL_status_string_child_length 7
#define FL_status_string_child_not_length 11
#define FL_status_string_complete_length 10
#define FL_status_string_complete_not_length 14
#define FL_status_string_connected_length 11
#define FL_status_string_connected_not_length 15
+ #define FL_status_string_container_length 11
+ #define FL_status_string_container_not_length 15
#define FL_status_string_critical_length 10
#define FL_status_string_critical_not_length 14
#define FL_status_string_deadlock_length 10
#define FL_status_string_fork_not_length 10
#define FL_status_string_found_length 7
#define FL_status_string_found_not_length 11
+ #define FL_status_string_group_length 7
+ #define FL_status_string_group_not_length 11
+ #define FL_status_string_ignore_length 8
+ #define FL_status_string_ignore_not_length 12
#define FL_status_string_input_length 7
#define FL_status_string_input_not_length 11
#define FL_status_string_input_output_length 14
#define FL_status_string_mount_not_length 11
#define FL_status_string_name_length 6
#define FL_status_string_name_not_length 10
+ #define FL_status_string_nice_length 6
+ #define FL_status_string_nice_not_length 10
#define FL_status_string_optional_length 10
#define FL_status_string_optional_not_length 14
#define FL_status_string_output_length 8
#define FL_status_string_resource_not_length 14
#define FL_status_string_search_length 8
#define FL_status_string_search_not_length 12
+ #define FL_status_string_schedule_length 10
+ #define FL_status_string_schedule_not_length 14
#define FL_status_string_signal_length 8
#define FL_status_string_signal_not_length 12
#define FL_status_string_space_length 7
#define FL_status_string_supported_not_length 15
#define FL_status_string_syntax_length 8
#define FL_status_string_syntax_not_length 12
+ #define FL_status_string_user_length 6
+ #define FL_status_string_user_not_length 10
#define FL_status_string_utf_length 5
#define FL_status_string_utf_not_length 9
#define FL_status_string_valid_length 7
#define FL_status_string_wait_not_length 10
#define FL_status_string_warn_length 6
#define FL_status_string_warn_not_length 10
+ #define FL_status_string_world_length 7
+ #define FL_status_string_world_not_length 11
#define FL_status_string_write_length 7
#define FL_status_string_write_not_length 11
#define FL_status_string_write_only_length 12
#endif // _di_fll_execute_into_
#ifndef _di_fll_execute_program_
- f_return_status fll_execute_program(const f_string_t program, const f_string_statics_t arguments, fl_execute_parameter_t * const parameter, int *result) {
+ f_return_status fll_execute_program(const f_string_t program, const f_string_statics_t arguments, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result) {
#ifndef _di_level_2_parameter_checking_
if (!program && !arguments.used) return F_status_set_error(F_parameter);
if (!result) return F_status_set_error(F_parameter);
if (F_status_is_error(status)) return status;
if (parameter && parameter->data) {
- return private_fll_execute_fork_data(program_path, fixed_arguments, parameter, result);
+ return private_fll_execute_fork_data(program_path, fixed_arguments, parameter, as, result);
}
- return private_fll_execute_fork(program_path, fixed_arguments, parameter, result);
+ return private_fll_execute_fork(program_path, fixed_arguments, parameter, as, result);
}
if (parameter && parameter->data) {
- return private_fll_execute_fork_data(program, fixed_arguments, parameter, result);
+ return private_fll_execute_fork_data(program, fixed_arguments, parameter, as, result);
}
- return private_fll_execute_fork(program, fixed_arguments, parameter, result);
+ return private_fll_execute_fork(program, fixed_arguments, parameter, as, result);
}
#endif // _di_fll_execute_program_
#include <signal.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
* Otherwise, this returns F_child and assigns the child's return code to result for the child process.
* The caller is expected to handle the appropriate exit procedures and memory deallocation for the child process when F_child is returned.
*
+ * This returns F_capability, F_group, and F_user only for the child process and must be treated the same as F_child for the purposes of understanding what the current process is.
+ * These are essentialy F_child with explicit error codes that are returned instead of performing the desired execution.
+ *
* @param program
* The name or path of the program.
* The string pointer may be set to 0, to designate that the first index in arguments is assumed to be the program.
* data:
* A pointer to a string to pipe as standard input to the child process.
* The parent will block until the standard input is fully read or the child process exits.
+ * @param as
+ * (optional) This and most of its fields are optional and are disabled when set to 0.
* @param result
* The code returned after finishing execution of program.
*
* @return
* F_none on success.
- * F_child on success but this is the child thread.
+ * F_capability (with error bit) on failure to set capabilities in the child (only the child process returns this).
+ * F_child (with error bit) on any failure without an explicit failure code (like F_group) before calling execute but this is the child thread.
* F_failure (with error bit) on execution failure.
* F_fork (with error bit) on fork failure.
+ * F_group (with error bit) on failure to set GID in the child (only the child process returns this).
+ * F_nice (with error bit) on failure to set process niceness in the child (only the child process returns this).
* F_pipe (with error bit) on pipe failure.
+ * F_schedule (with error bit) on failure to set scheduler in the child (only the child process returns this).
+ * F_user (with error bit) on failure to set UID in the child (only the child process returns this).
*
* Errors (with error bit) from: f_environment_get().
* Errors (with error bit) from: f_file_exists().
* Errors (with error bit) from: fl_string_dynamic_delete().
* Errors (with error bit) from: fl_string_dynamic_terminate().
*
+ * @see cap_set_proc()
* @see close()
* @see clearenv()
* @see dup2()
* @see execvp()
* @see exit()
* @see fork()
+ * @see getpid()
* @see memcpy()
+ * @see nice()
* @see pipe()
+ * @see sched_setscheduler()
+ * @see setgid()
+ * @see setgroups()
+ * @see setuid()
* @see strnlen()
* @see waitpid()
*
* @see fl_string_dynamic_terminate()
*/
#ifndef _di_fll_execute_program_
- extern f_return_status fll_execute_program(const f_string_t program, const f_string_statics_t arguments, fl_execute_parameter_t * const parameter, int *result);
+ extern f_return_status fll_execute_program(const f_string_t program, const f_string_statics_t arguments, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result);
#endif // _di_fll_execute_program_
#ifdef __cplusplus
#endif // !defined(_di_fll_execute_arguments_add_parameter_) || !defined(_di_fll_execute_arguments_add_parameter_set_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_set_)
#if !defined(_di_fll_execute_program_)
- f_return_status private_fll_execute_fork(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, int *result) {
+ f_return_status private_fll_execute_as(const fl_execute_as_t as, fl_execute_parameter_t * const parameter, int *result) {
+
+ if (as.nice) {
+ errno = 0;
+
+ if (nice(*as.nice) == -1 && errno == -1) {
+ *result = -1;
+
+ if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+ exit(*result);
+ }
+
+ return F_status_set_error(F_nice);
+ }
+ }
+
+ if (as.scheduler) {
+ const int process_id = getpid();
+
+ errno = 0;
+
+ if (sched_setscheduler(process_id, as.scheduler->policy, as.scheduler->parameter) == -1) {
+ *result = -1;
+
+ if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+ exit(*result);
+ }
+
+ return F_status_set_error(F_schedule);
+ }
+ }
+
+ /* @todo library dependencies, if this is not in libc, then this may not be supported. more investigation is needed.
+ if (as.capability) {
+ if (cap_set_proc(*as.capability) == -1) {
+ *result = -1;
+
+ if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+ exit(*result);
+ }
+
+ return F_status_set_error(F_capability);
+ }
+ }
+ */
+
+ if (as.ids_group) {
+ if (setgroups(as.ids_group->size, as.ids_group->groups) == -1) {
+ *result = -1;
+
+ if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+ exit(*result);
+ }
+
+ return F_status_set_error(F_group);
+ }
+ }
+
+ if (as.id_group) {
+ if (setgid(*as.id_group) == -1) {
+ *result = -1;
+
+ if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+ exit(*result);
+ }
+
+ return F_status_set_error(F_group);
+ }
+ }
+
+ if (as.id_user) {
+ if (setuid(*as.id_user) == -1) {
+ *result = -1;
+
+ if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+ exit(*result);
+ }
+
+ return F_status_set_error(F_user);
+ }
+ }
+
+ return F_none;
+ }
+#endif // !defined(_di_fll_execute_program_)
+
+#if !defined(_di_fll_execute_program_)
+ f_return_status private_fll_execute_fork(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result) {
const pid_t process_id = fork();
} // for
}
+ if (as) {
+ const f_status_t status = private_fll_execute_as(*as, parameter, result);
+
+ if (F_status_is_error(status)) {
+ return status;
+ }
+ }
+
const int code = parameter && (parameter->option & fl_execute_parameter_option_path) ? execv(program, fixed_arguments) : execvp(program, fixed_arguments);
if (result) {
#endif // !defined(_di_fll_execute_program_)
#if !defined(_di_fll_execute_program_)
- f_return_status private_fll_execute_fork_data(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, int *result) {
+ f_return_status private_fll_execute_fork_data(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result) {
int descriptors[2] = { -1, -1 };
dup2(descriptors[0], f_type_descriptor_input);
+ if (as) {
+ const f_status_t status = private_fll_execute_as(*as, parameter, result);
+
+ if (F_status_is_error(status)) {
+ return status;
+ }
+ }
+
const int code = parameter && parameter->option & fl_execute_parameter_option_path ? execv(program, fixed_arguments) : execvp(program, fixed_arguments);
// close the write pipe for the child when done.
#endif // !defined(_di_fll_execute_arguments_add_parameter_) || !defined(_di_fll_execute_arguments_add_parameter_set_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_set_)
/**
+ * Private function for perform the execute as operations.
+ *
+ * This should be executed in the child thread.
+ *
+ * @param as
+ * The "as" operations to perform.
+ * @param parameter
+ * (optional) This and most of its fields are optional and are disabled when set to 0.
+ * This function only cares about "option" on this structure.
+ * option:
+ * A bitwise set of options, such as: fl_execute_parameter_option_exit, and fl_execute_parameter_option_path.
+ * @param result
+ * The code returned after finishing execution of program.
+ *
+ * @return
+ * F_none on success.
+ * F_capability (with error bit) on failure to set capabilities.
+ * F_group (with error bit) on failure to set GID.
+ * F_nice (with error bit) on failure to set process niceness.
+ * F_schedule (with error bit) on failure to set scheduler.
+ * F_user (with error bit) on failure to set UID.
+ *
+ * @see cap_set_proc()
+ * @see exit()
+ * @see getpid()
+ * @see nice()
+ * @see sched_setscheduler()
+ * @see setgid()
+ * @see setgroups()
+ * @see setuid()
+ *
+ * @see fll_execute_program()
+ */
+#if !defined(_di_fll_execute_program_)
+ extern f_return_status private_fll_execute_as(const fl_execute_as_t as, fl_execute_parameter_t * const parameter, int *result) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fll_execute_program_)
+
+/**
* Private function for performing the fork and execute operation.
*
* This implementation ignores parameter.data.
* data:
* A pointer to a string to pipe as standard input to the child process.
* The parent will block until the standard input is fully read or the child process exits.
+ * @param as
+ * (optional) This and most of its fields are optional and are disabled when set to 0.
* @param result
* The code returned after finishing execution of program.
*
* @return
* F_none on success.
+ * F_capability (with error bit) on failure to set capabilities in the child (only the child process returns this).
* F_child on success but this is the child thread.
* F_failure (with error bit) on execution failure.
* F_fork (with error bit) on fork failure.
+ * F_group (with error bit) on failure to set GID in the child (only the child process returns this).
+ * F_nice (with error bit) on failure to set process niceness in the child (only the child process returns this).
+ * F_schedule (with error bit) on failure to set scheduler in the child (only the child process returns this).
+ * F_user (with error bit) on failure to set UID in the child (only the child process returns this).
*
* @see clearenv()
* @see execv()
* @see fll_execute_program()
*/
#if !defined(_di_fll_execute_program_)
- extern f_return_status private_fll_execute_fork(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, int *result) f_gcc_attribute_visibility_internal;
+ extern f_return_status private_fll_execute_fork(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result) f_gcc_attribute_visibility_internal;
#endif // !defined(_di_fll_execute_program_)
/**
* data:
* A pointer to a string to pipe as standard input to the child process.
* The parent will block until the standard input is fully read or the child process exits.
+ * @param as
+ * (optional) This and most of its fields are optional and are disabled when set to 0.
* @param result
* The code returned after finishing execution of program.
*
* @return
* F_none on success.
+ * F_capability (with error bit) on failure to set capabilities in the child (only the child process returns this).
* F_child on success but this is the child thread.
* F_failure (with error bit) on execution failure.
* F_fork (with error bit) on fork failure.
+ * F_group (with error bit) on failure to set GID in the child (only the child process returns this).
+ * F_nice (with error bit) on failure to set process niceness in the child (only the child process returns this).
* F_pipe (with error bit) on pipe failure.
+ * F_schedule (with error bit) on failure to set scheduler in the child (only the child process returns this).
+ * F_user (with error bit) on failure to set UID in the child (only the child process returns this).
*
* @see clearenv()
* @see close()
* @see fll_execute_program()
*/
#if !defined(_di_fll_execute_program_)
- extern f_return_status private_fll_execute_fork_data(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, int *result) f_gcc_attribute_visibility_internal;
+ extern f_return_status private_fll_execute_fork_data(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result) f_gcc_attribute_visibility_internal;
#endif // !defined(_di_fll_execute_program_)
/**
return F_none;
}
- if (fl_string_compare(string, FL_status_string_complete, length, FL_status_string_complete_length) == F_equal_to) {
- *code = F_complete;
+ if (fl_string_compare(string, FL_status_string_capability, length, FL_status_string_capability_length) == F_equal_to) {
+ *code = F_capability;
return F_none;
}
- if (fl_string_compare(string, FL_status_string_complete_not, length, FL_status_string_complete_not_length) == F_equal_to) {
- *code = F_complete_not;
+ if (fl_string_compare(string, FL_status_string_capability_not, length, FL_status_string_capability_not_length) == F_equal_to) {
+ *code = F_capability_not;
return F_none;
}
return F_none;
}
+ if (fl_string_compare(string, FL_status_string_complete, length, FL_status_string_complete_length) == F_equal_to) {
+ *code = F_complete;
+ return F_none;
+ }
+
+ if (fl_string_compare(string, FL_status_string_complete_not, length, FL_status_string_complete_not_length) == F_equal_to) {
+ *code = F_complete_not;
+ return F_none;
+ }
+
if (fl_string_compare(string, FL_status_string_connected, length, FL_status_string_connected_length) == F_equal_to) {
*code = F_connected;
return F_none;
return F_none;
}
+ if (fl_string_compare(string, FL_status_string_container, length, FL_status_string_container_length) == F_equal_to) {
+ *code = F_container;
+ return F_none;
+ }
+
+ if (fl_string_compare(string, FL_status_string_container_not, length, FL_status_string_container_not_length) == F_equal_to) {
+ *code = F_container_not;
+ return F_none;
+ }
+
if (fl_string_compare(string, FL_status_string_critical, length, FL_status_string_critical_length) == F_equal_to) {
*code = F_critical;
return F_none;
return F_none;
}
+ if (fl_string_compare(string, FL_status_string_group, length, FL_status_string_group_length) == F_equal_to) {
+ *code = F_group;
+ return F_none;
+ }
+
+ if (fl_string_compare(string, FL_status_string_group_not, length, FL_status_string_group_not_length) == F_equal_to) {
+ *code = F_group_not;
+ return F_none;
+ }
+
+ if (fl_string_compare(string, FL_status_string_ignore, length, FL_status_string_ignore_length) == F_equal_to) {
+ *code = F_ignore;
+ return F_none;
+ }
+
+ if (fl_string_compare(string, FL_status_string_ignore_not, length, FL_status_string_ignore_not_length) == F_equal_to) {
+ *code = F_ignore_not;
+ return F_none;
+ }
+
if (fl_string_compare(string, FL_status_string_input, length, FL_status_string_input_length) == F_equal_to) {
*code = F_input;
return F_none;
return F_none;
}
+ if (fl_string_compare(string, FL_status_string_nice, length, FL_status_string_nice_length) == F_equal_to) {
+ *code = F_nice;
+ return F_none;
+ }
+
+ if (fl_string_compare(string, FL_status_string_nice_not, length, FL_status_string_nice_not_length) == F_equal_to) {
+ *code = F_nice_not;
+ return F_none;
+ }
+
if (fl_string_compare(string, FL_status_string_optional, length, FL_status_string_optional_length) == F_equal_to) {
*code = F_optional;
return F_none;
return F_none;
}
+ if (fl_string_compare(string, FL_status_string_schedule, length, FL_status_string_schedule_length) == F_equal_to) {
+ *code = F_schedule;
+ return F_none;
+ }
+
+ if (fl_string_compare(string, FL_status_string_schedule_not, length, FL_status_string_schedule_not_length) == F_equal_to) {
+ *code = F_schedule_not;
+ return F_none;
+ }
+
if (fl_string_compare(string, FL_status_string_signal, length, FL_status_string_signal_length) == F_equal_to) {
*code = F_signal;
return F_none;
return F_none;
}
+ if (fl_string_compare(string, FL_status_string_user, length, FL_status_string_user_length) == F_equal_to) {
+ *code = F_user;
+ return F_none;
+ }
+
+ if (fl_string_compare(string, FL_status_string_user_not, length, FL_status_string_user_not_length) == F_equal_to) {
+ *code = F_user_not;
+ return F_none;
+ }
+
if (fl_string_compare(string, FL_status_string_utf, length, FL_status_string_utf_length) == F_equal_to) {
*code = F_utf;
return F_none;
return F_none;
}
+ if (fl_string_compare(string, FL_status_string_world, length, FL_status_string_world_length) == F_equal_to) {
+ *code = F_world;
+ return F_none;
+ }
+
+ if (fl_string_compare(string, FL_status_string_world_not, length, FL_status_string_world_not_length) == F_equal_to) {
+ *code = F_world_not;
+ return F_none;
+ }
+
if (fl_string_compare(string, FL_status_string_write, length, FL_status_string_write_length) == F_equal_to) {
*code = F_write;
return F_none;
#ifndef _di_controller_rule_execute_
f_return_status controller_rule_execute(const controller_cache_t cache, const f_array_length_t index, const uint8_t type, controller_data_t *data, controller_setting_t *setting) {
f_status_t status = F_none;
+ f_status_t success = F_false;
f_array_length_t i = 0;
f_array_length_t j = 0;
}
status = controller_rule_execute_foreground(item->type, *action, 0, action->parameters, 0, ¶meter, data);
- if (F_status_is_error(status)) break;
+
+ if (F_status_is_error(status)) {
+ action->status = F_status_set_error(F_failure);
+ break;
+ }
+
+ success = F_true;
}
else if (item->type == controller_rule_item_type_script) {
parameter.data = &action->parameters.array[0];
}
status = controller_rule_execute_foreground(item->type, *action, rule->script.used ? rule->script.string : controller_default_program_script, arguments_none, 0, ¶meter, data);
- if (F_status_is_error(status)) break;
+
+ if (F_status_is_error(status)) {
+ action->status = F_status_set_error(F_failure);
+ break;
+ }
+
+ success = F_true;
}
else if (item->type == controller_rule_item_type_service) {
parameter.option |= fl_execute_parameter_option_path;
}
- // @todo
- //status = controller_rule_execute_background(item->type, *action, 0, action->parameters, 0, ¶meter, data);
- //if (F_status_is_error(status)) break;
+ status = controller_rule_execute_pid_with(item->type, *action, 0, action->parameters, 0, ¶meter, data);
+
+ if (F_status_is_error(status)) {
+ action->status = F_status_set_error(F_failure);
+ break;
+ }
+
+ success = F_true;
}
else {
- status = F_none;
- // unknown, just ignore for now. (@todo print a warning when in debug mode.)
+ if (data->warning.verbosity == f_console_verbosity_debug) {
+ fprintf(data->warning.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(data->warning.to.stream, "%s%sAction type is unknown, ignoring.%s%c", data->warning.context.before->string, data->warning.prefix ? data->warning.prefix : f_string_empty_s, data->warning.context.after->string, f_string_eol_s[0]);
+
+ controller_rule_error_print(data->warning, cache, F_true);
+ }
+
+ action->status = F_ignore;
+
+ if (success != F_true) {
+ success = F_ignore;
+ }
+
continue;
}
fl_string_maps_delete(&environment);
- return status;
+ if (F_status_is_error(status) || success == F_false) {
+ rule->status = F_status_set_error(F_failure);
+ }
+ else if (success == F_ignore || success == F_busy) {
+ rule->status = success;
+ }
+ else {
+ rule->status = F_none;
+ }
+
+ return rule->status;
}
#endif // _di_controller_rule_execute_
+#ifndef _di_controller_rule_execute_pid_with_
+ f_return_status controller_rule_execute_pid_with(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, controller_data_t *data) {
+ int result = 0;
+
+ // @todo check to see if pid file exists.
+
+ // @todo this needs to support/use an option to designate that the process automatically forks in the background.
+ // in which case fll_execute_program() is called.
+ // otherwise this needs to call an asynchronous execute process.
+ // until then, this controller_rule_execute_pid_with() function is not correct and only represents a process that forks to the background.
+ f_status_t status = fll_execute_program(program, arguments, parameter, 0, &result);
+
+ if (status == F_child) {
+ data->child = result;
+
+ return F_child;
+ }
+
+ if (result != 0) {
+ status = F_status_set_error(F_failure);
+ }
+
+ if (F_status_is_error(status)) {
+ if (F_status_set_fine(status) == F_failure) {
+ controller_rule_error_print_execute(data->error, type == controller_rule_item_type_script, program, result);
+ }
+ else if (F_status_set_fine(status) == F_file_found_not) {
+ controller_rule_error_print_execute_not_found(data->error, F_false, program);
+ }
+ else {
+ fll_error_print(data->error, F_status_set_fine(status), "fll_execute_program_environment", F_true);
+ }
+
+ data->child = 0;
+
+ return status;
+ }
+
+ // @todo wait for pid file or timeout.
+
+ data->child = 0;
+
+ return status;
+ }
+#endif // _di_controller_rule_execute_pid_with_
+
#ifndef _di_controller_rule_execute_foreground_
f_return_status controller_rule_execute_foreground(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, controller_data_t *data) {
int result = 0;
- f_status_t status = fll_execute_program(program, arguments, parameter, &result);
+ f_status_t status = fll_execute_program(program, arguments, parameter, 0, &result);
if (status == F_child) {
data->child = result;
#endif // _di_controller_rule_execute_
/**
+ * Perform an execution of the given rule in the foreground or background and creating a PID file.
+ *
+ * When this is synchronous, this will wait for the PID file to be generated before continuing.
+ * When this is asynchronous, this will continue on adding the rule id and action to the asynchronous list.
+ *
+ * @param type
+ * The item type code.
+ * @param action
+ * The action to perform based on the action type codes.
+ *
+ * Only subset of the action type codes are supported:
+ * - controller_rule_action_type_kill
+ * - controller_rule_action_type_reload
+ * - controller_rule_action_type_restart
+ * - controller_rule_action_type_start
+ * - controller_rule_action_type_stop
+ * @param program
+ * The program to use (such as "bash").
+ * @param arguments
+ * The arguments to pass to the program.
+ * @param options
+ * The controller execute options (and not fl_execute_parameter_t.option).
+ * This is for designating asynchronous and other controller specific execution options.
+ * @todo this is not yet implemented.
+ * @param parameter
+ * The execute parameter settings.
+ * @param data
+ * The program data.
+ *
+ * @return
+ * F_none on success.
+ * F_busy on successful execute in asynchronous mode (executed process may or may not fail later on).
+ * F_child on child process exiting.
+ * F_signal on (exit) signal received.
+ *
+ * Errors (with error bit) from: fll_execute_program().
+ *
+ * @see fll_execute_program()
+ */
+#ifndef _di_controller_rule_execute_pid_with_
+ extern f_return_status controller_rule_execute_pid_with(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, controller_data_t *data) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_rule_execute_pid_with_
+
+/**
* Perform an execution of the given rule in the foreground.
*
* @param type
* - controller_rule_action_type_start
* - controller_rule_action_type_stop
* @param program
- * The script program to use (such as "bash").
+ * The program to use (such as "bash").
* @param arguments
- * The arguments to pass to the script.
+ * The arguments to pass to the program.
* @param options
* The controller execute options (and not fl_execute_parameter_t.option).
* This is for designating asynchronous and other controller specific execution options.
fl_execute_parameter_t parameter = fl_macro_execute_parameter_t_initialize(fl_execute_parameter_option_path, &data_build.environment, &signals, 0);
- *status = fll_execute_program(path.string, arguments, ¶meter, &return_code);
+ *status = fll_execute_program(path.string, arguments, ¶meter, 0, &return_code);
fl_string_dynamics_delete(&arguments);
fl_execute_parameter_t parameter = fl_macro_execute_parameter_t_initialize(0, &environment, &signals, 0);
- *status = fll_execute_program(program.string, arguments, ¶meter, &return_code);
+ *status = fll_execute_program(program.string, arguments, ¶meter, 0, &return_code);
if (fake_signal_received(data)) {
*status = F_status_set_error(F_signal);
fl_execute_parameter_t parameter = fl_macro_execute_parameter_t_initialize(as_shell ? 0 : fl_execute_parameter_option_path, &data_make->environment, &signals, 0);
- status = fll_execute_program(program.string, arguments, ¶meter, &return_code);
+ status = fll_execute_program(program.string, arguments, ¶meter, 0, &return_code);
if (status == F_status_set_error(F_signal)) {
return status;
parameters.array[4].used = 9;
parameters.array[5].used = 6;
- status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, &return_code);
+ status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
parameters.array[4].used = 9;
parameters.array[5].used = 6;
- status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, &return_code);
+ status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
parameters.array[2].used = 9;
parameters.array[3].used = 6;
- status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, &return_code);
+ status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
fprintf(f_type_debug, "\n");
}
- status = fll_execute_program((f_string_t) current_tool, arguments, 0, &return_code);
+ status = fll_execute_program((f_string_t) current_tool, arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
fprintf(f_type_debug, "\n");
}
- status = fll_execute_program(current_tool, arguments, 0, &return_code);
+ status = fll_execute_program(current_tool, arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
}
tool = firewall_program_iptables;
- status = fll_execute_program((f_string_t) firewall_tool_iptables, arguments, 0, &return_code);
+ status = fll_execute_program((f_string_t) firewall_tool_iptables, arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
}
tool = firewall_program_ip6tables;
- status = fll_execute_program((f_string_t) firewall_tool_ip6tables, arguments, 0, &return_code);
+ status = fll_execute_program((f_string_t) firewall_tool_ip6tables, arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
fprintf(f_type_debug, "\n");
}
- status = fll_execute_program(tools[i], arguments, 0, &return_code);
+ status = fll_execute_program(tools[i], arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
fprintf(f_type_debug, "\n");
}
- status = fll_execute_program(tools[i], arguments, 0, &return_code);
+ status = fll_execute_program(tools[i], arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
fprintf(f_type_debug, "\n");
}
- status = fll_execute_program(tools[j], arguments, 0, &return_code);
+ status = fll_execute_program(tools[j], arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {