From: Kevin Day Date: Mon, 21 Dec 2020 01:04:56 +0000 (-0600) Subject: Progress: controller program and execute "as" additions. X-Git-Tag: 0.5.2~5 X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=09d4a28ebc771082be1ae306353837d4ae43b8aa;p=fll Progress: controller program and execute "as" additions. The execute "as" additions are very much incomplete as of this commit. --- diff --git a/level_0/f_status/c/status.h b/level_0/f_status/c/status.h index 055413d..7a9e7c6 100644 --- a/level_0/f_status/c/status.h +++ b/level_0/f_status/c/status.h @@ -153,12 +153,16 @@ extern "C" { 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, @@ -185,6 +189,10 @@ extern "C" { 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, @@ -208,6 +216,8 @@ extern "C" { F_mount_not, F_name, F_name_not, + F_nice, + F_nice_not, F_optional, F_optional_not, F_output, @@ -239,6 +249,8 @@ extern "C" { F_resource_not, F_search, F_search_not, + F_schedule, + F_schedule_not, F_signal, F_signal_not, F_space, @@ -253,6 +265,8 @@ extern "C" { F_supported_not, F_syntax, F_syntax_not, + F_user, + F_user_not, F_utf, F_utf_not, F_valid, @@ -263,6 +277,8 @@ extern "C" { F_wait_not, F_warn, F_warn_not, + F_world, + F_world_not, F_write, F_write_not, F_write_only, diff --git a/level_1/fl_execute/c/execute-common.h b/level_1/fl_execute/c/execute-common.h index 3efb1b7..3a5610c 100644 --- a/level_1/fl_execute/c/execute-common.h +++ b/level_1/fl_execute/c/execute-common.h @@ -51,6 +51,90 @@ extern "C" { 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 diff --git a/level_1/fl_execute/c/execute.h b/level_1/fl_execute/c/execute.h index ed970c0..cd5e08e 100644 --- a/level_1/fl_execute/c/execute.h +++ b/level_1/fl_execute/c/execute.h @@ -6,11 +6,18 @@ * 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 +#include +//#include // @todo // fll-0 includes #include diff --git a/level_1/fl_status/c/status.c b/level_1/fl_status/c/status.c index 3eb1a23..14bb0b3 100644 --- a/level_1/fl_status/c/status.c +++ b/level_1/fl_status/c/status.c @@ -242,6 +242,12 @@ extern "C" { 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; @@ -260,6 +266,12 @@ extern "C" { 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; @@ -338,6 +350,18 @@ extern "C" { 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; @@ -407,6 +431,12 @@ extern "C" { 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; @@ -500,6 +530,12 @@ extern "C" { 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; @@ -548,6 +584,12 @@ extern "C" { 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; @@ -572,6 +614,12 @@ extern "C" { 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; diff --git a/level_1/fl_status/c/status.h b/level_1/fl_status/c/status.h index 0f09466..4fb4c29 100644 --- a/level_1/fl_status/c/status.h +++ b/level_1/fl_status/c/status.h @@ -172,12 +172,16 @@ extern "C" { #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" @@ -204,6 +208,10 @@ extern "C" { #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" @@ -227,6 +235,8 @@ extern "C" { #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" @@ -258,6 +268,8 @@ extern "C" { #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" @@ -272,6 +284,8 @@ extern "C" { #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" @@ -282,6 +296,8 @@ extern "C" { #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" @@ -295,12 +311,16 @@ extern "C" { #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 @@ -327,6 +347,10 @@ extern "C" { #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 @@ -350,6 +374,8 @@ extern "C" { #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 @@ -381,6 +407,8 @@ extern "C" { #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 @@ -395,6 +423,8 @@ extern "C" { #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 @@ -405,6 +435,8 @@ extern "C" { #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 diff --git a/level_2/fll_execute/c/execute.c b/level_2/fll_execute/c/execute.c index 38145ed..79ddaac 100644 --- a/level_2/fll_execute/c/execute.c +++ b/level_2/fll_execute/c/execute.c @@ -168,7 +168,7 @@ extern "C" { #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); @@ -274,17 +274,17 @@ extern "C" { 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_ diff --git a/level_2/fll_execute/c/execute.h b/level_2/fll_execute/c/execute.h index 00c18bd..ce34a3d 100644 --- a/level_2/fll_execute/c/execute.h +++ b/level_2/fll_execute/c/execute.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -381,6 +382,9 @@ extern "C" { * 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. @@ -404,15 +408,22 @@ extern "C" { * 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(). @@ -423,6 +434,7 @@ extern "C" { * 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() @@ -430,8 +442,14 @@ extern "C" { * @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() * @@ -443,7 +461,7 @@ extern "C" { * @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 diff --git a/level_2/fll_execute/c/private-execute.c b/level_2/fll_execute/c/private-execute.c index eae5406..c3f8154 100644 --- a/level_2/fll_execute/c/private-execute.c +++ b/level_2/fll_execute/c/private-execute.c @@ -117,7 +117,94 @@ extern "C" { #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(); @@ -155,6 +242,14 @@ extern "C" { } // 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) { @@ -170,7 +265,7 @@ extern "C" { #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 }; @@ -235,6 +330,14 @@ extern "C" { 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. diff --git a/level_2/fll_execute/c/private-execute.h b/level_2/fll_execute/c/private-execute.h index 96c9b7a..6abd480 100644 --- a/level_2/fll_execute/c/private-execute.h +++ b/level_2/fll_execute/c/private-execute.h @@ -105,6 +105,44 @@ extern "C" { #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. @@ -131,14 +169,21 @@ extern "C" { * 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() @@ -151,7 +196,7 @@ extern "C" { * @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_) /** @@ -181,15 +226,22 @@ extern "C" { * 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() @@ -205,7 +257,7 @@ extern "C" { * @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_) /** diff --git a/level_2/fll_status/c/status.c b/level_2/fll_status/c/status.c index f2c459f..16aa35b 100644 --- a/level_2/fll_status/c/status.c +++ b/level_2/fll_status/c/status.c @@ -406,13 +406,13 @@ extern "C" { 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; } @@ -426,6 +426,16 @@ extern "C" { 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; @@ -436,6 +446,16 @@ extern "C" { 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; @@ -566,6 +586,26 @@ extern "C" { 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; @@ -681,6 +721,16 @@ extern "C" { 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; @@ -836,6 +886,16 @@ extern "C" { 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; @@ -906,6 +966,16 @@ extern "C" { 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; @@ -956,6 +1026,16 @@ extern "C" { 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; diff --git a/level_3/controller/c/private-rule.c b/level_3/controller/c/private-rule.c index 04bb3b3..23ac512 100644 --- a/level_3/controller/c/private-rule.c +++ b/level_3/controller/c/private-rule.c @@ -439,6 +439,7 @@ extern "C" { #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; @@ -487,7 +488,13 @@ extern "C" { } 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]; @@ -497,7 +504,13 @@ extern "C" { } 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) { @@ -505,14 +518,30 @@ extern "C" { 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; } @@ -524,15 +553,71 @@ extern "C" { 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; diff --git a/level_3/controller/c/private-rule.h b/level_3/controller/c/private-rule.h index 7f46215..81e4f6f 100644 --- a/level_3/controller/c/private-rule.h +++ b/level_3/controller/c/private-rule.h @@ -235,6 +235,50 @@ extern "C" { #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 @@ -249,9 +293,9 @@ extern "C" { * - 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. diff --git a/level_3/fake/c/private-build.c b/level_3/fake/c/private-build.c index 3939d2d..cd0d643 100644 --- a/level_3/fake/c/private-build.c +++ b/level_3/fake/c/private-build.c @@ -666,7 +666,7 @@ extern "C" { 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); diff --git a/level_3/fake/c/private-fake.c b/level_3/fake/c/private-fake.c index 806821b..5f6addd 100644 --- a/level_3/fake/c/private-fake.c +++ b/level_3/fake/c/private-fake.c @@ -43,7 +43,7 @@ extern "C" { 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); diff --git a/level_3/fake/c/private-make.c b/level_3/fake/c/private-make.c index c05e60d..6366946 100644 --- a/level_3/fake/c/private-make.c +++ b/level_3/fake/c/private-make.c @@ -3818,7 +3818,7 @@ extern "C" { 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; diff --git a/level_3/firewall/c/firewall.c b/level_3/firewall/c/firewall.c index e196987..844c7f0 100644 --- a/level_3/firewall/c/firewall.c +++ b/level_3/firewall/c/firewall.c @@ -251,7 +251,7 @@ extern "C" { 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) { @@ -284,7 +284,7 @@ extern "C" { 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) { @@ -313,7 +313,7 @@ extern "C" { 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) { diff --git a/level_3/firewall/c/private-firewall.c b/level_3/firewall/c/private-firewall.c index 97beec1..95e8438 100644 --- a/level_3/firewall/c/private-firewall.c +++ b/level_3/firewall/c/private-firewall.c @@ -752,7 +752,7 @@ f_return_status firewall_perform_commands(const firewall_local_data_t local, con 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) { @@ -826,7 +826,7 @@ f_return_status firewall_perform_commands(const firewall_local_data_t local, con 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) { @@ -1070,7 +1070,7 @@ f_return_status firewall_create_custom_chains(firewall_reserved_chains_t *reserv } 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) { @@ -1091,7 +1091,7 @@ f_return_status firewall_create_custom_chains(firewall_reserved_chains_t *reserv } 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) { @@ -1179,7 +1179,7 @@ f_return_status firewall_delete_chains(const firewall_data_t data) { 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) { @@ -1239,7 +1239,7 @@ f_return_status firewall_delete_chains(const firewall_data_t data) { 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) { @@ -1321,7 +1321,7 @@ f_return_status firewall_default_lock(const firewall_data_t data) { 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) {