From e6f8e514bdc34a1b1ee9a740eca65d2dca1426c5 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 13 Dec 2020 13:01:48 -0600 Subject: [PATCH] Security: A child process of an execv() family of functions may leak memory if script is called. When calling a bash script, the exit() call gets triggered but memory is never cleared. I am suspecting that this is happening because the script is run in the current process space whereas when calling a binary the process changes for the child. There are new status codes: F_child, F_child_not, F_parent, F_parent_not. The execute functions do not know what type of file is being executed. Return F_child for the child process and allow the caller to handle the exit behavior of the child process. This required significant changes to the Featureless Make, but the Featureless Make now always clears memory even for scripts. The firewall program also had to be changed. Instead of solving the potentially issues there, I decided to (for the time being) just mimic the previous behavior and call exit for the child process. The firewall program needs a rewrite anyway, so I am holding off on major changes. Refactor, cleanup, and improve the execute family of functions. This was my original commit plans but when I observed the memory leak the refactor and cleanup became this security related commit. As per cleanup plans: - Moved common code into shared private functions. - Change parameter checking granularity. - Allow for 0 length strings as arguments. - Avoid memory allocation inside execute functions. - Consistently check WIFEXITED() on child process result. - Update the documentation to follow more recent practices. --- level_0/f_status/c/status.h | 4 + level_1/fl_status/c/status.c | 12 + level_1/fl_status/c/status.h | 8 + level_2/fll_execute/c/execute.c | 364 ++---------------- level_2/fll_execute/c/execute.h | 238 +++++++----- level_2/fll_execute/c/private-execute.c | 170 +++++++-- level_2/fll_execute/c/private-execute.h | 126 ++++++- level_2/fll_status/c/status.c | 20 + level_3/fake/c/fake.c | 12 +- level_3/fake/c/fake.h | 2 + level_3/fake/c/main.c | 6 + level_3/fake/c/private-build.c | 212 ++++++----- level_3/fake/c/private-build.h | 78 ++-- level_3/fake/c/private-fake.c | 6 +- level_3/fake/c/private-make.c | 633 +++++++++++++++++--------------- level_3/fake/c/private-make.h | 29 +- level_3/firewall/c/private-firewall.c | 35 ++ 17 files changed, 1042 insertions(+), 913 deletions(-) diff --git a/level_0/f_status/c/status.h b/level_0/f_status/c/status.h index a49e09b..4320da8 100644 --- a/level_0/f_status/c/status.h +++ b/level_0/f_status/c/status.h @@ -153,6 +153,8 @@ extern "C" { F_block_not, F_bound, F_bound_not, + F_child, + F_child_not, F_complete, F_complete_not, F_connected, @@ -210,6 +212,8 @@ extern "C" { F_output_not, F_parameter, F_parameter_not, + F_parent, + F_parent_not, F_pipe, F_pipe_not, F_port, diff --git a/level_1/fl_status/c/status.c b/level_1/fl_status/c/status.c index 68ea346..195d670 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_child: + *string = FL_status_string_child; + break; + case F_child_not: + *string = FL_status_string_child_not; + break; case F_complete: *string = FL_status_string_complete; break; @@ -413,6 +419,12 @@ extern "C" { case F_parameter_not: *string = FL_status_string_parameter_not; break; + case F_parent: + *string = FL_status_string_parent; + break; + case F_parent_not: + *string = FL_status_string_parent_not; + break; case F_pipe: *string = FL_status_string_pipe; break; diff --git a/level_1/fl_status/c/status.h b/level_1/fl_status/c/status.h index 4985b75..0c64a48 100644 --- a/level_1/fl_status/c/status.h +++ b/level_1/fl_status/c/status.h @@ -172,6 +172,8 @@ 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_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" @@ -229,6 +231,8 @@ extern "C" { #define FL_status_string_output_not "F_output_not" #define FL_status_string_parameter "F_parameter" #define FL_status_string_parameter_not "F_parameter_not" + #define FL_status_string_parent "F_parent" + #define FL_status_string_parent_not "F_parent_not" #define FL_status_string_pipe "F_pipe" #define FL_status_string_pipe_not "F_pipe_not" #define FL_status_string_port "F_port" @@ -287,6 +291,8 @@ 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_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 @@ -344,6 +350,8 @@ extern "C" { #define FL_status_string_output_not_length 12 #define FL_status_string_parameter_length 11 #define FL_status_string_parameter_not_length 15 + #define FL_status_string_parent_length 8 + #define FL_status_string_parent_not_length 12 #define FL_status_string_pipe_length 6 #define FL_status_string_pipe_not_length 10 #define FL_status_string_port_length 6 diff --git a/level_2/fll_execute/c/execute.c b/level_2/fll_execute/c/execute.c index a60de33..c0b78ee 100644 --- a/level_2/fll_execute/c/execute.c +++ b/level_2/fll_execute/c/execute.c @@ -9,14 +9,9 @@ extern "C" { f_return_status fll_execute_arguments_add(const f_string_t source, const f_string_length_t length, f_string_dynamics_t *arguments) { #ifndef _di_level_2_parameter_checking_ if (!arguments) return F_status_set_error(F_parameter); - if (arguments->used > arguments->size) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ - if (!length) return F_data_not; - - f_status_t status = F_none; - - status = private_fll_execute_arguments_add(source, length, arguments); + const f_status_t status = private_fll_execute_arguments_add(source, length, arguments); if (F_status_is_error(status)) return status; return F_none; @@ -27,15 +22,9 @@ extern "C" { f_return_status fll_execute_arguments_add_parameter(const f_string_t prefix, const f_string_length_t prefix_length, const f_string_t name, const f_string_length_t name_length, const f_string_t value, const f_string_length_t value_length, f_string_dynamics_t *arguments) { #ifndef _di_level_2_parameter_checking_ if (!arguments) return F_status_set_error(F_parameter); - if (arguments->used > arguments->size) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ - if (!name_length) return F_data_not; - if (!value_length) return F_data_not; - - f_status_t status = F_none; - - status = private_fll_execute_arguments_add_parameter(prefix, prefix_length, name, name_length, value, value_length, arguments); + const f_status_t status = private_fll_execute_arguments_add_parameter(prefix, prefix_length, name, name_length, value, value_length, arguments); if (F_status_is_error(status)) return status; return F_none; @@ -46,16 +35,11 @@ extern "C" { f_return_status fll_execute_arguments_add_parameter_set(const f_string_t prefix[], const f_string_length_t prefix_length[], const f_string_t name[], const f_string_length_t name_length[], const f_string_t value[], const f_string_length_t value_length[], const f_array_length_t size, f_string_dynamics_t *arguments) { #ifndef _di_level_2_parameter_checking_ if (!arguments) return F_status_set_error(F_parameter); - if (arguments->used > arguments->size) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ - if (!size) return F_data_not; - f_status_t status = F_none; for (f_array_length_t i = 0; i < size; i++) { - if (!name_length[i]) continue; - if (!value_length[i]) continue; status = private_fll_execute_arguments_add_parameter(prefix[i], prefix_length[i], name[i], name_length[i], value[i], value_length[i], arguments); if (F_status_is_error(status)) return status; @@ -69,15 +53,11 @@ extern "C" { f_return_status fll_execute_arguments_add_set(const f_string_t source[], const f_string_length_t length[], const f_array_length_t size, f_string_dynamics_t *arguments) { #ifndef _di_level_2_parameter_checking_ if (!arguments) return F_status_set_error(F_parameter); - if (arguments->used > arguments->size) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ - if (!size) return F_data_not; - f_status_t status = F_none; for (f_array_length_t i = 0; i < size; i++) { - if (!length[i]) continue; status = private_fll_execute_arguments_add(source[i], length[i], arguments); if (F_status_is_error(status)) return status; @@ -90,16 +70,10 @@ extern "C" { #ifndef _di_fll_execute_arguments_dynamic_add_ f_return_status fll_execute_arguments_dynamic_add(const f_string_static_t source, f_string_dynamics_t *arguments) { #ifndef _di_level_2_parameter_checking_ - if (source.used > source.size) return F_status_set_error(F_parameter); if (!arguments) return F_status_set_error(F_parameter); - if (arguments->used > arguments->size) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ - if (!source.used) return F_data_not; - - f_status_t status = F_none; - - status = private_fll_execute_arguments_add(source.string, source.used, arguments); + const f_status_t status = private_fll_execute_arguments_add(source.string, source.used, arguments); if (F_status_is_error(status)) return status; return F_none; @@ -109,19 +83,10 @@ extern "C" { #ifndef _di_fll_execute_arguments_dynamic_add_parameter_ f_return_status fll_execute_arguments_dynamic_add_parameter(const f_string_static_t prefix, const f_string_static_t name, const f_string_static_t value, f_string_dynamics_t *arguments) { #ifndef _di_level_2_parameter_checking_ - if (prefix.used > prefix.size) return F_status_set_error(F_parameter); - if (name.used > name.size) return F_status_set_error(F_parameter); - if (value.used > value.size) return F_status_set_error(F_parameter); if (!arguments) return F_status_set_error(F_parameter); - if (arguments->used > arguments->size) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ - if (!name.used) return F_data_not; - if (!value.used) return F_data_not; - - f_status_t status = F_none; - - status = private_fll_execute_arguments_add_parameter(prefix.string, prefix.used, name.string, name.used, value.string, value.used, arguments); + const f_status_t status = private_fll_execute_arguments_add_parameter(prefix.string, prefix.used, name.string, name.used, value.string, value.used, arguments); if (F_status_is_error(status)) return status; return F_none; @@ -132,19 +97,11 @@ extern "C" { f_return_status fll_execute_arguments_dynamic_add_parameter_set(const f_string_static_t prefix[], const f_string_static_t name[], const f_string_static_t value[], const f_array_length_t size, f_string_dynamics_t *arguments) { #ifndef _di_level_2_parameter_checking_ if (!arguments) return F_status_set_error(F_parameter); - if (arguments->used > arguments->size) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ - if (!size) return F_data_not; - f_status_t status = F_none; for (f_array_length_t i = 0; i < size; i++) { - if (prefix[i].used > prefix[i].size) continue; - if (!name[i].used) continue; - if (name[i].used > name[i].size) continue; - if (!value[i].used) continue; - if (value[i].used > value[i].size) continue; status = private_fll_execute_arguments_add_parameter(prefix[i].string, prefix[i].used, name[i].string, name[i].used, value[i].string, value[i].used, arguments); if (F_status_is_error(status)) return status; @@ -158,16 +115,11 @@ extern "C" { f_return_status fll_execute_arguments_dynamic_add_set(const f_string_static_t source[], const f_array_length_t size, f_string_dynamics_t *arguments) { #ifndef _di_level_2_parameter_checking_ if (!arguments) return F_status_set_error(F_parameter); - if (arguments->used > arguments->size) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ - if (!size) return F_data_not; - f_status_t status = F_none; for (f_array_length_t i = 0; i < size; i++) { - if (!source[i].used) continue; - if (source[i].used > source[i].size) continue; status = private_fll_execute_arguments_add(source[i].string, source[i].used, arguments); if (F_status_is_error(status)) return status; @@ -181,240 +133,63 @@ extern "C" { f_return_status fll_execute_path(const f_string_t program_path, const f_string_statics_t arguments, const f_signal_how_t *signals, int *result) { #ifndef _di_level_2_parameter_checking_ if (!result) return F_status_set_error(F_parameter); - if (arguments.used > arguments.size) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ // create a string array that is compatible with execv() calls. f_string_t fixed_arguments[arguments.used + 2]; - f_string_t last_slash = f_string_t_initialize; - f_string_t program_name = f_string_t_initialize; - - f_string_length_t name_size = 0; + const f_string_t last_slash = strrchr(program_path, '/'); + const f_string_length_t name_size = last_slash ? strnlen(last_slash, f_path_max) : strnlen(program_path, f_path_max); - f_status_t status = F_none; + char program_name[name_size + 1]; - last_slash = strrchr(program_path, '/'); + program_name[name_size] = 0; - if (!last_slash) { - name_size = strnlen(program_path, f_path_max); + private_fll_execute_path_arguments_fixate(last_slash ? last_slash : program_path, arguments, name_size, program_name, fixed_arguments); - if (name_size > 1) { - f_macro_string_t_new(status, program_name, name_size + 1); - if (F_status_is_error(status)) return status; + { + const f_status_t status = f_file_exists(program_path); - memcpy(program_name, program_path, name_size); - memset(program_name, name_size, 0); - } - else { - name_size = 0; - } - } - else { - name_size = strnlen(last_slash, f_path_max); - - if (name_size > 1) { - f_macro_string_t_new(status, program_name, name_size + 1); - if (F_status_is_error(status)) return status; - - memcpy(program_name, last_slash + 1, name_size); - memset(program_name, name_size, 0); - } - else { - name_size = 0; - } - } - - if (!name_size) { - fixed_arguments[0] = 0; - } - else { - fixed_arguments[0] = program_name; - } - - for (f_string_length_t i = 0; i < arguments.used; i++) { - fixed_arguments[i + 1] = arguments.array[i].string; - } // for - - // insert the required array terminated. - fixed_arguments[arguments.used + 1] = 0; - - status = f_file_exists(program_path); - - if (F_status_is_error(status)) { - if (name_size > 0) f_macro_string_t_delete_simple(program_name, name_size); - - return status; - } - else if (status == F_false) { - if (name_size > 0) f_macro_string_t_delete_simple(program_name, name_size); - - return F_status_set_error(F_file_found_not); - } - - pid_t process_id = 0; - - process_id = fork(); - - if (process_id < 0) { - if (name_size > 0) { - f_macro_string_t_delete_simple(program_name, name_size); + if (F_status_is_error(status)) { + return status; } - - return F_status_set_error(F_fork); - } - - // child process. - if (!process_id) { - if (signals) { - f_signal_set_handle(SIG_BLOCK, &signals->block); - f_signal_set_handle(SIG_UNBLOCK, &signals->block_not); + else if (status == F_false) { + return F_status_set_error(F_file_found_not); } - - const int code = execv(program_path, fixed_arguments); - - exit(code); } - // have the parent wait for the child process to finish - waitpid(process_id, result, WUNTRACED | WCONTINUED); - - if (name_size > 0) { - f_macro_string_t_delete_simple(program_name, name_size); - } - - if (result != 0 && *result != 0) { - return F_status_set_error(F_failure); - } - - return F_none; + return private_fll_execute_fork(program_name, fixed_arguments, F_false, signals, result); } #endif // _di_fll_execute_path_ #ifndef _di_fll_execute_path_environment_ - f_return_status fll_execute_path_environment(const f_string_t program_path, const f_string_statics_t arguments, const f_signal_how_t *signals, const f_string_statics_t names, const f_string_statics_t values, int *result) { + f_return_status fll_execute_path_environment(const f_string_t program_path, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, int *result) { #ifndef _di_level_2_parameter_checking_ if (!result) return F_status_set_error(F_parameter); - if (arguments.used > arguments.size) return F_status_set_error(F_parameter); - if (names.used > names.size) return F_status_set_error(F_parameter); - if (values.used > values.size) return F_status_set_error(F_parameter); - if (names.used > values.used) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ // create a string array that is compatible with execv() calls. f_string_t fixed_arguments[arguments.used + 2]; - f_string_t last_slash = f_string_t_initialize; - f_string_t program_name = f_string_t_initialize; - - f_string_length_t name_size = 0; - - f_status_t status = F_none; - - last_slash = strrchr(program_path, '/'); - - if (!last_slash) { - name_size = strnlen(program_path, f_path_max); - - if (name_size > 1) { - f_macro_string_t_new(status, program_name, name_size + 1); - - if (F_status_is_error(status)) return status; + const f_string_t last_slash = strrchr(program_path, '/'); + const f_string_length_t name_size = last_slash ? strnlen(last_slash, f_path_max) : strnlen(program_path, f_path_max); - memcpy(program_name, program_path, name_size); - memset(program_name, name_size, 0); - } - else { - name_size = 0; - } - } - else { - name_size = strnlen(last_slash, f_path_max); + char program_name[name_size + 1]; - if (name_size > 1) { - f_macro_string_t_new(status, program_name, name_size + 1); + private_fll_execute_path_arguments_fixate(last_slash ? last_slash : program_path, arguments, name_size, program_name, fixed_arguments); - if (F_status_is_error(status)) return status; + { + const f_status_t status = f_file_exists(program_path); - memcpy(program_name, last_slash + 1, name_size); - memset(program_name, name_size, 0); - } - else { - name_size = 0; - } - } - - if (!name_size) { - fixed_arguments[0] = 0; - } - else { - fixed_arguments[0] = program_name; - } - - for (f_string_length_t i = 0; i < arguments.used; i++) { - fixed_arguments[i + 1] = arguments.array[i].string; - } // for - - // insert the required array terminated. - fixed_arguments[arguments.used + 1] = 0; - - status = f_file_exists(program_path); - - if (F_status_is_error(status)) { - if (name_size > 0) f_macro_string_t_delete_simple(program_name, name_size); - - return status; - } - else if (status == F_false) { - if (name_size > 0) f_macro_string_t_delete_simple(program_name, name_size); - - return F_status_set_error(F_file_found_not); - } - - pid_t process_id = 0; - - process_id = fork(); - - if (process_id < 0) { - if (name_size > 0) f_macro_string_t_delete_simple(program_name, name_size); - - return F_status_set_error(F_fork); - } - - // child process. - if (!process_id) { - if (signals) { - f_signal_set_handle(SIG_BLOCK, &signals->block); - f_signal_set_handle(SIG_UNBLOCK, &signals->block_not); + if (F_status_is_error(status)) { + return status; } - - clearenv(); - - for (f_array_length_t i = 0; i < names.used; i++) { - f_environment_set_dynamic(names.array[i], values.array[i], F_true); - } // for - - const int code = execv(program_path, fixed_arguments); - - exit(code); - } - - // have the parent wait for the child process to finish. - waitpid(process_id, result, WUNTRACED | WCONTINUED); - - if (name_size > 0) { - f_macro_string_t_delete_simple(program_name, name_size); - } - - if (result != 0) { - if (WIFEXITED(*result)) { - return F_none; + else if (status == F_false) { + return F_status_set_error(F_file_found_not); } - - return F_status_set_error(F_failure); } - return F_none; + return private_fll_execute_fork_environment(program_name, fixed_arguments, F_false, names, values, signals, result); } #endif // _di_fll_execute_path_environment_ @@ -422,7 +197,6 @@ extern "C" { f_return_status fll_execute_program(const f_string_t program_name, const f_string_statics_t arguments, const f_signal_how_t *signals, int *result) { #ifndef _di_level_2_parameter_checking_ if (!result) return F_status_set_error(F_parameter); - if (arguments.used > arguments.size) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ // create a string array that is compatible with execv() calls. @@ -430,55 +204,21 @@ extern "C" { fixed_arguments[0] = program_name; - f_status_t status = F_none; - f_array_length_t i = 0; - - for (; i < arguments.used; i++) { + for (f_array_length_t i = 0; i < arguments.used; i++) { fixed_arguments[i + 1] = arguments.array[i].string; } // for // insert the required array terminated. fixed_arguments[arguments.used + 1] = 0; - pid_t process_id = 0; - - process_id = fork(); - - if (process_id < 0) { - return F_status_set_error(F_fork); - } - - // child process. - if (!process_id) { - if (signals) { - f_signal_set_handle(SIG_BLOCK, &signals->block); - f_signal_set_handle(SIG_UNBLOCK, &signals->block_not); - } - - const int code = execvp(program_name, fixed_arguments); - - exit(code); - } - - // have the parent wait for the child process to finish - waitpid(process_id, result, WUNTRACED | WCONTINUED); - - if (result != 0 && *result != 0) { - return F_status_set_error(F_failure); - } - - return F_none; + return private_fll_execute_fork(program_name, fixed_arguments, F_true, signals, result); } #endif // _di_fll_execute_program_ #ifndef _di_fll_execute_program_environment_ - f_return_status fll_execute_program_environment(const f_string_t program_name, const f_string_statics_t arguments, const f_signal_how_t *signals, const f_string_statics_t names, const f_string_statics_t values, int *result) { + f_return_status fll_execute_program_environment(const f_string_t program_name, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, int *result) { #ifndef _di_level_2_parameter_checking_ if (!result) return F_status_set_error(F_parameter); - if (arguments.used > arguments.size) return F_status_set_error(F_parameter); - if (names.used > names.size) return F_status_set_error(F_parameter); - if (values.used > values.size) return F_status_set_error(F_parameter); - if (names.used > values.used) return F_status_set_error(F_parameter); #endif // _di_level_2_parameter_checking_ // create a string array that is compatible with execv() calls. @@ -486,10 +226,7 @@ extern "C" { fixed_arguments[0] = program_name; - f_status_t status = F_none; - f_array_length_t i = 0; - - for (; i < arguments.used; i++) { + for (f_array_length_t i = 0; i < arguments.used; i++) { fixed_arguments[i + 1] = arguments.array[i].string; } // for @@ -499,7 +236,7 @@ extern "C" { f_string_dynamic_t path = f_string_dynamic_t_initialize; f_string_dynamics_t paths = f_string_dynamics_t_initialize; - status = f_environment_get("PATH", &path); + f_status_t status = f_environment_get("PATH", &path); if (F_status_is_error(status)) { @@ -528,7 +265,7 @@ extern "C" { const f_string_length_t program_name_length = strnlen(program_name, f_path_max); f_string_dynamic_t *found = 0; - for (i = 0; i < paths.used; i++) { + for (f_array_length_t i = 0; i < paths.used; i++) { status = fl_string_append(program_name, program_name_length, &paths.array[i]); @@ -578,38 +315,7 @@ extern "C" { f_macro_string_dynamics_t_delete(status, paths); if (F_status_is_error(status)) return status; - pid_t process_id = 0; - - process_id = fork(); - - if (process_id < 0) { - return F_status_set_error(F_fork); - } - - // child process. - if (!process_id) { - if (signals) { - f_signal_set_handle(SIG_BLOCK, &signals->block); - f_signal_set_handle(SIG_UNBLOCK, &signals->block_not); - } - - clearenv(); - - for (i = 0; i < names.used; i++) { - f_environment_set_dynamic(names.array[i], values.array[i], F_true); - } // for - - const int code = execvp(program_path, fixed_arguments); - - exit(code); - } - - // have the parent wait for the child process to finish - waitpid(process_id, result, WUNTRACED | WCONTINUED); - - if (result != 0 && *result != 0) return F_status_set_error(F_failure); - - return F_none; + return private_fll_execute_fork_environment(program_name, fixed_arguments, F_true, names, values, signals, result); } #endif // _di_fll_execute_program_environment_ diff --git a/level_2/fll_execute/c/execute.h b/level_2/fll_execute/c/execute.h index fd51d31..756965b 100644 --- a/level_2/fll_execute/c/execute.h +++ b/level_2/fll_execute/c/execute.h @@ -52,18 +52,23 @@ extern "C" { * * @return * F_none on success. - * F_data_not if source length is 0. - * F_array_too_large (with error bit) if arguments array is too large for further allocation. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_reallocation (with error bit) on reallocation error. - * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_macro_string_dynamic_t_delete_simple(). + * Errors (with error bit) from: f_macro_string_dynamics_t_resize(). * Errors (with error bit) from: fl_string_append(). * Errors (with error bit) from: fl_string_dynamic_terminate(). + * Errors (with error bit) from: fl_string_dynamics_increase(). + * + * @see f_macro_string_dynamic_t_delete_simple() + * @see f_macro_string_dynamics_t_resize() + * @see fl_string_append() + * @see fl_string_dynamic_terminate() + * @see fl_string_dynamics_increase() */ #ifndef _di_fll_execute_arguments_add_ extern f_return_status fll_execute_arguments_add(const f_string_t source, const f_string_length_t length, f_string_dynamics_t *arguments); #endif // _di_fll_execute_arguments_add_ + /** * Add parameters as arguments to the execution arguments array. * @@ -93,14 +98,18 @@ extern "C" { * * @return * F_none on success. - * F_data_not if source length is 0. - * F_array_too_large (with error bit) if arguments array is too large for further allocation. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_reallocation (with error bit) on reallocation error. - * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_macro_string_dynamic_t_delete_simple(). + * Errors (with error bit) from: f_macro_string_dynamics_t_resize(). * Errors (with error bit) from: fl_string_append(). * Errors (with error bit) from: fl_string_dynamic_terminate(). + * Errors (with error bit) from: fl_string_dynamics_increase(). + * + * @see f_macro_string_dynamic_t_delete_simple() + * @see f_macro_string_dynamics_t_resize() + * @see fl_string_append() + * @see fl_string_dynamic_terminate() + * @see fl_string_dynamics_increase() */ #ifndef _di_fll_execute_arguments_add_parameter_ extern f_return_status fll_execute_arguments_add_parameter(const f_string_t prefix, const f_string_length_t prefix_length, const f_string_t name, const f_string_length_t name_length, const f_string_t value, const f_string_length_t value_length, f_string_dynamics_t *arguments); @@ -137,14 +146,18 @@ extern "C" { * * @return * F_none on success. - * F_data_not if size is 0. - * F_array_too_large (with error bit) if arguments array is too large for further allocation. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_reallocation (with error bit) on reallocation error. - * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_macro_string_dynamic_t_delete_simple(). + * Errors (with error bit) from: f_macro_string_dynamics_t_resize(). * Errors (with error bit) from: fl_string_append(). * Errors (with error bit) from: fl_string_dynamic_terminate(). + * Errors (with error bit) from: fl_string_dynamics_increase(). + * + * @see f_macro_string_dynamic_t_delete_simple() + * @see f_macro_string_dynamics_t_resize() + * @see fl_string_append() + * @see fl_string_dynamic_terminate() + * @see fl_string_dynamics_increase() */ #ifndef _di_fll_execute_arguments_add_parameter_set_ extern f_return_status fll_execute_arguments_add_parameter_set(const f_string_t prefix[], const f_string_length_t prefix_length[], const f_string_t name[], const f_string_length_t name_length[], const f_string_t value[], const f_string_length_t value_length[], const f_array_length_t size, f_string_dynamics_t *arguments); @@ -167,14 +180,18 @@ extern "C" { * * @return * F_none on success. - * F_data_not if size is 0. - * F_array_too_large (with error bit) if arguments array is too large for further allocation. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_reallocation (with error bit) on reallocation error. - * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_macro_string_dynamic_t_delete_simple(). + * Errors (with error bit) from: f_macro_string_dynamics_t_resize(). * Errors (with error bit) from: fl_string_append(). * Errors (with error bit) from: fl_string_dynamic_terminate(). + * Errors (with error bit) from: fl_string_dynamics_increase(). + * + * @see f_macro_string_dynamic_t_delete_simple() + * @see f_macro_string_dynamics_t_resize() + * @see fl_string_append() + * @see fl_string_dynamic_terminate() + * @see fl_string_dynamics_increase() */ #ifndef _di_fll_execute_arguments_add_set_ extern f_return_status fll_execute_arguments_add_set(const f_string_t source[], const f_string_length_t length[], const f_array_length_t size, f_string_dynamics_t *arguments); @@ -193,14 +210,18 @@ extern "C" { * * @return * F_none on success. - * F_data_not if source length is 0. - * F_array_too_large (with error bit) if arguments array is too large for further allocation. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_reallocation (with error bit) on reallocation error. - * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_macro_string_dynamic_t_delete_simple(). + * Errors (with error bit) from: f_macro_string_dynamics_t_resize(). * Errors (with error bit) from: fl_string_append(). * Errors (with error bit) from: fl_string_dynamic_terminate(). + * Errors (with error bit) from: fl_string_dynamics_increase(). + * + * @see f_macro_string_dynamic_t_delete_simple() + * @see f_macro_string_dynamics_t_resize() + * @see fl_string_append() + * @see fl_string_dynamic_terminate() + * @see fl_string_dynamics_increase() */ #ifndef _di_fll_execute_arguments_dynamic_add_ extern f_return_status fll_execute_arguments_dynamic_add(const f_string_static_t source, f_string_dynamics_t *arguments); @@ -229,14 +250,18 @@ extern "C" { * * @return * F_none on success. - * F_data_not if source length is 0. - * F_array_too_large (with error bit) if arguments array is too large for further allocation. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_reallocation (with error bit) on reallocation error. - * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_macro_string_dynamic_t_delete_simple(). + * Errors (with error bit) from: f_macro_string_dynamics_t_resize(). * Errors (with error bit) from: fl_string_append(). * Errors (with error bit) from: fl_string_dynamic_terminate(). + * Errors (with error bit) from: fl_string_dynamics_increase(). + * + * @see f_macro_string_dynamic_t_delete_simple() + * @see f_macro_string_dynamics_t_resize() + * @see fl_string_append() + * @see fl_string_dynamic_terminate() + * @see fl_string_dynamics_increase() */ #ifndef _di_fll_execute_arguments_dynamic_add_parameter_ extern f_return_status fll_execute_arguments_dynamic_add_parameter(const f_string_static_t prefix, const f_string_static_t name, const f_string_static_t value, f_string_dynamics_t *arguments); @@ -267,14 +292,18 @@ extern "C" { * * @return * F_none on success. - * F_data_not if source length is 0. - * F_array_too_large (with error bit) if arguments array is too large for further allocation. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_reallocation (with error bit) on reallocation error. - * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_macro_string_dynamic_t_delete_simple(). + * Errors (with error bit) from: f_macro_string_dynamics_t_resize(). * Errors (with error bit) from: fl_string_append(). * Errors (with error bit) from: fl_string_dynamic_terminate(). + * Errors (with error bit) from: fl_string_dynamics_increase(). + * + * @see f_macro_string_dynamic_t_delete_simple() + * @see f_macro_string_dynamics_t_resize() + * @see fl_string_append() + * @see fl_string_dynamic_terminate() + * @see fl_string_dynamics_increase() */ #ifndef _di_fll_execute_arguments_dynamic_add_parameter_set_ extern f_return_status fll_execute_arguments_dynamic_add_parameter_set(const f_string_static_t prefix[], const f_string_static_t name[], const f_string_static_t value[], const f_array_length_t size, f_string_dynamics_t *arguments); @@ -295,14 +324,18 @@ extern "C" { * * @return * F_none on success. - * F_data_not if source length is 0. - * F_array_too_large (with error bit) if arguments array is too large for further allocation. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_reallocation (with error bit) on reallocation error. - * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_macro_string_dynamic_t_delete_simple(). + * Errors (with error bit) from: f_macro_string_dynamics_t_resize(). * Errors (with error bit) from: fl_string_append(). * Errors (with error bit) from: fl_string_dynamic_terminate(). + * Errors (with error bit) from: fl_string_dynamics_increase(). + * + * @see f_macro_string_dynamic_t_delete_simple() + * @see f_macro_string_dynamics_t_resize() + * @see fl_string_append() + * @see fl_string_dynamic_terminate() + * @see fl_string_dynamics_increase() */ #ifndef _di_fll_execute_arguments_dynamic_add_set_ extern f_return_status fll_execute_arguments_dynamic_add_set(const f_string_static_t source[], const f_array_length_t size, f_string_dynamics_t *arguments); @@ -313,6 +346,10 @@ extern "C" { * * This does validate that the program path exists. * + * This does not call exit() when the child process exits. + * Instead, this returns F_child and assigns the child's return code to result. + * The caller is expected to handle the appropriate exit procedures and memory deallocation. + * * @param program_path * The entire path to the program. * @param arguments @@ -325,22 +362,22 @@ extern "C" { * * @return * F_none on success. - * F_access_denied (with error bit) on access denied for program_path. - * F_directory (with error bit) on invalid directory in program_path. + * F_child on success but this is the child thread (this may happen when calling scripts rather than executing a binary). * F_failure (with error bit) if result is non-zero. - * F_file_found_not (with error bit) if file does not exist at the program_path. - * F_file_stat (with error bit) on stat error while checking the program_path. - * F_loop (with error bit) on loop error while checking the program_path. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_not (with error bit) if out of memory. - * F_memory_reallocation (with error bit) on reallocation error. - * F_name (with error bit) on path name error. - * F_number_overflow (with error bit) on overflow error. - * F_parameter (with error bit) if a parameter is invalid. + * F_fork (with error bit) if fork failed. * * Errors (with error bit) from: f_file_exists(). + * Errors (with error bit) from: f_signal_set_handle(). * * @see execv() + * @see exit() + * @see fork() + * @see memcpy() + * @see strnlen() + * @see waitpid() + * + * @see f_file_exists() + * @see f_signal_set_handle() */ #ifndef _di_fll_execute_path_ extern f_return_status fll_execute_path(const f_string_t program_path, const f_string_statics_t arguments, const f_signal_how_t *signals, int *result); @@ -353,6 +390,10 @@ extern "C" { * * The environment is defined by the names and values pair. * + * This does not call exit() when the child process exits. + * Instead, this returns F_child and assigns the child's return code to result. + * The caller is expected to handle the appropriate exit procedures and memory deallocation. + * * @param program_path * The entire path to the program. * @param arguments @@ -361,37 +402,39 @@ extern "C" { * An array of strings representing the environment variable names. * At most names.used variables are created. * Duplicate names are overwritten. - * @param set_signal - * (optional) A pointer to the set of signals. - * Set to 0 to disable. * @param values * An array of strings representing the environment variable names. * The values.used must be of at least names.used. * Set individual strings.used to 0 for empty/NULL values. + * @param signals + * (optional) A pointer to the set of signals. + * Set to 0 to disable. * @param result * The code returned after finishing execution of program_path. * * @return * F_none on success. - * F_access_denied (with error bit) on access denied for program_path. - * F_directory (with error bit) on invalid directory in program_path. + * F_child on success but this is the child thread (this may happen when calling scripts rather than executing a binary). * F_failure (with error bit) if result is non-zero. - * F_file_found_not (with error bit) if file does not exist at the program_path. - * F_file_stat (with error bit) on stat error while checking the program_path. - * F_loop (with error bit) on loop error while checking the program_path. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_not (with error bit) if out of memory. - * F_memory_reallocation (with error bit) on reallocation error. - * F_name (with error bit) on path name error. - * F_number_overflow (with error bit) on overflow error. - * F_parameter (with error bit) if a parameter is invalid. + * F_fork (with error bit) if fork failed. * + * Errors (with error bit) from: f_environment_set_dynamic(). * Errors (with error bit) from: f_file_exists(). + * Errors (with error bit) from: f_signal_set_handle(). * * @see execv() + * @see clearenv() + * @see fork() + * @see memcpy() + * @see strnlen() + * @see waitpid() + * + * @see f_environment_set_dynamic() + * @see f_file_exists() + * @see f_signal_set_handle() */ #ifndef _di_fll_execute_path_environment_ - f_return_status fll_execute_path_environment(const f_string_t program_path, const f_string_statics_t arguments, const f_signal_how_t *signals, const f_string_statics_t names, const f_string_statics_t values, int *result); + extern f_return_status fll_execute_path_environment(const f_string_t program_path, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, int *result); #endif // _di_fll_execute_path_environment_ /** @@ -399,6 +442,10 @@ extern "C" { * * This does not validate the path to the program. * + * This does not call exit() when the child process exits. + * Instead, this returns F_child and assigns the child's return code to result. + * The caller is expected to handle the appropriate exit procedures and memory deallocation. + * * @param program_name * The name of the program. * @param arguments @@ -411,17 +458,20 @@ extern "C" { * * @return * F_none on success. + * F_child on success but this is the child thread (this may happen when calling scripts rather than executing a binary). * F_failure (with error bit) if result is non-zero. - * F_file_found_not (with error bit) if file does not exist at the program_path. - * F_fork (with error bit) on fork failure. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_reallocation (with error bit) on reallocation error. - * F_parameter (with error bit) if a parameter is invalid. - * F_string_too_large (with error bit) if the combined string (generated from PATH) is too large. + * F_fork (with error bit) if fork failed. * * Errors (with error bit) from: f_file_exists(). + * Errors (with error bit) from: f_signal_set_handle(). * * @see execvp() + * @see fork() + * @see strnlen() + * @see waitpid() + * + * @see f_file_exists() + * @see f_signal_set_handle() */ #ifndef _di_fll_execute_program_ extern f_return_status fll_execute_program(const f_string_t program_name, const f_string_statics_t arguments, const f_signal_how_t *signals, int *result); @@ -436,6 +486,10 @@ extern "C" { * This is done because the PATH environment will get cleared or may be set differently. * Execution of program_name is done using the PATH environment prior to clearing and reassigning the environment variables. * + * Unlike the execv() family of functions, this does not call exit() when the child process exits. + * Instead, this returns F_child and assigns the child's return code to result. + * The caller is expected to handle the appropriate exit procedures and memory deallocation. + * * @param program_name * The name of the program. * @param arguments @@ -444,42 +498,46 @@ extern "C" { * An array of strings representing the environment variable names. * At most names.used variables are created. * Duplicate names are overwritten. - * @param set_signal - * (optional) A pointer to the set of signals. - * Set to 0 to disable. * @param values * An array of strings representing the environment variable names. * The values.used must be of at least names.used. * Set individual strings.used to 0 for empty/null values. + * @param signals + * (optional) A pointer to the set of signals. + * Set to 0 to disable. * @param result * The code returned after finishing execution of program. * * @return * F_none on success. - * F_access_denied (with error bit) on access denied for program_path. - * F_array_too_large (with error bit) if paths array (generated from PATH) is too large for further addressing. - * F_directory (with error bit) on invalid directory in program_path. + * F_child on success but this is the child thread (this may happen when calling scripts rather than executing a binary). * F_failure (with error bit) if result is non-zero. - * F_file_found_not (with error bit) if file does not exist at the program_path. - * F_fork (with error bit) on fork failure. - * F_loop (with error bit) on loop error while checking the program_path. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_not (with error bit) if out of memory. - * F_memory_reallocation (with error bit) on reallocation error. - * F_name (with error bit) on path name error. - * F_number_overflow (with error bit) on overflow error. - * F_parameter (with error bit) if a parameter is invalid. - * F_string_too_large (with error bit) if the combined string (generated from PATH) is too large. + * F_fork (with error bit) if fork failed. * + * Errors (with error bit) from: f_environment_get(). * Errors (with error bit) from: f_file_exists(). + * Errors (with error bit) from: f_macro_string_dynamic_t_delete(). + * Errors (with error bit) from: f_macro_string_dynamics_t_delete(). + * Errors (with error bit) from: f_signal_set_handle(). * Errors (with error bit) from: fl_environment_path_explode_dynamic(). * Errors (with error bit) from: fl_string_append(). * Errors (with error bit) from: fl_string_dynamic_terminate(). * - * @see execvpe() + * @see execvp() + * @see fork() + * @see memcpy() + * @see strnlen() + * @see waitpid() + * + * @see f_environment_get() + * @see f_file_exists() + * @see f_signal_set_handle() + * @see fl_environment_path_explode_dynamic() + * @see fl_string_append() + * @see fl_string_dynamic_terminate() */ #ifndef _di_fll_execute_program_environment_ - extern f_return_status fll_execute_program_environment(const f_string_t program_name, const f_string_statics_t arguments, const f_signal_how_t *signals, const f_string_statics_t names, const f_string_statics_t values, int *result); + extern f_return_status fll_execute_program_environment(const f_string_t program_name, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, int *result); #endif // _di_fll_execute_program_environment_ #ifdef __cplusplus diff --git a/level_2/fll_execute/c/private-execute.c b/level_2/fll_execute/c/private-execute.c index aae7076..11e12dc 100644 --- a/level_2/fll_execute/c/private-execute.c +++ b/level_2/fll_execute/c/private-execute.c @@ -7,27 +7,19 @@ extern "C" { #if !defined(_di_fll_execute_arguments_add_) || !defined(_di_fll_execute_arguments_add_set_) || !defined(_di_fll_execute_arguments_dynamic_add_) || !defined(_di_fll_execute_arguments_dynamic_add_set_) f_return_status private_fll_execute_arguments_add(const f_string_t source, const f_string_length_t length, f_string_dynamics_t *arguments) { - f_status_t status = F_none; - if (arguments->used == arguments->size) { - if (arguments->size + f_memory_default_allocation_step > f_array_length_t_size) { - if (arguments->size + 1 > f_array_length_t_size) return F_status_set_error(F_array_too_large); - f_macro_string_dynamics_t_resize(status, (*arguments), arguments->size + 1); - } - else { - f_macro_string_dynamics_t_resize(status, (*arguments), arguments->size + f_memory_default_allocation_step); - } - - if (F_status_is_error(status)) return status; - } + f_status_t status = fl_string_dynamics_increase(arguments); + if (F_status_is_error(status)) return status; f_string_dynamic_t argument = f_string_dynamic_t_initialize; - status = fl_string_append(source, length, &argument); + if (length) { + status = fl_string_append(source, length, &argument); - if (F_status_is_error(status)) { - f_macro_string_dynamic_t_delete_simple(argument); - return status; + if (F_status_is_error(status)) { + f_macro_string_dynamic_t_delete_simple(argument); + return status; + } } status = fl_string_dynamic_terminate(&argument); @@ -48,23 +40,13 @@ extern "C" { #if !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_) f_return_status private_fll_execute_arguments_add_parameter(const f_string_t prefix, const f_string_length_t prefix_length, const f_string_t name, const f_string_length_t name_length, const f_string_t value, const f_string_length_t value_length, f_string_dynamics_t *arguments) { - f_status_t status = F_none; - if (arguments->used + 1 >= arguments->size) { - if (arguments->size + f_memory_default_allocation_step > f_array_length_t_size) { - if (arguments->size + 2 > f_array_length_t_size) return F_status_set_error(F_array_too_large); - f_macro_string_dynamics_t_resize(status, (*arguments), arguments->size + 2); - } - else { - f_macro_string_dynamics_t_resize(status, (*arguments), arguments->size + f_memory_default_allocation_step + 1); - } - - if (F_status_is_error(status)) return status; - } + f_status_t status = fl_string_dynamics_increase(arguments); + if (F_status_is_error(status)) return status; f_string_dynamic_t argument = f_string_dynamic_t_initialize; - if (prefix_length > 0) { + if (prefix_length) { status = fl_string_append(prefix, prefix_length, &argument); if (F_status_is_error(status)) { @@ -73,11 +55,13 @@ extern "C" { } } - status = fl_string_append(name, name_length, &argument); + if (name_length) { + status = fl_string_append(name, name_length, &argument); - if (F_status_is_error(status)) { - f_macro_string_dynamic_t_delete_simple(argument); - return status; + if (F_status_is_error(status)) { + f_macro_string_dynamic_t_delete_simple(argument); + return status; + } } status = fl_string_dynamic_terminate(&argument); @@ -94,14 +78,23 @@ extern "C" { f_macro_string_dynamic_t_clear(argument); - status = fl_string_append(value, value_length, &argument); + if (value_length) { + status = fl_string_append(value, value_length, &argument); + + if (F_status_is_error(status)) { + f_macro_string_dynamic_t_delete_simple(argument); + return status; + } + } + + status = fl_string_dynamic_terminate(&argument); if (F_status_is_error(status)) { f_macro_string_dynamic_t_delete_simple(argument); return status; } - status = fl_string_dynamic_terminate(&argument); + status = fl_string_dynamics_increase(arguments); if (F_status_is_error(status)) { f_macro_string_dynamic_t_delete_simple(argument); @@ -117,6 +110,113 @@ 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_path_) || !defined(_di_fll_execute_program_) + f_return_status private_fll_execute_fork(const f_string_t program_path, const f_string_t fixed_arguments[], const bool execute_program, const f_signal_how_t *signals, int *result) { + + const pid_t process_id = fork(); + + if (process_id < 0) { + return F_status_set_error(F_fork); + } + + // child process. + if (!process_id) { + + if (signals) { + f_signal_set_handle(SIG_BLOCK, &signals->block); + f_signal_set_handle(SIG_UNBLOCK, &signals->block_not); + } + + const int code = execute_program ? execvp(program_path, fixed_arguments) : execv(program_path, fixed_arguments); + + if (result) { + *result = code; + } + + return F_child; + } + + // have the parent wait for the child process to finish. + waitpid(process_id, result, WUNTRACED | WCONTINUED); + + if (result != 0) { + if (WIFEXITED(*result)) { + return F_none; + } + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_program_) + +#if !defined(_di_fll_execute_path_environment_) || !defined(_di_fll_execute_program_environment_) + f_return_status private_fll_execute_fork_environment(const f_string_t program_path, const f_string_t fixed_arguments[], const bool execute_program, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, int *result) { + + const pid_t process_id = fork(); + + if (process_id < 0) { + return F_status_set_error(F_fork); + } + + // child process. + if (!process_id) { + if (signals) { + f_signal_set_handle(SIG_BLOCK, &signals->block); + f_signal_set_handle(SIG_UNBLOCK, &signals->block_not); + } + + clearenv(); + + for (f_array_length_t i = 0; i < names.used; i++) { + f_environment_set_dynamic(names.array[i], values.array[i], F_true); + } // for + + const int code = execute_program ? execvp(program_path, fixed_arguments) : execv(program_path, fixed_arguments); + + if (result) { + *result = code; + } + + return F_child; + } + + // have the parent wait for the child process to finish. + waitpid(process_id, result, WUNTRACED | WCONTINUED); + + if (result != 0) { + if (WIFEXITED(*result)) { + return F_none; + } + + return F_status_set_error(F_failure); + } + } +#endif // !defined(_di_fll_execute_path_environment_) || !defined(_di_fll_execute_program_environment_) + +#if !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_path_environment_) + void private_fll_execute_path_arguments_fixate(const f_string_t program_path, const f_string_statics_t arguments, const f_string_length_t name_size, char program_name[], f_string_t fixed_arguments[]) { + + memcpy(program_name, program_path, name_size); + program_name[name_size] = 0; + + if (name_size) { + fixed_arguments[0] = program_name; + } + else { + fixed_arguments[0] = 0; + } + + for (f_string_length_t i = 0; i < arguments.used; i++) { + fixed_arguments[i + 1] = arguments.array[i].string; + } // for + + // insert the required end of array designator. + fixed_arguments[arguments.used + 1] = 0; + } +#endif // !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_path_environment_) + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_2/fll_execute/c/private-execute.h b/level_2/fll_execute/c/private-execute.h index cf75d09..0b7df63 100644 --- a/level_2/fll_execute/c/private-execute.h +++ b/level_2/fll_execute/c/private-execute.h @@ -44,12 +44,18 @@ extern "C" { * * @return * F_none on success. - * F_data_not if name_length is 0. - * F_array_too_large (with error bit) if arguments array is too large for further allocation. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_reallocation (with error bit) on reallocation error. - * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_macro_string_dynamic_t_delete_simple(). + * Errors (with error bit) from: f_macro_string_dynamics_t_resize(). + * Errors (with error bit) from: fl_string_append(). + * Errors (with error bit) from: fl_string_dynamic_terminate(). + * Errors (with error bit) from: fl_string_dynamics_increase(). + * + * @see f_macro_string_dynamic_t_delete_simple() + * @see f_macro_string_dynamics_t_resize() + * @see fl_string_append() + * @see fl_string_dynamic_terminate() + * @see fl_string_dynamics_increase() * @see fll_execute_arguments_add() * @see fll_execute_arguments_add_set() * @see fll_execute_arguments_dynamic_add() @@ -81,12 +87,18 @@ extern "C" { * * @return * F_none on success. - * F_data_not if name_length is 0. - * F_array_too_large (with error bit) if arguments array is too large for further allocation. - * F_memory_allocation (with error bit) on allocation error. - * F_memory_reallocation (with error bit) on reallocation error. - * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_macro_string_dynamic_t_delete_simple(). + * Errors (with error bit) from: f_macro_string_dynamics_t_resize(). + * Errors (with error bit) from: fl_string_append(). + * Errors (with error bit) from: fl_string_dynamic_terminate(). + * Errors (with error bit) from: fl_string_dynamics_increase(). + * + * @see f_macro_string_dynamic_t_delete_simple() + * @see f_macro_string_dynamics_t_resize() + * @see fl_string_append() + * @see fl_string_dynamic_terminate() + * @see fl_string_dynamics_increase() * @see fll_execute_arguments_add_parameter() * @see fll_execute_arguments_add_parameter_set() * @see fll_execute_arguments_dynamic_add_parameter() @@ -96,6 +108,100 @@ extern "C" { extern f_return_status private_fll_execute_arguments_add_parameter(const f_string_t prefix, const f_string_length_t prefix_length, const f_string_t name, const f_string_length_t name_length, const f_string_t value, const f_string_length_t value_length, f_string_dynamics_t *arguments) f_gcc_attribute_visibility_internal; #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 performing the fork and execute operation. + * + * @param program_path + * The part of the path to the program representing the program name to copy from. + * @param fixed_arguments + * A fixed array of strings representing the arguments. + * @param execute_path + * If TRUE then execvp() is called to perform execution. + * If FALSE then execv() is called to perform execution. + * @param set_signal + * (optional) A pointer to the set of signals. + * Set to 0 to disable. + * @param result + * The code returned after finishing execution of program_path. + * + * @return + * F_none on success. + * F_child on success but this is the child thread. + * F_fork (with error bit set) on fork failure. + * F_failure (with error bit set) on execution failure. + * + * @see execv() + * @see execvp() + * @see fll_execute_path() + * @see fll_execute_program() + */ +#if !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_program_) + extern f_return_status private_fll_execute_fork(const f_string_t program_path, const f_string_t fixed_arguments[], const bool execute_path, const f_signal_how_t *signals, int *result) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_program_) + +/** + * Private function for performing the fork and execute operation using a specified environment. + * + * @param program_path + * The part of the path to the program representing the program name to copy from. + * @param fixed_arguments + * A fixed array of strings representing the arguments. + * @param execute_program + * If TRUE then execvp() is called to perform execution. + * If FALSE then execv() is called to perform execution. + * @param names + * An array of strings representing the environment variable names. + * At most names.used variables are created. + * Duplicate names are overwritten. + * @param values + * An array of strings representing the environment variable names. + * The values.used must be of at least names.used. + * Set individual strings.used to 0 for empty/NULL values. + * @param signals + * (optional) A pointer to the set of signals. + * Set to 0 to disable. + * @param result + * The code returned after finishing execution of program_path. + * + * @return + * F_none on success. + * F_child on success but this is the child thread. + * F_fork (with error bit set) on fork failure. + * F_failure (with error bit set) on execution failure. + * + * @see execv() + * @see execvpe() + * @see fll_execute_path_environment() + * @see fll_execute_program_environment() + */ +#if !defined(_di_fll_execute_path_environment_) || !defined(_di_fll_execute_program_environment_) + extern f_return_status private_fll_execute_fork_environment(const f_string_t program_path, const f_string_t fixed_arguments[], const bool execute_program, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, int *result) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_fll_execute_path_environment_) || !defined(_di_fll_execute_program_environment_) + +/** + * Private function for reconstructing the arguments into a fixed array. + * + * @param program_path + * The part of the path to the program representing the program name to copy from. + * @param arguments + * An array of strings representing the arguments. + * @param name_size + * The size of the program_path to copy. + * @param program_name + * The destination to copy the name to. + * @param fixed_arguments + * The array of arguments to be updated with the program name. + * + * @return + * F_none on success. + * + * @see fll_execute_path() + * @see fll_execute_path_environment() + */ +#if !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_path_environment_) + extern void private_fll_execute_path_arguments_fixate(const f_string_t program_path, const f_string_statics_t arguments, const f_string_length_t name_size, char program_name[], f_string_t fixed_arguments[]) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_path_environment_) + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_2/fll_status/c/status.c b/level_2/fll_status/c/status.c index c209c88..a539418 100644 --- a/level_2/fll_status/c/status.c +++ b/level_2/fll_status/c/status.c @@ -416,6 +416,16 @@ extern "C" { return F_none; } + if (fl_string_compare(string, FL_status_string_child, length, FL_status_string_child_length) == F_equal_to) { + *code = F_child; + return F_none; + } + + if (fl_string_compare(string, FL_status_string_child_not, length, FL_status_string_child_not_length) == F_equal_to) { + *code = F_child_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; @@ -691,6 +701,16 @@ extern "C" { return F_none; } + if (fl_string_compare(string, FL_status_string_parent, length, FL_status_string_parent_length) == F_equal_to) { + *code = F_parent; + return F_none; + } + + if (fl_string_compare(string, FL_status_string_parent_not, length, FL_status_string_parent_not_length) == F_equal_to) { + *code = F_parent_not; + return F_none; + } + if (fl_string_compare(string, FL_status_string_pipe, length, FL_status_string_pipe_length) == F_equal_to) { *code = F_pipe; return F_none; diff --git a/level_3/fake/c/fake.c b/level_3/fake/c/fake.c index f3fa3dd..0f1d37b 100644 --- a/level_3/fake/c/fake.c +++ b/level_3/fake/c/fake.c @@ -290,7 +290,7 @@ extern "C" { if (F_status_is_error_not(status) && status != F_signal) { f_string_static_t stub = f_string_static_t_initialize; - status = fake_build_operate(*data, stub); + status = fake_build_operate(stub, data); } } else if (data->operation == fake_operation_clean) { @@ -310,14 +310,18 @@ extern "C" { } if (F_status_is_error_not(status) && status != F_signal) { - status = fake_make_operate(*data); + status = fake_make_operate(data); + + if (status == F_child) { + break; + } } } else if (data->operation == fake_operation_skeleton) { status = fake_skeleton_operate(*data); } - if (status == F_signal || fake_signal_received(*data)) { + if (status == F_signal || status == F_child || fake_signal_received(*data)) { break; } else if (F_status_is_error(status)) { @@ -337,7 +341,7 @@ extern "C" { if (F_status_is_error(status) || status == F_signal) { fprintf(data->error.to.stream, "%c", f_string_eol[0]); } - else { + else if (status != F_child) { fprintf(data->output.stream, "%cAll operations complete.%c%c", f_string_eol[0], f_string_eol[0], f_string_eol[0]); } } diff --git a/level_3/fake/c/fake.h b/level_3/fake/c/fake.h index 67954cb..6e6f91a 100644 --- a/level_3/fake/c/fake.h +++ b/level_3/fake/c/fake.h @@ -378,6 +378,7 @@ extern "C" { uint8_t operation; mode_t umask; + int child; f_signal_t signal; f_string_dynamics_t define; @@ -445,6 +446,7 @@ extern "C" { fll_error_print_t_initialize, \ 0, \ 0, \ + 0, \ f_signal_t_initialize, \ f_string_dynamics_t_initialize, \ f_string_dynamic_t_initialize, \ diff --git a/level_3/fake/c/main.c b/level_3/fake/c/main.c index 7aa0125..5d612b0 100644 --- a/level_3/fake/c/main.c +++ b/level_3/fake/c/main.c @@ -11,6 +11,8 @@ * @return * 0 on success. * 1 on error. + * + * @see exit() */ int main(const unsigned long argc, const f_string_t *argv) { const f_console_arguments_t arguments = { argc, argv }; @@ -47,5 +49,9 @@ int main(const unsigned long argc, const f_string_t *argv) { return 1; } + if (status == F_child) { + exit(data.child); + } + return 0; } diff --git a/level_3/fake/c/private-build.c b/level_3/fake/c/private-build.c index 87b0803..fcee29f 100644 --- a/level_3/fake/c/private-build.c +++ b/level_3/fake/c/private-build.c @@ -165,7 +165,7 @@ extern "C" { #ifndef _di_fake_build_copy_ void fake_build_copy(const fake_data_t data, const f_mode_t mode, const f_string_t label, const f_string_static_t source, const f_string_static_t destination, const f_string_statics_t files, const f_string_static_t file_stage, const f_string_length_t preserve, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return; + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return; if (fake_signal_received(data)) { *status = F_status_set_error(F_signal); @@ -379,7 +379,7 @@ extern "C" { #ifndef _di_fake_build_skeleton_ void fake_build_skeleton(const fake_data_t data, const fake_build_data_t data_build, const mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return; + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return; if (fake_signal_received(data)) { *status = F_status_set_error(F_signal); @@ -464,13 +464,13 @@ extern "C" { #endif // _di_fake_build_skeleton_ #ifndef _di_fake_build_execute_process_script_ - void fake_build_execute_process_script(const fake_data_t data, const fake_build_data_t data_build, const f_string_static_t process_script, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return; - if (!process_script.used) return; + int fake_build_execute_process_script(const fake_data_t data, const fake_build_data_t data_build, const f_string_static_t process_script, const f_string_static_t file_stage, f_status_t *status) { + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return data.child; + if (!process_script.used) return 0; if (fake_signal_received(data)) { *status = F_status_set_error(F_signal); - return; + return 0; } f_string_dynamics_t arguments = f_string_dynamics_t_initialize; @@ -515,7 +515,7 @@ extern "C" { fll_error_print(data.error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); f_macro_string_dynamics_t_delete_simple(arguments); - return; + return 0; } { @@ -536,7 +536,7 @@ extern "C" { f_macro_string_dynamic_t_delete_simple(defines); f_macro_string_dynamics_t_delete_simple(arguments); - return; + return 0; } *status = fl_string_dynamic_terminate_after(&defines); @@ -546,7 +546,7 @@ extern "C" { f_macro_string_dynamic_t_delete_simple(defines); f_macro_string_dynamics_t_delete_simple(arguments); - return; + return 0; } } @@ -618,7 +618,7 @@ extern "C" { fll_error_print(data.error, F_status_set_fine(*status), "fll_execute_arguments_add_parameter_set", F_true); f_macro_string_dynamics_t_delete_simple(arguments); - return; + return 0; } } @@ -646,10 +646,12 @@ extern "C" { f_macro_string_dynamic_t_delete_simple(path); f_macro_string_dynamics_t_delete_simple(arguments); - return; + return 0; } } + int return_code = 0; + if (fake_signal_received(data)) { *status = F_status_set_error(F_signal); @@ -657,21 +659,19 @@ extern "C" { f_macro_string_dynamics_t_delete_simple(arguments); } else { - int return_code = 0; - // child processes should receive all signals, without blocking. f_signal_how_t signals = f_signal_how_t_initialize; f_signal_set_empty(&signals.block); f_signal_set_fill(&signals.block_not); - *status = fll_execute_path_environment(path.string, arguments, &signals, data_build.environment.names, data_build.environment.values, &return_code); + *status = fll_execute_path_environment(path.string, arguments, data_build.environment.names, data_build.environment.values, &signals, &return_code); f_macro_string_dynamics_t_delete_simple(arguments); if (fake_signal_received(data)) { *status = F_status_set_error(F_signal); } - else { + else if (*status != F_child) { if (F_status_is_error(*status)) { if (F_status_set_fine(*status) == F_failure) { if (data.error.verbosity != f_console_verbosity_quiet) { @@ -693,6 +693,8 @@ extern "C" { } f_macro_string_dynamic_t_delete_simple(path); + + return return_code; } #endif // _di_fake_build_execute_process_script_ @@ -730,19 +732,21 @@ extern "C" { #endif // _di_fake_build_get_file_name_without_extension_ #ifndef _di_fake_build_libraries_script_ - void fake_build_libraries_script(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return; + int fake_build_libraries_script(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return data.child; // @todo needs to perform some sort of regex replace on the library scripts. fake_build_touch(data, file_stage, status); + + return 0; } #endif // _di_fake_build_libraries_script_ #ifndef _di_fake_build_library_shared_ - void fake_build_library_shared(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return; - if (!data_build.setting.build_sources_library.used) return; + int fake_build_library_shared(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return data.child; + if (!data_build.setting.build_sources_library.used) return 0; if (data.error.verbosity != f_console_verbosity_quiet) { fprintf(data.output.stream, "%c", f_string_eol[0]); @@ -786,7 +790,7 @@ extern "C" { fll_error_print(data.error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); f_macro_string_dynamics_t_delete_simple(arguments); - return; + return 0; } } @@ -925,16 +929,22 @@ extern "C" { fll_error_print(data.error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); f_macro_string_dynamics_t_delete_simple(arguments); - return; + return 0; } } - fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status); + { + const int result = fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status); - f_macro_string_dynamics_t_delete_simple(arguments); + f_macro_string_dynamics_t_delete_simple(arguments); - if (F_status_is_error(*status)) { - return; + if (F_status_is_error(*status)) { + return 0; + } + + if (*status == F_child) { + return result; + } } if (data_build.setting.version_target != fake_build_version_type_micro) { @@ -963,7 +973,7 @@ extern "C" { if (fake_signal_received(data)) { *status = F_status_set_error(F_signal); - return; + return 0; } *status = f_file_link(parameter_file_name_micro, parameter_file_path); @@ -974,11 +984,11 @@ extern "C" { else if (F_status_is_error(*status)) { if (F_status_set_fine(*status) == F_file_found) { fll_error_file_print(data.error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_path, "link", fll_error_file_type_file); - return; + return 0; } fll_error_file_print(data.error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_name_micro, "link", fll_error_file_type_file); - return; + return 0; } } @@ -995,7 +1005,7 @@ extern "C" { if (fake_signal_received(data)) { *status = F_status_set_error(F_signal); - return; + return 0; } if (data_build.setting.version_target == fake_build_version_type_major) { @@ -1027,7 +1037,7 @@ extern "C" { if (F_status_set_fine(*status) == F_file_found) { fll_error_file_print(data.error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_path, "link", fll_error_file_type_file); - return; + return 0; } if (data_build.setting.version_target == fake_build_version_type_major) { @@ -1040,18 +1050,20 @@ extern "C" { fll_error_file_print(data.error, F_status_set_fine(*status), "f_file_link", F_true, parameter_file_name_micro, "link", fll_error_file_type_file); } - return; + return 0; } } fake_build_touch(data, file_stage, status); + + return 0; } #endif // _di_fake_build_library_shared_ #ifndef _di_fake_build_library_static_ - void fake_build_library_static(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return; - if (!data_build.setting.build_sources_library.used) return; + int fake_build_library_static(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return data.child; + if (!data_build.setting.build_sources_library.used) return 0; if (data.error.verbosity != f_console_verbosity_quiet) { fprintf(data.output.stream, "%c", f_string_eol[0]); @@ -1167,17 +1179,21 @@ extern "C" { } // for } + int result = data.child; + if (F_status_is_error_not(*status)) { - fake_execute(data, data_build.environment, data_build.setting.build_indexer, arguments, status); + result = fake_execute(data, data_build.environment, data_build.setting.build_indexer, arguments, status); } f_macro_string_dynamic_t_delete_simple(file_name); f_macro_string_dynamic_t_delete_simple(source_path); f_macro_string_dynamics_t_delete_simple(arguments); - if (F_status_is_error_not(*status)) { + if (F_status_is_error_not(*status) && *status != F_child) { fake_build_touch(data, file_stage, status); } + + return result; } #endif // _di_fake_build_library_static_ @@ -2377,9 +2393,9 @@ extern "C" { #endif // _di_fake_build_load_stage_ #ifndef _di_fake_build_objects_static_ - void fake_build_objects_static(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return; - if (!data_build.setting.build_sources_library.used) return; + int fake_build_objects_static(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return data.child; + if (!data_build.setting.build_sources_library.used) return 0; if (data.error.verbosity != f_console_verbosity_quiet) { fprintf(data.output.stream, "%c", f_string_eol[0]); @@ -2395,6 +2411,8 @@ extern "C" { const f_string_static_t *path_sources = &data.path_sources; + int result = data.child; + if (data_build.setting.path_standard) { path_sources = &data.path_sources_c; @@ -2555,27 +2573,29 @@ extern "C" { break; } - fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status); + result = fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status); f_macro_string_dynamics_t_delete_simple(arguments); - if (F_status_is_error(*status)) break; + if (F_status_is_error(*status) || *status == F_child) break; } // for f_macro_string_dynamic_t_delete_simple(file_name); f_macro_string_dynamic_t_delete_simple(destination_path); f_macro_string_dynamics_t_delete_simple(arguments); - if (F_status_is_error_not(*status)) { + if (F_status_is_error_not(*status) && *status != F_child) { fake_build_touch(data, file_stage, status); } + + return result; } #endif // _di_fake_build_objects_static_ #ifndef _di_fake_build_operate_ - f_return_status fake_build_operate(const fake_data_t data, const f_string_static_t setting_file) { + f_return_status fake_build_operate(const f_string_static_t setting_file, fake_data_t *data) { - if (fake_signal_received(data)) { + if (fake_signal_received(*data)) { return F_signal; } @@ -2585,70 +2605,70 @@ extern "C" { fake_build_data_t data_build = fake_build_data_t_initialize; fake_build_stage_t stage = fake_build_stage_t_initialize; - f_macro_mode_t_set_default_umask(mode, data.umask); + f_macro_mode_t_set_default_umask(mode, data->umask); - fake_build_load_setting(data, setting_file, &data_build.setting, &status); + fake_build_load_setting(*data, setting_file, &data_build.setting, &status); if (F_status_is_fine(status)) { - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.output.stream, "%c", f_string_eol[0]); - fl_color_print(data.output.stream, data.context.set.important, "Building project%c", data_build.setting.project_name.used ? ' ' : 0); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->output.stream, "%c", f_string_eol[0]); + fl_color_print(data->output.stream, data->context.set.important, "Building project%c", data_build.setting.project_name.used ? ' ' : 0); if (data_build.setting.project_name.used) { - fl_color_print_code(data.output.stream, data.context.notable); - f_print_dynamic(data.output.stream, data_build.setting.project_name); - fl_color_print_code(data.output.stream, data.context.reset); + fl_color_print_code(data->output.stream, data->context.notable); + f_print_dynamic(data->output.stream, data_build.setting.project_name); + fl_color_print_code(data->output.stream, data->context.reset); } - fl_color_print(data.output.stream, data.context.set.important, "."); - fprintf(data.output.stream, "%c", f_string_eol[0]); + fl_color_print(data->output.stream, data->context.set.important, "."); + fprintf(data->output.stream, "%c", f_string_eol[0]); } } - fake_build_load_stage(data, setting_file, &stage, &status); + fake_build_load_stage(*data, setting_file, &stage, &status); - fake_build_load_environment(data, data_build, &data_build.environment, &status); + fake_build_load_environment(*data, data_build, &data_build.environment, &status); - fake_build_skeleton(data, data_build, mode.directory, stage.file_skeleton, &status); + fake_build_skeleton(*data, data_build, mode.directory, stage.file_skeleton, &status); - fake_build_execute_process_script(data, data_build, data_build.setting.process_pre, stage.file_process_pre, &status); + data->child = fake_build_execute_process_script(*data, data_build, data_build.setting.process_pre, stage.file_process_pre, &status); - fake_build_copy(data, mode, "setting files", data.path_data_settings, data.path_build_settings, data_build.setting.build_sources_setting, stage.file_sources_settings, 0, &status); + fake_build_copy(*data, mode, "setting files", data->path_data_settings, data->path_build_settings, data_build.setting.build_sources_setting, stage.file_sources_settings, 0, &status); if (data_build.setting.build_language == fake_build_language_type_bash) { - fake_build_libraries_script(data, data_build, mode, stage.file_libraries_script, &status); + fake_build_libraries_script(*data, data_build, mode, stage.file_libraries_script, &status); - fake_build_programs_script(data, data_build, mode, stage.file_programs_script, &status); + fake_build_programs_script(*data, data_build, mode, stage.file_programs_script, &status); if (data_build.setting.build_script) { - fake_build_copy(data, mode, "scripts", data.path_sources_script, data.path_build_programs_script, data_build.setting.build_sources_script, stage.file_sources_script, 0, &status); + fake_build_copy(*data, mode, "scripts", data->path_sources_script, data->path_build_programs_script, data_build.setting.build_sources_script, stage.file_sources_script, 0, &status); } } else { if (data_build.setting.build_sources_headers.used) { - const f_string_static_t *path_sources = &data.path_sources; + const f_string_static_t *path_sources = &data->path_sources; if (data_build.setting.path_standard) { - path_sources = &data.path_sources_c; + path_sources = &data->path_sources_c; if (data_build.setting.build_language == fake_build_language_type_cpp) { - path_sources = &data.path_sources_cpp; + path_sources = &data->path_sources_cpp; } } - else if (data.parameters[fake_parameter_path_sources].result != f_console_result_additional) { + else if (data->parameters[fake_parameter_path_sources].result != f_console_result_additional) { path_sources = &data_build.setting.path_sources; } const f_string_length_t path_sources_base_length = path_sources->used; f_string_static_t path_headers = f_string_static_t_initialize; - f_string_length_t directory_headers_length = data.path_build_includes.used + data_build.setting.path_headers.used; + f_string_length_t directory_headers_length = data->path_build_includes.used + data_build.setting.path_headers.used; char directory_headers[directory_headers_length + 1]; if (data_build.setting.path_headers.used > 0) { - memcpy(directory_headers, data.path_build_includes.string, data.path_build_includes.used); - memcpy(directory_headers + data.path_build_includes.used, data_build.setting.path_headers.string, data_build.setting.path_headers.used); + memcpy(directory_headers, data->path_build_includes.string, data->path_build_includes.used); + memcpy(directory_headers + data->path_build_includes.used, data_build.setting.path_headers.string, data_build.setting.path_headers.used); directory_headers[directory_headers_length] = 0; @@ -2657,7 +2677,7 @@ extern "C" { path_headers.size = directory_headers_length + 1; } else { - memcpy(directory_headers, data.path_build_includes.string, data.path_build_includes.used); + memcpy(directory_headers, data->path_build_includes.string, data->path_build_includes.used); directory_headers[directory_headers_length] = 0; @@ -2666,29 +2686,29 @@ extern "C" { path_headers.size = directory_headers_length + 1; } - fake_build_copy(data, mode, "header files", *path_sources, path_headers, data_build.setting.build_sources_headers, stage.file_sources_headers, data_build.setting.path_headers_preserve ? path_sources_base_length : 0, &status); + fake_build_copy(*data, mode, "header files", *path_sources, path_headers, data_build.setting.build_sources_headers, stage.file_sources_headers, data_build.setting.path_headers_preserve ? path_sources_base_length : 0, &status); } if (data_build.setting.build_shared) { - fake_build_library_shared(data, data_build, mode, stage.file_libraries_shared, &status); + data->child = fake_build_library_shared(*data, data_build, mode, stage.file_libraries_shared, &status); - fake_build_program_shared(data, data_build, mode, stage.file_programs_shared, &status); + data->child = fake_build_program_shared(*data, data_build, mode, stage.file_programs_shared, &status); } if (data_build.setting.build_static) { - fake_build_objects_static(data, data_build, mode, stage.file_objects_static, &status); + data->child = fake_build_objects_static(*data, data_build, mode, stage.file_objects_static, &status); - fake_build_library_static(data, data_build, mode, stage.file_libraries_static, &status); + data->child = fake_build_library_static(*data, data_build, mode, stage.file_libraries_static, &status); - fake_build_program_static(data, data_build, mode, stage.file_programs_static, &status); + data->child = fake_build_program_static(*data, data_build, mode, stage.file_programs_static, &status); } if (data_build.setting.build_script) { - fake_build_copy(data, mode, "scripts", data.path_sources_script, data.path_build_programs_script, data_build.setting.build_sources_script, stage.file_sources_script, 0, &status); + fake_build_copy(*data, mode, "scripts", data->path_sources_script, data->path_build_programs_script, data_build.setting.build_sources_script, stage.file_sources_script, 0, &status); } } - fake_build_execute_process_script(data, data_build, data_build.setting.process_post, stage.file_process_post, &status); + fake_build_execute_process_script(*data, data_build, data_build.setting.process_post, stage.file_process_post, &status); fake_macro_build_data_delete_simple(data_build); fake_macro_build_stage_t_delete_simple(stage); @@ -2703,19 +2723,21 @@ extern "C" { #endif // _di_fake_build_operate_ #ifndef _di_fake_build_programs_script_ - void fake_build_programs_script(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return; + int fake_build_programs_script(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return data.child; // @todo needs to perform some sort of regex replace on the program scripts. fake_build_touch(data, file_stage, status); + + return 0; } #endif // _di_fake_build_programs_script_ #ifndef _di_fake_build_program_shared_ - void fake_build_program_shared(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return; - if (!data_build.setting.build_sources_program.used) return; + int fake_build_program_shared(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return data.child; + if (!data_build.setting.build_sources_program.used) return 0; if (data.error.verbosity != f_console_verbosity_quiet) { fprintf(data.output.stream, "%c", f_string_eol[0]); @@ -2799,23 +2821,25 @@ extern "C" { fll_error_print(data.error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); f_macro_string_dynamics_t_delete_simple(arguments); - return; + return 0; } - fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status); + int result = fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status); f_macro_string_dynamics_t_delete_simple(arguments); - if (F_status_is_error_not(*status)) { + if (F_status_is_error_not(*status) && *status != F_child) { fake_build_touch(data, file_stage, status); } + + return result; } #endif // _di_fake_build_program_shared_ #ifndef _di_fake_build_program_static_ - void fake_build_program_static(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { - if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return; - if (!data_build.setting.build_sources_program.used) return; + int fake_build_program_static(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) { + if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true || *status == F_child) return data.child; + if (!data_build.setting.build_sources_program.used) return 0; if (data.error.verbosity != f_console_verbosity_quiet) { fprintf(data.output.stream, "%c", f_string_eol[0]); @@ -2915,16 +2939,18 @@ extern "C" { fll_error_print(data.error, F_status_set_fine(*status), "fll_execute_arguments_add", F_true); f_macro_string_dynamics_t_delete_simple(arguments); - return; + return 0; } - fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status); + int result = fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status); f_macro_string_dynamics_t_delete_simple(arguments); - if (F_status_is_error_not(*status)) { + if (F_status_is_error_not(*status) && *status != F_child) { fake_build_touch(data, file_stage, status); } + + return result; } #endif // _di_fake_build_program_static_ diff --git a/level_3/fake/c/private-build.h b/level_3/fake/c/private-build.h index c88a2b4..c248381 100644 --- a/level_3/fake/c/private-build.h +++ b/level_3/fake/c/private-build.h @@ -483,15 +483,16 @@ extern "C" { * @param file_stage * The specific stage file path. * @param status - * The return status. - * - * @return * F_none on success. * * Status codes (with error bit) are returned on any problem. + * + * @return + * The return code of the execution process. + * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_execute_process_script_ - extern void fake_build_execute_process_script(const fake_data_t data, const fake_build_data_t data_build, const f_string_static_t process_script, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; + extern int fake_build_execute_process_script(const fake_data_t data, const fake_build_data_t data_build, const f_string_static_t process_script, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_build_execute_process_script_ /** @@ -525,15 +526,16 @@ extern "C" { * @param file_stage * The specific stage file path. * @param status - * The return status. - * - * @return * F_none on success. * * Status codes (with error bit) are returned on any problem. + * + * @return + * The return code of the execution process. + * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_libraries_script_ - extern void fake_build_libraries_script(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; + extern int fake_build_libraries_script(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_build_libraries_script_ /** @@ -548,15 +550,16 @@ extern "C" { * @param file_stage * The specific stage file path. * @param status - * The return status. - * - * @return * F_none on success. * * Status codes (with error bit) are returned on any problem. + * + * @return + * The return code of the execution process. + * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_library_shared_ - extern void fake_build_library_shared(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; + extern int fake_build_library_shared(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_build_library_shared_ /** @@ -571,15 +574,16 @@ extern "C" { * @param file_stage * The specific stage file path. * @param status - * The return status. - * - * @return * F_none on success. * * Status codes (with error bit) are returned on any problem. + * + * @return + * The return code of the execution process. + * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_library_static_ - extern void fake_build_library_static(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; + extern int fake_build_library_static(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_build_library_static_ /** @@ -711,25 +715,26 @@ extern "C" { * @param file_stage * The specific stage file path. * @param status - * The return status. - * - * @return * F_none on success. * * Status codes (with error bit) are returned on any problem. + * + * @return + * The return code of the execution process. + * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_objects_static_ - extern void fake_build_objects_static(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; + extern int fake_build_objects_static(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_build_objects_static_ /** * Execute the build operation. * - * @param data - * The program data. * @param setting_file * The name of the settings file to use. * If setting_file.used is 0, then the default or program parameter supplied file is used. + * @param data + * The program data. * * @return * F_none on success. @@ -737,7 +742,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_build_operate_ - extern f_return_status fake_build_operate(const fake_data_t data, const f_string_static_t setting_file) f_gcc_attribute_visibility_internal; + extern f_return_status fake_build_operate(const f_string_static_t setting_file, fake_data_t *data) f_gcc_attribute_visibility_internal; #endif // _di_fake_build_operate_ /** @@ -752,15 +757,16 @@ extern "C" { * @param file_stage * The specific stage file path. * @param status - * The return status. - * - * @return * F_none on success. * * Status codes (with error bit) are returned on any problem. + * + * @return + * The return code of the execution process. + * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_programs_script_ - extern void fake_build_programs_script(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; + extern int fake_build_programs_script(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_build_programs_script_ /** @@ -775,15 +781,16 @@ extern "C" { * @param file_stage * The specific stage file path. * @param status - * The return status. - * - * @return * F_none on success. * * Status codes (with error bit) are returned on any problem. + * + * @return + * The return code of the execution process. + * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_program_shared_ - extern void fake_build_program_shared(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; + extern int fake_build_program_shared(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_build_program_shared_ /** @@ -798,15 +805,16 @@ extern "C" { * @param file_stage * The specific stage file path. * @param status - * The return status. - * - * @return * F_none on success. * * Status codes (with error bit) are returned on any problem. + * + * @return + * The return code of the execution process. + * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_build_program_static_ - extern void fake_build_program_static(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; + extern int fake_build_program_static(const fake_data_t data, const fake_build_data_t data_build, const f_mode_t mode, const f_string_static_t file_stage, f_status_t *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_build_program_static_ /** diff --git a/level_3/fake/c/private-fake.c b/level_3/fake/c/private-fake.c index 9969f72..9e56f0f 100644 --- a/level_3/fake/c/private-fake.c +++ b/level_3/fake/c/private-fake.c @@ -41,12 +41,16 @@ extern "C" { f_signal_set_empty(&signals.block); f_signal_set_fill(&signals.block_not); - *status = fll_execute_program_environment(program.string, arguments, &signals, environment.names, environment.values, &return_code); + *status = fll_execute_program_environment(program.string, arguments, environment.names, environment.values, &signals, &return_code); if (fake_signal_received(data)) { *status = F_status_set_error(F_signal); return 0; } + + if (*status == F_child) { + return return_code; + } } else { *status = F_status_set_error(F_file_found_not); diff --git a/level_3/fake/c/private-make.c b/level_3/fake/c/private-make.c index 1b984e0..67ce461 100644 --- a/level_3/fake/c/private-make.c +++ b/level_3/fake/c/private-make.c @@ -1048,15 +1048,15 @@ extern "C" { #endif // _di_fake_make_load_parameters_ #ifndef _di_fake_make_operate_ - f_return_status fake_make_operate(const fake_data_t data) { + f_return_status fake_make_operate(fake_data_t *data) { - if (fake_signal_received(data)) { + if (fake_signal_received(*data)) { return F_signal; } - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.output.stream, "%c", f_string_eol[0]); - fl_color_print(data.output.stream, data.context.set.important, "Making project.%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->output.stream, "%c", f_string_eol[0]); + fl_color_print(data->output.stream, data->context.set.important, "Making project.%c", f_string_eol[0]); } f_status_t status = F_none; @@ -1068,11 +1068,11 @@ extern "C" { f_macro_string_dynamics_new(status, data_make.path.stack, f_memory_default_allocation_step); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_macro_string_dynamics_new", F_true); + fll_error_print(data->error, F_status_set_fine(status), "f_macro_string_dynamics_new", F_true); return status; } - if (fake_signal_received(data)) { + if (fake_signal_received(*data)) { fake_macro_make_data_t_delete_simple(data_make); return F_signal; } @@ -1080,7 +1080,7 @@ extern "C" { status = f_path_current(F_true, &data_make.path.stack.array[0]); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_path_current", F_true); + fll_error_print(data->error, F_status_set_fine(status), "f_path_current", F_true); fake_macro_make_data_t_delete_simple(data_make); return status; @@ -1089,7 +1089,7 @@ extern "C" { status = f_directory_open(data_make.path.stack.array[0].string, F_false, &data_make.path.top.id); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_directory_open", F_true); + fll_error_print(data->error, F_status_set_fine(status), "f_directory_open", F_true); fake_macro_make_data_t_delete_simple(data_make); return status; @@ -1097,11 +1097,11 @@ extern "C" { data_make.path.stack.used = 1; - f_macro_mode_t_set_default_umask(mode, data.umask); + f_macro_mode_t_set_default_umask(mode, data->umask); - fake_make_load_parameters(data, &data_make, &status); + fake_make_load_parameters(*data, &data_make, &status); - fake_make_load_fakefile(data, &data_make, &status); + fake_make_load_fakefile(*data, &data_make, &status); if (F_status_is_error(status)) { fake_macro_make_data_t_delete_simple(data_make); @@ -1116,15 +1116,15 @@ extern "C" { if (data_make.setting_make.fail == fake_make_operation_fail_type_exit) { data_make.error.prefix = fll_error_print_error; - data_make.error.context = data.context.set.error; - data_make.error.notable = data.context.set.notable; + data_make.error.context = data->context.set.error; + data_make.error.notable = data->context.set.notable; data_make.error.to.stream = f_type_error; data_make.error.to.id = f_type_descriptor_error; } else if (data_make.setting_make.fail == fake_make_operation_fail_type_warn) { data_make.error.prefix = fll_error_print_warning; - data_make.error.context = data.context.set.warning; - data_make.error.notable = data.context.set.notable; + data_make.error.context = data->context.set.warning; + data_make.error.notable = data->context.set.notable; data_make.error.to.stream = f_type_warning; data_make.error.to.id = f_type_descriptor_warning; } @@ -1133,7 +1133,13 @@ extern "C" { data_make.error.to.id = -1; } - fake_make_operate_section(data, data_make.main, &data_make, §ion_stack, &status); + { + const int result = fake_make_operate_section(data_make.main, data, &data_make, §ion_stack, &status); + + if (status == F_child) { + data->child = result; + } + } if (data_make.path.current.stream) { f_file_stream_close(F_true, &data_make.path.current); @@ -1142,13 +1148,13 @@ extern "C" { { f_status_t status_path = f_path_change_at(data_make.path.top.id); - if (F_status_is_error(status_path) && data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "%c", f_string_eol[0]); - fl_color_print(data.output.stream, data.context.set.warning, "%sFailed change back to orignal path '", fll_error_print_warning); - fl_color_print(data.output.stream, data.context.set.notable, "%s", data_make.path.stack.array[0].string); - fl_color_print(data.output.stream, data.context.set.warning, "', status code = "); - fl_color_print(data.output.stream, data.context.set.notable, "%llu", F_status_set_fine(status_path)); - fl_color_print(data.output.stream, data.context.set.warning, ".%c", f_string_eol[0]); + if (F_status_is_error(status_path) && data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "%c", f_string_eol[0]); + fl_color_print(data->output.stream, data->context.set.warning, "%sFailed change back to orignal path '", fll_error_print_warning); + fl_color_print(data->output.stream, data->context.set.notable, "%s", data_make.path.stack.array[0].string); + fl_color_print(data->output.stream, data->context.set.warning, "', status code = "); + fl_color_print(data->output.stream, data->context.set.notable, "%llu", F_status_set_fine(status_path)); + fl_color_print(data->output.stream, data->context.set.warning, ".%c", f_string_eol[0]); } } @@ -1883,19 +1889,19 @@ extern "C" { #endif // _di_fake_make_operate_expand_environment_ #ifndef _di_fake_make_operate_section_ - void fake_make_operate_section(const fake_data_t data, const f_array_length_t id_section, fake_make_data_t *data_make, f_string_lengths_t *section_stack, f_status_t *status) { - if (F_status_is_error(*status)) return; + int fake_make_operate_section(const f_array_length_t id_section, fake_data_t *data, fake_make_data_t *data_make, f_string_lengths_t *section_stack, f_status_t *status) { + if (F_status_is_error(*status) || *status == F_child) return data->child; - if (fake_signal_received(data)) { + if (fake_signal_received(*data)) { *status = F_status_set_error(F_signal); - return; + return 0; } if (id_section > data_make->fakefile.used) { *status = F_status_set_error(F_parameter); fll_error_print(data_make->error, F_parameter, "fake_make_operate_section", F_true); - return; + return 0; } // add the operation id to the operation stack. @@ -1904,7 +1910,7 @@ extern "C" { if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "fl_string_lengths_increase_by", F_true); - return; + return 0; } } @@ -1914,21 +1920,21 @@ extern "C" { const f_fss_named_t *section = &data_make->fakefile.array[id_section]; - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.output.stream, "%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->output.stream, "%c", f_string_eol[0]); - fl_color_print(data.output.stream, data.context.set.important, "Processing Section '"); + fl_color_print(data->output.stream, data->context.set.important, "Processing Section '"); - fl_color_print_code(data.output.stream, *data.context.set.notable.before); - f_print_dynamic_partial(data.output.stream, data_make->buffer, section->name); - fl_color_print_code(data.output.stream, *data.context.set.notable.after); + fl_color_print_code(data->output.stream, *data->context.set.notable.before); + f_print_dynamic_partial(data->output.stream, data_make->buffer, section->name); + fl_color_print_code(data->output.stream, *data->context.set.notable.after); - fl_color_print(data.output.stream, data.context.set.important, "'.%c", f_string_eol[0]); + fl_color_print(data->output.stream, data->context.set.important, "'.%c", f_string_eol[0]); } if (!section->objects.used) { section_stack->used--; - return; + return 0; } const f_string_static_t operations_name[] = { @@ -2053,7 +2059,7 @@ extern "C" { operation = 0; operation_name = 0; - if (fake_signal_received(data)) { + if (fake_signal_received(*data)) { *status = F_status_set_error(F_signal); break; } @@ -2068,13 +2074,13 @@ extern "C" { } // for if (!operation) { - fake_print_message_section_operation_unknown(data, data_make->error, data_make->buffer, section->name, section->objects.array[i]); + fake_print_message_section_operation_unknown(*data, data_make->error, data_make->buffer, section->name, section->objects.array[i]); *status = F_status_set_error(F_valid_not); } else if (operation == fake_make_operation_type_operate) { if (section_stack->used == fake_make_section_stack_max) { - fake_print_message_section_operation_stack_max(data, data_make->error, data_make->buffer, section->name, section->objects.array[i], fake_make_section_stack_max); + fake_print_message_section_operation_stack_max(*data, data_make->error, data_make->buffer, section->name, section->objects.array[i], fake_make_section_stack_max); *status = F_status_set_error(F_recurse); } @@ -2083,7 +2089,7 @@ extern "C" { if (F_status_is_error_not(*status)) { operations[i] = operation; - fake_make_operate_expand(data, section->name, operation, *operation_name, section->contents.array[i], section->quotess.array[i], data_make, &arguments[i], status); + fake_make_operate_expand(*data, section->name, operation, *operation_name, section->contents.array[i], section->quotess.array[i], data_make, &arguments[i], status); } if (operation_if == fake_make_operation_if_type_true_next) { @@ -2096,7 +2102,7 @@ extern "C" { operation_if = fake_make_operation_if_type_false_always; } - fake_make_operate_validate(data, section->name, operation, *operation_name, arguments[i], &operation_if, data_make, section_stack, status); + fake_make_operate_validate(*data, section->name, operation, *operation_name, arguments[i], &operation_if, data_make, section_stack, status); if (F_status_is_error_not(*status)) { @@ -2113,7 +2119,11 @@ extern "C" { continue; } - fake_make_operate_process(data, section->name, operation, *operation_name, arguments[i], success, &operation_if, data_make, section_stack, status); + const int result = fake_make_operate_process(section->name, operation, *operation_name, arguments[i], success, &operation_if, data, data_make, section_stack, status); + + if (*status == F_child) { + return result; + } } else { @@ -2173,13 +2183,13 @@ extern "C" { if (F_status_set_fine(*status) == F_signal_abort && !section_stack->used) { data_make->setting_make.fail = fake_make_operation_fail_type_exit; data_make->error.prefix = fll_error_print_error; - data_make->error.context = data.context.set.error; - data_make->error.notable = data.context.set.notable; + data_make->error.context = data->context.set.error; + data_make->error.notable = data->context.set.notable; data_make->error.to.stream = f_type_error; data_make->error.to.id = f_type_descriptor_error; } - fake_print_message_section_operation_failed(data, data_make->error, data_make->buffer, section->name, section->objects.array[i]); + fake_print_message_section_operation_failed(*data, data_make->error, data_make->buffer, section->name, section->objects.array[i]); // F_signal_abort is used by the break section operation. if (F_status_set_fine(*status) == F_signal_abort) { @@ -2226,12 +2236,12 @@ extern "C" { f_macro_string_dynamics_t_delete_simple(arguments[i]); } // for - return; + return 0; } if (i == section->objects.used && (operation_if == fake_make_operation_if_type_true_next || operation_if == fake_make_operation_if_type_false_next || operation_if == fake_make_operation_if_type_else_true || operation_if == fake_make_operation_if_type_else_false)) { - if (data.error.verbosity != f_console_verbosity_quiet && data_make->error.to.stream) { + if (data->error.verbosity != f_console_verbosity_quiet && data_make->error.to.stream) { const char *type_name = 0; if (operation_if == fake_make_operation_if_type_true_next || operation_if == fake_make_operation_if_type_false_next) { @@ -2247,7 +2257,7 @@ extern "C" { fl_color_print(data_make->error.to.stream, data_make->error.context, "' at end of section.%c", f_string_eol[0]); } - fake_print_message_section_operation_failed(data, data_make->error, data_make->buffer, section->name, section->objects.array[section->objects.used - 1]); + fake_print_message_section_operation_failed(*data, data_make->error, data_make->buffer, section->name, section->objects.array[section->objects.used - 1]); *status = F_status_set_error(F_failure); } @@ -2262,22 +2272,29 @@ extern "C" { } // for section_stack->used--; + + return 0; } #endif // _di_fake_make_operate_section_ #ifndef _di_fake_make_operate_process_ - void fake_make_operate_process(const fake_data_t data, const f_string_range_t section_name, const uint8_t operation, const f_string_static_t operation_name, const f_string_dynamics_t arguments, const bool success, uint8_t *operation_if, fake_make_data_t *data_make, f_string_lengths_t *section_stack, f_status_t *status) { + int fake_make_operate_process(const f_string_range_t section_name, const uint8_t operation, const f_string_static_t operation_name, const f_string_dynamics_t arguments, const bool success, uint8_t *operation_if, fake_data_t *data, fake_make_data_t *data_make, f_string_lengths_t *section_stack, f_status_t *status) { + if (*status == F_child) return data->child; if (operation == fake_make_operation_type_index) { - int return_code = fake_execute(data, data_make->environment, data_make->setting_build.build_indexer, arguments, status); + const f_status_t result = fake_execute(*data, data_make->environment, data_make->setting_build.build_indexer, arguments, status); if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "fake_execute", F_true); } - fake_make_operate_process_return(data, return_code, data_make, status); + if (*status == F_child) { + return result; + } - return; + fake_make_operate_process_return(*data, result, data_make, status); + + return 0; } if (operation == fake_make_operation_type_break) { @@ -2289,54 +2306,54 @@ extern "C" { *status = F_status_set_error(F_signal_abort); } else { - return; + return 0; } - if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Breaking as '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", arguments.used ? arguments.array[0].string : fake_make_operation_argument_success); - fprintf(data.output.stream, "'.%c", f_string_eol[0]); + if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Breaking as '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", arguments.used ? arguments.array[0].string : fake_make_operation_argument_success); + fprintf(data->output.stream, "'.%c", f_string_eol[0]); } - return; + return 0; } if (operation == fake_make_operation_type_build) { f_string_static_t stub = f_string_static_t_initialize; - *status = fake_build_operate(data, arguments.used ? arguments.array[0] : stub); + *status = fake_build_operate(arguments.used ? arguments.array[0] : stub, data); if (F_status_set_fine(*status) == F_signal) { *status = F_status_set_error(F_signal); - return; + return 0; } if (F_status_is_error(*status)) { - fake_make_operate_process_return(data, 1, data_make, status); + fake_make_operate_process_return(*data, 1, data_make, status); } else { - fake_make_operate_process_return(data, 0, data_make, status); + fake_make_operate_process_return(*data, 0, data_make, status); } - return; + return 0; } if (operation == fake_make_operation_type_clean) { - *status = fake_clean_operate(data); + *status = fake_clean_operate(*data); if (F_status_set_fine(*status) == F_signal) { *status = F_status_set_error(F_signal); - return; + return 0; } if (F_status_is_error(*status)) { - fake_make_operate_process_return(data, 1, data_make, status); + fake_make_operate_process_return(*data, 1, data_make, status); } else { - fake_make_operate_process_return(data, 0, data_make, status); + fake_make_operate_process_return(*data, 0, data_make, status); } - return; + return 0; } if (operation == fake_make_operation_type_clone) { @@ -2347,8 +2364,8 @@ extern "C" { f_string_length_t destination_length = 0; - if (data.error.verbosity == f_console_verbosity_verbose) { - recurse.output = data.output; + if (data->error.verbosity == f_console_verbosity_verbose) { + recurse.output = data->output; recurse.verbose = fake_verbose_print_clone; } @@ -2361,7 +2378,7 @@ extern "C" { if (F_status_is_error(status_file)) { fll_error_file_print(data_make->error, F_status_set_fine(status_file), "f_directory_is", F_true, arguments.array[1].string, "identify", fll_error_file_type_directory); *status = F_status_set_error(F_failure); - return; + return 0; } if (status_file == F_false || status_file == F_file_found_not) { @@ -2405,12 +2422,12 @@ extern "C" { fll_error_file_print(data_make->error, F_status_set_fine(status_file), "f_file_clone", F_true, arguments.array[i].string, "clone", fll_error_file_type_file); *status = F_status_set_error(F_failure); } - else if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Cloned '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", arguments.array[i].string); - fprintf(data.output.stream, "' to '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", destination); - fprintf(data.output.stream, "'.%c", f_string_eol[0]); + else if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Cloned '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", arguments.array[i].string); + fprintf(data->output.stream, "' to '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", destination); + fprintf(data->output.stream, "'.%c", f_string_eol[0]); } } else if (F_status_is_error(status_file)) { @@ -2420,19 +2437,23 @@ extern "C" { } } // for - return; + return 0; } if (operation == fake_make_operation_type_compile) { - int return_code = fake_execute(data, data_make->environment, data_make->setting_build.build_compiler, arguments, status); + const int result = fake_execute(*data, data_make->environment, data_make->setting_build.build_compiler, arguments, status); if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "fake_execute", F_true); } - fake_make_operate_process_return(data, return_code, data_make, status); + if (*status == F_child) { + return result; + } - return; + fake_make_operate_process_return(*data, result, data_make, status); + + return 0; } if (operation == fake_make_operation_type_copy) { @@ -2445,10 +2466,10 @@ extern "C" { f_mode_t mode = f_mode_t_initialize; - f_macro_mode_t_set_default_umask(mode, data.umask); + f_macro_mode_t_set_default_umask(mode, data->umask); - if (data.error.verbosity == f_console_verbosity_verbose) { - recurse.output = data.output; + if (data->error.verbosity == f_console_verbosity_verbose) { + recurse.output = data->output; recurse.verbose = fake_verbose_print_copy; } @@ -2462,7 +2483,7 @@ extern "C" { fll_error_file_print(data_make->error, F_status_set_fine(status_file), "f_directory_is", F_true, arguments.array[1].string, "identify", fll_error_file_type_directory); *status = F_status_set_error(F_failure); - return; + return 0; } if (status_file == F_false || status_file == F_file_found_not) { @@ -2505,12 +2526,12 @@ extern "C" { fll_error_file_print(data_make->error, F_status_set_fine(status_file), "f_file_copy", F_true, arguments.array[i].string, "copy", fll_error_file_type_file); *status = F_status_set_error(F_failure); } - else if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Copied '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", arguments.array[i].string); - fprintf(data.output.stream, "' to '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", destination); - fprintf(data.output.stream, "'.%c", f_string_eol[0]); + else if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Copied '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", arguments.array[i].string); + fprintf(data->output.stream, "' to '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", destination); + fprintf(data->output.stream, "'.%c", f_string_eol[0]); } } else if (F_status_is_error(status_file)) { @@ -2520,7 +2541,7 @@ extern "C" { } } // for - return; + return 0; } if (operation == fake_make_operation_type_define) { @@ -2535,13 +2556,13 @@ extern "C" { if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "f_environment_set", F_true); } - else if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Defined environment variable '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", arguments.array[0].string); - fprintf(data.output.stream, "'.%c", f_string_eol[0]); + else if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Defined environment variable '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", arguments.array[0].string); + fprintf(data->output.stream, "'.%c", f_string_eol[0]); } - return; + return 0; } if (operation == fake_make_operation_type_delete || operation == fake_make_operation_type_deletes) { @@ -2555,22 +2576,22 @@ extern "C" { if (F_status_is_error(*status)) { if (F_status_set_fine(*status) == F_file_found_not) { - if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "%c", f_string_eol[0]); - fl_color_print(data.output.stream, data.context.set.warning, "%sthe file '", fll_error_print_warning); - fl_color_print(data.output.stream, data.context.set.notable, "%s", arguments.array[i].string); - fl_color_print(data.output.stream, data.context.set.warning, "' was not found.%c", f_string_eol[0]); + if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "%c", f_string_eol[0]); + fl_color_print(data->output.stream, data->context.set.warning, "%sthe file '", fll_error_print_warning); + fl_color_print(data->output.stream, data->context.set.notable, "%s", arguments.array[i].string); + fl_color_print(data->output.stream, data->context.set.warning, "' was not found.%c", f_string_eol[0]); } *status = F_none; } else { fll_error_file_print(data_make->error, F_status_set_fine(*status), "f_file_stat", F_true, arguments.array[i].string, "delete", fll_error_file_type_file); - return; + return 0; } } else if (f_macro_file_type_is_directory(file_stat.st_mode)) { - if (data.error.verbosity == f_console_verbosity_verbose) { + if (data->error.verbosity == f_console_verbosity_verbose) { *status = f_directory_remove_custom(arguments.array[i].string, recursion_max, F_false, fake_clean_remove_recursively_verbosely); } else { @@ -2578,10 +2599,10 @@ extern "C" { } if (F_status_set_fine(*status) == F_file_found_not) { - if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "The directory '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", arguments.array[i].string); - fprintf(data.output.stream, "' does not exist.%c", f_string_eol[0]); + if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "The directory '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", arguments.array[i].string); + fprintf(data->output.stream, "' does not exist.%c", f_string_eol[0]); } *status = F_none; @@ -2589,22 +2610,22 @@ extern "C" { if (F_status_is_error(*status)) { fll_error_file_print(data_make->error, F_status_set_fine(*status), "f_directory_remove", F_true, arguments.array[i].string, "delete", fll_error_file_type_directory); - return; + return 0; } - else if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Removed '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", arguments.array[i].string); - fprintf(data.output.stream, "'.%c", f_string_eol[0]); + else if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Removed '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", arguments.array[i].string); + fprintf(data->output.stream, "'.%c", f_string_eol[0]); } } else { *status = f_file_remove(arguments.array[i].string); if (F_status_set_fine(*status) == F_file_found_not) { - if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "The file '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", arguments.array[i].string); - fprintf(data.output.stream, "' does not exist.%c", f_string_eol[0]); + if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "The file '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", arguments.array[i].string); + fprintf(data->output.stream, "' does not exist.%c", f_string_eol[0]); } *status = F_none; @@ -2612,17 +2633,17 @@ extern "C" { if (F_status_is_error(*status)) { fll_error_file_print(data_make->error, F_status_set_fine(*status), "f_file_remove", F_true, arguments.array[i].string, "delete", fll_error_file_type_file); - return; + return 0; } - else if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Removed '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", arguments.array[i].string); - fprintf(data.output.stream, "'.%c", f_string_eol[0]); + else if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Removed '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", arguments.array[i].string); + fprintf(data->output.stream, "'.%c", f_string_eol[0]); } } } // for - return; + return 0; } if (operation == fake_make_operation_type_else) { @@ -2634,7 +2655,7 @@ extern "C" { *operation_if = fake_make_operation_if_type_else_true; } - return; + return 0; } if (operation == fake_make_operation_type_exit) { @@ -2648,22 +2669,22 @@ extern "C" { // forcing exit forces fail mode. data_make->setting_make.fail = fake_make_operation_fail_type_exit; data_make->error.prefix = fll_error_print_error; - data_make->error.context = data.context.set.error; - data_make->error.notable = data.context.set.notable; + data_make->error.context = data->context.set.error; + data_make->error.notable = data->context.set.notable; data_make->error.to.stream = f_type_error; data_make->error.to.id = f_type_descriptor_error; } else { - return; + return 0; } - if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Exiting as '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", arguments.used ? arguments.array[0].string : fake_make_operation_argument_success); - fprintf(data.output.stream, "'.%c", f_string_eol[0]); + if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Exiting as '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", arguments.used ? arguments.array[0].string : fake_make_operation_argument_success); + fprintf(data->output.stream, "'.%c", f_string_eol[0]); } - return; + return 0; } if (operation == fake_make_operation_type_fail) { @@ -2671,16 +2692,16 @@ extern "C" { if (fl_string_dynamic_compare_string(fake_make_operation_argument_exit, arguments.array[0], fake_make_operation_argument_exit_length) == F_equal_to) { data_make->setting_make.fail = fake_make_operation_fail_type_exit; data_make->error.prefix = fll_error_print_error; - data_make->error.context = data.context.set.error; - data_make->error.notable = data.context.set.notable; + data_make->error.context = data->context.set.error; + data_make->error.notable = data->context.set.notable; data_make->error.to.stream = f_type_error; data_make->error.to.id = f_type_descriptor_error; } else if (fl_string_dynamic_compare_string(fake_make_operation_argument_warn, arguments.array[0], fake_make_operation_argument_warn_length) == F_equal_to) { data_make->setting_make.fail = fake_make_operation_fail_type_warn; data_make->error.prefix = fll_error_print_warning; - data_make->error.context = data.context.set.warning; - data_make->error.notable = data.context.set.notable; + data_make->error.context = data->context.set.warning; + data_make->error.notable = data->context.set.notable; data_make->error.to.stream = f_type_warning; data_make->error.to.id = f_type_descriptor_warning; } @@ -2690,41 +2711,41 @@ extern "C" { data_make->error.to.id = -1; } - if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Set failure state to '"); + if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Set failure state to '"); if (data_make->setting_make.fail == fake_make_operation_fail_type_exit) { - fl_color_print(data.output.stream, data.context.set.notable, "%s", fake_make_operation_argument_exit); + fl_color_print(data->output.stream, data->context.set.notable, "%s", fake_make_operation_argument_exit); } else if (data_make->setting_make.fail == fake_make_operation_fail_type_warn) { - fl_color_print(data.output.stream, data.context.set.notable, "%s", fake_make_operation_argument_warn); + fl_color_print(data->output.stream, data->context.set.notable, "%s", fake_make_operation_argument_warn); } else if (data_make->setting_make.fail == fake_make_operation_fail_type_ignore) { - fl_color_print(data.output.stream, data.context.set.notable, "%s", fake_make_operation_argument_ignore); + fl_color_print(data->output.stream, data->context.set.notable, "%s", fake_make_operation_argument_ignore); } - fprintf(data.output.stream, "'.%c", f_string_eol[0]); + fprintf(data->output.stream, "'.%c", f_string_eol[0]); } - return; + return 0; } if (operation == fake_make_operation_type_group) { gid_t id = 0; - *status = fake_make_get_id_group(data, data_make->error, arguments.array[0], &id); - if (F_status_is_error(*status)) return; + *status = fake_make_get_id_group(*data, data_make->error, arguments.array[0], &id); + if (F_status_is_error(*status)) return 0; f_status_t status_file = F_none; for (f_array_length_t i = 1; i < arguments.used; i++) { - status_file = fake_make_assure_inside_project(data, arguments.array[i], data_make); + status_file = fake_make_assure_inside_project(*data, arguments.array[i], data_make); if (F_status_is_error(status_file)) { *status = status_file; - fake_print_message_section_operation_path_outside(data, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); + fake_print_message_section_operation_path_outside(*data, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); continue; } @@ -2736,34 +2757,34 @@ extern "C" { fll_error_file_print(data_make->error, F_status_set_fine(*status), "f_file_role_change", F_true, arguments.array[i].string, "change group of", fll_error_file_type_file); } - else if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Changed group of '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", arguments.array[i].string); - fprintf(data.output.stream, "' to "); - fl_color_print(data.output.stream, data.context.set.notable, "%llu", id); - fprintf(data.output.stream, ".%c", f_string_eol[0]); + else if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Changed group of '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", arguments.array[i].string); + fprintf(data->output.stream, "' to "); + fl_color_print(data->output.stream, data->context.set.notable, "%llu", id); + fprintf(data->output.stream, ".%c", f_string_eol[0]); } } // for - return; + return 0; } if (operation == fake_make_operation_type_groups) { gid_t id = 0; - *status = fake_make_get_id_group(data, data_make->error, arguments.array[0], &id); - if (F_status_is_error(*status)) return; + *status = fake_make_get_id_group(*data, data_make->error, arguments.array[0], &id); + if (F_status_is_error(*status)) return 0; f_status_t status_file = F_none; for (f_array_length_t i = 1; i < arguments.used; i++) { - status_file = fake_make_assure_inside_project(data, arguments.array[i], data_make); + status_file = fake_make_assure_inside_project(*data, arguments.array[i], data_make); if (F_status_is_error(status_file)) { *status = status_file; - fake_print_message_section_operation_path_outside(data, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); + fake_print_message_section_operation_path_outside(*data, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); continue; } @@ -2775,16 +2796,16 @@ extern "C" { fll_error_file_print(data_make->error, F_status_set_fine(*status), "fll_file_role_change_all", F_true, arguments.array[i].string, "change group of", fll_error_file_type_file); } - else if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Changed group of '"); - fl_color_print(data.output.stream, data.context.set.notable, "%s", arguments.array[i].string); - fprintf(data.output.stream, "' to "); - fl_color_print(data.output.stream, data.context.set.notable, "%llu", id); - fprintf(data.output.stream, ".%c", f_string_eol[0]); + else if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Changed group of '"); + fl_color_print(data->output.stream, data->context.set.notable, "%s", arguments.array[i].string); + fprintf(data->output.stream, "' to "); + fl_color_print(data->output.stream, data->context.set.notable, "%llu", id); + fprintf(data->output.stream, ".%c", f_string_eol[0]); } } // for - return; + return 0; } if (operation == fake_make_operation_type_if) { @@ -2797,7 +2818,7 @@ extern "C" { *operation_if = fake_make_operation_if_type_false_next; } - return; + return 0; } if (*operation_if == fake_make_operation_if_type_if_failure) { @@ -2808,14 +2829,14 @@ extern "C" { *operation_if = fake_make_operation_if_type_true_next; } - return; + return 0; } if (*operation_if == fake_make_operation_if_type_if_group) { uid_t id = 0; - *status = fake_make_get_id_group(data, data_make->error, arguments.array[1], &id); - if (F_status_is_error(*status)) return; + *status = fake_make_get_id_group(*data, data_make->error, arguments.array[1], &id); + if (F_status_is_error(*status)) return 0; uid_t id_file = 0; @@ -2836,7 +2857,7 @@ extern "C" { } } // for - return; + return 0; } if (*operation_if == fake_make_operation_if_type_if_mode) { @@ -2852,11 +2873,11 @@ extern "C" { { uint8_t mode_replace = 0; - *status = fake_make_get_id_mode(data, data_make->error, arguments.array[2], &mode_rule, &mode_replace); + *status = fake_make_get_id_mode(*data, data_make->error, arguments.array[2], &mode_rule, &mode_replace); if (F_status_is_error(*status)) { *operation_if = fake_make_operation_if_type_false_always_next; - return; + return 0; } *status = f_file_mode_to_mode(mode_rule, &mode_match); @@ -2864,7 +2885,7 @@ extern "C" { if (F_status_is_error(*status)) { *operation_if = fake_make_operation_if_type_false_always_next; fll_error_print(data_make->error, F_status_set_fine(*status), "f_file_mode_to_mode", F_true); - return; + return 0; } } @@ -2896,14 +2917,14 @@ extern "C" { } } // for - return; + return 0; } if (*operation_if == fake_make_operation_if_type_if_owner) { uid_t id = 0; - *status = fake_make_get_id_owner(data, data_make->error, arguments.array[1], &id); - if (F_status_is_error(*status)) return; + *status = fake_make_get_id_owner(*data, data_make->error, arguments.array[1], &id); + if (F_status_is_error(*status)) return 0; uid_t id_file = 0; @@ -2925,7 +2946,7 @@ extern "C" { } } // for - return; + return 0; } if (*operation_if == fake_make_operation_if_type_if_is) { @@ -3011,7 +3032,7 @@ extern "C" { } } // for - return; + return 0; } if (*operation_if == fake_make_operation_if_type_if_exists) { @@ -3033,7 +3054,7 @@ extern "C" { } } // for - return; + return 0; } if (*operation_if == fake_make_operation_if_type_if_defined) { @@ -3053,7 +3074,7 @@ extern "C" { if (!data_make->setting_make.parameter.used) { *operation_if = fake_make_operation_if_type_false_next; - return; + return 0; } f_array_length_t i = 2; @@ -3079,7 +3100,7 @@ extern "C" { } // for } - return; + return 0; } if (*operation_if == fake_make_operation_if_type_if_equal) { @@ -3093,7 +3114,7 @@ extern "C" { } } // for - return; + return 0; } if (*operation_if == fake_make_operation_if_type_if_equal_not) { @@ -3114,7 +3135,7 @@ extern "C" { } // for } // for - return; + return 0; } if (*operation_if == fake_make_operation_if_type_if_greater || *operation_if == fake_make_operation_if_type_if_greater_equal || *operation_if == fake_make_operation_if_type_if_less || *operation_if == fake_make_operation_if_type_if_less_equal) { @@ -3243,26 +3264,26 @@ extern "C" { *status = F_status_set_error(F_failure); *operation_if = fake_make_operation_if_type_false_always_next; - if (data.error.verbosity != f_console_verbosity_quiet && data_make->error.to.stream) { - fprintf(data.output.stream, "%c", f_string_eol[0]); + if (data->error.verbosity != f_console_verbosity_quiet && data_make->error.to.stream) { + fprintf(data->output.stream, "%c", f_string_eol[0]); if ((i == 1 && number_left > f_number_t_size_unsigned) || (i > 1 && number_right > f_number_t_size_unsigned)) { - fl_color_print(data.error.to.stream, data_make->error.context, "%sThe number '", data_make->error.prefix); - fl_color_print(data.error.to.stream, data_make->error.notable, "%c%s", arguments.array[i].string); - fl_color_print(data.error.to.stream, data_make->error.context, "' may only be between the ranges -%llu to %llu.%c", f_number_t_size_unsigned, f_number_t_size_unsigned, f_string_eol[0]); + fl_color_print(data->error.to.stream, data_make->error.context, "%sThe number '", data_make->error.prefix); + fl_color_print(data->error.to.stream, data_make->error.notable, "%c%s", arguments.array[i].string); + fl_color_print(data->error.to.stream, data_make->error.context, "' may only be between the ranges -%llu to %llu.%c", f_number_t_size_unsigned, f_number_t_size_unsigned, f_string_eol[0]); } else { - fl_color_print(data.error.to.stream, data_make->error.context, "%sInvalid or unsupported number provided '", data_make->error.prefix); - fl_color_print(data.error.to.stream, data_make->error.notable, "%s", arguments.array[i].string); - fl_color_print(data.error.to.stream, data_make->error.context, "'.%c", f_string_eol[0]); + fl_color_print(data->error.to.stream, data_make->error.context, "%sInvalid or unsupported number provided '", data_make->error.prefix); + fl_color_print(data->error.to.stream, data_make->error.notable, "%s", arguments.array[i].string); + fl_color_print(data->error.to.stream, data_make->error.context, "'.%c", f_string_eol[0]); } } } - return; + return 0; } - return; + return 0; } if (operation == fake_make_operation_type_link) { @@ -3271,23 +3292,23 @@ extern "C" { if (F_status_is_error(*status)) { fll_error_file_print(data_make->error, F_status_set_fine(*status), "f_file_link", F_true, arguments.array[1].string, "create link", fll_error_file_type_file); } - else if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Created symbolic link from '"); - fl_color_print(data.error.to.stream, data.context.set.notable, "%s", arguments.array[1].string); - fprintf(data.output.stream, "' to '"); - fl_color_print(data.error.to.stream, data.context.set.notable, "%s", arguments.array[0].string); - fprintf(data.output.stream, "'.%c", f_string_eol[0]); + else if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Created symbolic link from '"); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s", arguments.array[1].string); + fprintf(data->output.stream, "' to '"); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s", arguments.array[0].string); + fprintf(data->output.stream, "'.%c", f_string_eol[0]); } - return; + return 0; } if (operation == fake_make_operation_type_mode) { f_file_mode_t mode_rule = 0; uint8_t replace = 0; - *status = fake_make_get_id_mode(data, data_make->error, arguments.array[0], &mode_rule, &replace); - if (F_status_is_error(*status)) return; + *status = fake_make_get_id_mode(*data, data_make->error, arguments.array[0], &mode_rule, &replace); + if (F_status_is_error(*status)) return 0; mode_t mode = 0; mode_t mode_file = 0; @@ -3316,24 +3337,24 @@ extern "C" { break; } - if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Changed mode of '"); - fl_color_print(data.error.to.stream, data.context.set.notable, "%s", arguments.array[i].string); - fprintf(data.output.stream, "' to "); - fl_color_print(data.error.to.stream, data.context.set.notable, "%#o", mode); - fprintf(data.output.stream, ".%c", f_string_eol[0]); + if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Changed mode of '"); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s", arguments.array[i].string); + fprintf(data->output.stream, "' to "); + fl_color_print(data->error.to.stream, data->context.set.notable, "%#o", mode); + fprintf(data->output.stream, ".%c", f_string_eol[0]); } } // for - return; + return 0; } if (operation == fake_make_operation_type_modes) { f_file_mode_t mode_rule = 0; uint8_t replace = 0; - *status = fake_make_get_id_mode(data, data_make->error, arguments.array[0], &mode_rule, &replace); - if (F_status_is_error(*status)) return; + *status = fake_make_get_id_mode(*data, data_make->error, arguments.array[0], &mode_rule, &replace); + if (F_status_is_error(*status)) return 0; mode_t mode = 0; mode_t mode_file = 0; @@ -3362,16 +3383,16 @@ extern "C" { break; } - if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Changed mode of '"); - fl_color_print(data.error.to.stream, data.context.set.notable, "%s", arguments.array[i].string); - fprintf(data.output.stream, "' to "); - fl_color_print(data.error.to.stream, data.context.set.notable, "%#o", mode); - fprintf(data.output.stream, ".%c", f_string_eol[0]); + if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Changed mode of '"); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s", arguments.array[i].string); + fprintf(data->output.stream, "' to "); + fl_color_print(data->error.to.stream, data->context.set.notable, "%#o", mode); + fprintf(data->output.stream, ".%c", f_string_eol[0]); } } // for - return; + return 0; } if (operation == fake_make_operation_type_move) { @@ -3382,8 +3403,8 @@ extern "C" { f_string_length_t destination_length = 0; - if (data.error.verbosity == f_console_verbosity_verbose) { - recurse.output = data.output; + if (data->error.verbosity == f_console_verbosity_verbose) { + recurse.output = data->output; recurse.verbose = fake_verbose_print_move; } @@ -3397,7 +3418,7 @@ extern "C" { fll_error_file_print(data_make->error, F_status_set_fine(*status), "f_directory_is", F_true, arguments.array[1].string, "identify", fll_error_file_type_directory); *status = F_status_set_error(F_failure); - return; + return 0; } if (status_file == F_false || status_file == F_file_found_not) { @@ -3432,7 +3453,7 @@ extern "C" { } } // for - return; + return 0; } if (operation == fake_make_operation_type_operate) { @@ -3446,10 +3467,10 @@ extern "C" { } // for if (id_section == data_make->fakefile.used) { - return; + return 0; } - fake_make_operate_section(data, id_section, data_make, section_stack, status); + const int result = fake_make_operate_section(id_section, data, data_make, section_stack, status); // Ensure that a break only happens within its active operation stack. if (*status == F_signal_abort) { @@ -3459,25 +3480,25 @@ extern "C" { *status = F_status_set_error(F_failure); } - return; + return result; } if (operation == fake_make_operation_type_owner) { uid_t id = 0; - *status = fake_make_get_id_owner(data, data_make->error, arguments.array[0], &id); - if (F_status_is_error(*status)) return; + *status = fake_make_get_id_owner(*data, data_make->error, arguments.array[0], &id); + if (F_status_is_error(*status)) return 0; f_status_t status_file = F_none; for (f_array_length_t i = 1; i < arguments.used; i++) { - status_file = fake_make_assure_inside_project(data, arguments.array[i], data_make); + status_file = fake_make_assure_inside_project(*data, arguments.array[i], data_make); if (F_status_is_error(status_file)) { *status = status_file; - fake_print_message_section_operation_path_outside(data, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); + fake_print_message_section_operation_path_outside(*data, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); continue; } @@ -3490,34 +3511,34 @@ extern "C" { fll_error_file_print(data_make->error, F_status_set_fine(*status), "f_file_role_change", F_true, arguments.array[i].string, "change owner of", fll_error_file_type_file); break; } - else if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Changed owner of '"); - fl_color_print(data.error.to.stream, data.context.set.notable, "%s", arguments.array[i].string); - fprintf(data.output.stream, "' to "); - fl_color_print(data.error.to.stream, data.context.set.notable, "%d", id); - fprintf(data.output.stream, ".%c", f_string_eol[0]); + else if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Changed owner of '"); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s", arguments.array[i].string); + fprintf(data->output.stream, "' to "); + fl_color_print(data->error.to.stream, data->context.set.notable, "%d", id); + fprintf(data->output.stream, ".%c", f_string_eol[0]); } } // for - return; + return 0; } if (operation == fake_make_operation_type_owners) { uid_t id = 0; - *status = fake_make_get_id_owner(data, data_make->error, arguments.array[0], &id); - if (F_status_is_error(*status)) return; + *status = fake_make_get_id_owner(*data, data_make->error, arguments.array[0], &id); + if (F_status_is_error(*status)) return 0; f_status_t status_file = F_none; for (f_array_length_t i = 1; i < arguments.used; i++) { - status_file = fake_make_assure_inside_project(data, arguments.array[i], data_make); + status_file = fake_make_assure_inside_project(*data, arguments.array[i], data_make); if (F_status_is_error(status_file)) { *status = status_file; - fake_print_message_section_operation_path_outside(data, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); + fake_print_message_section_operation_path_outside(*data, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string); continue; } @@ -3529,16 +3550,16 @@ extern "C" { fll_error_file_print(data_make->error, F_status_set_fine(*status), "fll_file_role_change_all", F_true, arguments.array[i].string, "change owner of", fll_error_file_type_file); } - else if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Changed owner of '"); - fl_color_print(data.error.to.stream, data.context.set.notable, "%s", arguments.array[i].string); - fprintf(data.output.stream, "' to "); - fl_color_print(data.error.to.stream, data.context.set.notable, "%d", id); - fprintf(data.output.stream, ".%c", f_string_eol[0]); + else if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Changed owner of '"); + fl_color_print(data->error.to.stream, data->context.set.notable, "%s", arguments.array[i].string); + fprintf(data->output.stream, "' to "); + fl_color_print(data->error.to.stream, data->context.set.notable, "%d", id); + fprintf(data->output.stream, ".%c", f_string_eol[0]); } } // for - return; + return 0; } if (operation == fake_make_operation_type_pop) { @@ -3549,98 +3570,98 @@ extern "C" { *status = f_path_change(data_make->path.stack.array[data_make->path.stack.used - 1].string); if (F_status_is_error(*status)) { - fake_print_message_section_operation_path_stack_max(data, data_make->error, F_status_set_fine(*status), "f_path_change", data_make->path.stack.array[data_make->path.stack.used - 1].string); - return; + fake_print_message_section_operation_path_stack_max(*data, data_make->error, F_status_set_fine(*status), "f_path_change", data_make->path.stack.array[data_make->path.stack.used - 1].string); + return 0; } - if (data.error.verbosity == f_console_verbosity_verbose) { - *status = fake_make_path_relative(data, data_make->path.stack.array[data_make->path.stack.used - 1], data_make); + if (data->error.verbosity == f_console_verbosity_verbose) { + *status = fake_make_path_relative(*data, data_make->path.stack.array[data_make->path.stack.used - 1], data_make); if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "fake_make_path_relative", F_true); - return; + return 0; } - fprintf(data.output.stream, "Changed to project path '"); - fl_color_print_code(data.output.stream, *data.context.set.notable.before); - f_print_dynamic(data.output.stream, data_make->path_cache); - fl_color_print_code(data.output.stream, *data.context.set.notable.after); - fprintf(data.output.stream, "'.%c", f_string_eol[0]); + fprintf(data->output.stream, "Changed to project path '"); + fl_color_print_code(data->output.stream, *data->context.set.notable.before); + f_print_dynamic(data->output.stream, data_make->path_cache); + fl_color_print_code(data->output.stream, *data->context.set.notable.after); + fprintf(data->output.stream, "'.%c", f_string_eol[0]); } - return; + return 0; } if (operation == fake_make_operation_type_print) { for (f_array_length_t i = 0; i < arguments.used; i++) { - f_print_dynamic(data.output.stream, arguments.array[i]); + f_print_dynamic(data->output.stream, arguments.array[i]); if (i + 1 < arguments.used) { - fprintf(data.output.stream, " "); + fprintf(data->output.stream, " "); } } // for - fprintf(data.output.stream, "%c", f_string_eol[0]); - return; + fprintf(data->output.stream, "%c", f_string_eol[0]); + return 0; } if (operation == fake_make_operation_type_run) { - *status = fake_make_operate_process_run(data, arguments, F_false, data_make); - return; + *status = fake_make_operate_process_run(*data, arguments, F_false, data_make); + return 0; } if (operation == fake_make_operation_type_shell) { - *status = fake_make_operate_process_run(data, arguments, F_true, data_make); - return; + *status = fake_make_operate_process_run(*data, arguments, F_true, data_make); + return 0; } if (operation == fake_make_operation_type_skeleton) { - *status = fake_skeleton_operate(data); + *status = fake_skeleton_operate(*data); if (F_status_set_fine(*status) == F_signal) { *status = F_status_set_error(F_signal); - return; + return 0; } if (F_status_is_error(*status)) { - fake_make_operate_process_return(data, 1, data_make, status); + fake_make_operate_process_return(*data, 1, data_make, status); } else { - fake_make_operate_process_return(data, 0, data_make, status); + fake_make_operate_process_return(*data, 0, data_make, status); } - return; + return 0; } if (operation == fake_make_operation_type_to) { - *status = fake_make_assure_inside_project(data, arguments.array[0], data_make); + *status = fake_make_assure_inside_project(*data, arguments.array[0], data_make); if (F_status_is_error(*status)) { - fake_print_message_section_operation_path_outside(data, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[0].string); + fake_print_message_section_operation_path_outside(*data, data_make->error, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[0].string); if (F_status_set_fine(*status) == F_false) { *status = F_status_set_error(F_failure); } - return; + return 0; } *status = f_path_change(arguments.array[0].string); if (F_status_is_error(*status)) { - fake_print_message_section_operation_path_stack_max(data, data_make->error, F_status_set_fine(*status), "f_path_change", arguments.array[0].string); + fake_print_message_section_operation_path_stack_max(*data, data_make->error, F_status_set_fine(*status), "f_path_change", arguments.array[0].string); } else { if (data_make->path.stack.used == data_make->path.stack.size) { *status = fl_string_dynamics_increase_by(f_memory_default_allocation_step, &data_make->path.stack); if (F_status_set_fine(*status) == F_array_too_large) { - fake_print_message_section_operation_path_stack_max(data, data_make->error, F_array_too_large, "fl_string_lengths_increase_by", "path stack"); - return; + fake_print_message_section_operation_path_stack_max(*data, data_make->error, F_array_too_large, "fl_string_lengths_increase_by", "path stack"); + return 0; } else if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "f_macro_string_dynamics_t_resize", F_true); - return; + return 0; } } @@ -3651,28 +3672,28 @@ extern "C" { if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "fl_string_dynamic_append_nulless", F_true); - return; + return 0; } - if (data.error.verbosity == f_console_verbosity_verbose) { - *status = fake_make_path_relative(data, data_make->path.stack.array[data_make->path.stack.used], data_make); + if (data->error.verbosity == f_console_verbosity_verbose) { + *status = fake_make_path_relative(*data, data_make->path.stack.array[data_make->path.stack.used], data_make); if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "fake_make_path_relative", F_true); - return; + return 0; } - fprintf(data.output.stream, "Changed to project path '"); - fl_color_print_code(data.output.stream, *data.context.set.notable.before); - f_print_dynamic(data.output.stream, data_make->path_cache); - fl_color_print_code(data.output.stream, *data.context.set.notable.after); - fprintf(data.output.stream, "'.%c", f_string_eol[0]); + fprintf(data->output.stream, "Changed to project path '"); + fl_color_print_code(data->output.stream, *data->context.set.notable.before); + f_print_dynamic(data->output.stream, data_make->path_cache); + fl_color_print_code(data->output.stream, *data->context.set.notable.after); + fprintf(data->output.stream, "'.%c", f_string_eol[0]); } data_make->path.stack.used++; } - return; + return 0; } if (operation == fake_make_operation_type_top) { @@ -3680,12 +3701,12 @@ extern "C" { *status = f_path_change_at(data_make->path.top.id); if (F_status_is_error(*status)) { - fake_print_message_section_operation_path_stack_max(data, data_make->error, F_status_set_fine(*status), "f_path_change", arguments.array[0].string); - return; + fake_print_message_section_operation_path_stack_max(*data, data_make->error, F_status_set_fine(*status), "f_path_change", arguments.array[0].string); + return 0; } - if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Changed to project path ''.%c", f_string_eol[0]); + if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Changed to project path ''.%c", f_string_eol[0]); } // clear stack, except for the project root. @@ -3694,13 +3715,13 @@ extern "C" { } // for data_make->path.stack.used = 1; - return; + return 0; } if (operation == fake_make_operation_type_touch) { f_mode_t mode = f_mode_t_initialize; - f_macro_mode_t_set_default_umask(mode, data.umask); + f_macro_mode_t_set_default_umask(mode, data->umask); for (f_array_length_t i = 1; i < arguments.used; i++) { @@ -3733,18 +3754,18 @@ extern "C" { } } - if (data.error.verbosity == f_console_verbosity_verbose) { - fprintf(data.output.stream, "Touched %s '", arguments.array[0].string); - fl_color_print_code(data.output.stream, *data.context.set.notable.before); - f_print_dynamic(data.output.stream, arguments.array[i]); - fl_color_print_code(data.output.stream, *data.context.set.notable.after); - fprintf(data.output.stream, "'.%c", f_string_eol[0]); + if (data->error.verbosity == f_console_verbosity_verbose) { + fprintf(data->output.stream, "Touched %s '", arguments.array[0].string); + fl_color_print_code(data->output.stream, *data->context.set.notable.before); + f_print_dynamic(data->output.stream, arguments.array[i]); + fl_color_print_code(data->output.stream, *data->context.set.notable.after); + fprintf(data->output.stream, "'.%c", f_string_eol[0]); } } // for - - return; } + + return 0; } #endif // _di_fake_make_operate_process_ @@ -3826,10 +3847,10 @@ extern "C" { f_signal_set_fill(&signals.block_not); if (as_shell) { - status = fll_execute_path_environment(program.string, arguments, &signals, data_make->environment.names, data_make->environment.values, &return_code); + status = fll_execute_path_environment(program.string, arguments, data_make->environment.names, data_make->environment.values, &signals, &return_code); } else { - status = fll_execute_program_environment(program.string, arguments, &signals, data_make->environment.names, data_make->environment.values, &return_code); + status = fll_execute_program_environment(program.string, arguments, data_make->environment.names, data_make->environment.values, &signals, &return_code); } if (status == F_status_set_error(F_signal)) { diff --git a/level_3/fake/c/private-make.h b/level_3/fake/c/private-make.h index 8b83d3a..5a412c3 100644 --- a/level_3/fake/c/private-make.h +++ b/level_3/fake/c/private-make.h @@ -538,7 +538,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_operate_ - extern f_return_status fake_make_operate(const fake_data_t data) f_gcc_attribute_visibility_internal; + extern f_return_status fake_make_operate(fake_data_t *data) f_gcc_attribute_visibility_internal; #endif // _di_fake_make_operate_ /** @@ -622,29 +622,32 @@ extern "C" { /** * Perform the make operations within the given section. * - * @param data - * The program data. * @param id_section * The array location id within the fakefile of the section to operate on. + * @param data + * The program data. * @param data_make * All make related setting data, including data from the fakefile and optionally build settings file. * @param section_stack * The current operation stack. * @param status - * The return status. - * + * F_none on success. * F_valid_not (with error bit set) is returned if any part of the section is invalid, such as an invalid operation name. * F_recurse (with error bit set) is returned if unable to recurse to another operation section (usually max stack depth reached). + * + * Status codes (with error bit) are returned on any problem. + * + * @return + * The return code of the execution process. + * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_make_operate_section_ - void fake_make_operate_section(const fake_data_t data, const f_array_length_t id_section, fake_make_data_t *data_make, f_string_lengths_t *section_stack, f_status_t *status) f_gcc_attribute_visibility_internal; + int fake_make_operate_section(const f_array_length_t id_section, fake_data_t *data, fake_make_data_t *data_make, f_string_lengths_t *section_stack, f_status_t *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_make_operate_section_ /** * Perform a specific make operation within the given section. * - * @param data - * The program data. * @param section_name * The section name. * @param operation @@ -657,17 +660,23 @@ extern "C" { * Whether or not a previous section operation succeeded or failed. * @param operation_if * The if-condition status for the current operation. + * @param data + * The program data. * @param data_make * All make related setting data, including data from the fakefile and optionally build settings file. * @param section_stack * The current operation stack. * @param status - * The return status. + * F_none on success. * * Status codes (with error bit) are returned on any problem. + * + * @return + * The return code of the execution process. + * This generally is only needed when F_child is returned, where this holds the return status of the child process. */ #ifndef _di_fake_make_operate_process_ - extern void fake_make_operate_process(const fake_data_t data, const f_string_range_t section_name, const uint8_t operation, const f_string_static_t operation_name, const f_string_dynamics_t arguments, const bool success, uint8_t *operation_if, fake_make_data_t *data_make, f_string_lengths_t *section_stack, f_status_t *status) f_gcc_attribute_visibility_internal; + extern int fake_make_operate_process(const f_string_range_t section_name, const uint8_t operation, const f_string_static_t operation_name, const f_string_dynamics_t arguments, const bool success, uint8_t *operation_if, fake_data_t *data, fake_make_data_t *data_make, f_string_lengths_t *section_stack, f_status_t *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_make_operate_process_ /** diff --git a/level_3/firewall/c/private-firewall.c b/level_3/firewall/c/private-firewall.c index 62b985c..6f8beb0 100644 --- a/level_3/firewall/c/private-firewall.c +++ b/level_3/firewall/c/private-firewall.c @@ -754,6 +754,11 @@ f_return_status firewall_perform_commands(const firewall_local_data_t local, con status = fll_execute_program((f_string_t) current_tool, arguments, 0, &return_code); + // immediately exit child process, @todo this may require additional memory deallocation and relating changes. + if (status == F_child) { + exit(return_code); + } + if (status == F_failure) { fl_color_print(data.error.to.stream, data.context.set.error, "%sFailed to perform requested %s operation:%c", fll_error_print_error, current_tool, f_string_eol[0]); fprintf(f_type_error, " "); @@ -823,6 +828,11 @@ f_return_status firewall_perform_commands(const firewall_local_data_t local, con status = fll_execute_program(current_tool, arguments, 0, &return_code); + // immediately exit child process, @todo this may require additional memory deallocation and relating changes. + if (status == F_child) { + exit(return_code); + } + if (status == F_failure) { fl_color_print(data.error.to.stream, data.context.set.error, "%sFailed to perform requested %s operation:%c", fll_error_print_error, current_tool, f_string_eol[0]); fprintf(f_type_error, " "); @@ -1062,6 +1072,11 @@ 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); + // immediately exit child process, @todo this may require additional memory deallocation and relating changes. + if (status == F_child) { + exit(return_code); + } + if (F_status_is_error_not(status)) { if (data->error.verbosity == f_console_verbosity_debug) { fl_color_print_code(f_type_debug, data->context.warning); @@ -1077,6 +1092,11 @@ 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); + + // immediately exit child process, @todo this may require additional memory deallocation and relating changes. + if (status == F_child) { + exit(return_code); + } } if (F_status_is_error(status)) { @@ -1161,6 +1181,11 @@ f_return_status firewall_delete_chains(const firewall_data_t data) { status = fll_execute_program(tools[i], arguments, 0, &return_code); + // immediately exit child process, @todo this may require additional memory deallocation and relating changes. + if (status == F_child) { + exit(return_code); + } + if (F_status_is_error(status)) { status = F_status_set_fine(status); @@ -1216,6 +1241,11 @@ f_return_status firewall_delete_chains(const firewall_data_t data) { status = fll_execute_program(tools[i], arguments, 0, &return_code); + // immediately exit child process, @todo this may require additional memory deallocation and relating changes. + if (status == F_child) { + exit(return_code); + } + if (F_status_is_error(status)) { status = F_status_set_fine(status); @@ -1293,6 +1323,11 @@ f_return_status firewall_default_lock(const firewall_data_t data) { status = fll_execute_program(tools[j], arguments, 0, &return_code); + // immediately exit child process, @todo this may require additional memory deallocation and relating changes. + if (status == F_child) { + exit(return_code); + } + if (F_status_is_error(status)) { status = F_status_set_fine(status); -- 1.8.3.1