From 634f6cabdd79bed2f7677d4ff49513cc377d2519 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 16 Apr 2024 21:01:12 -0500 Subject: [PATCH] Progress: Continue migrating the project. --- data/build/defines | 32 ++++---- data/build/settings | 6 +- sources/c/controller/controller.h | 3 + sources/c/controller/main.c | 2 + sources/c/init/init.h | 3 + sources/c/init/main.c | 4 + sources/c/main/common.c | 140 ++++++++++++++++++++++++++++++++++- sources/c/main/common.h | 2 + sources/c/main/common/enumeration.h | 24 ++++-- sources/c/main/common/print.c | 2 + sources/c/main/common/print.h | 2 + sources/c/main/common/string.h | 32 +------- sources/c/main/common/type/process.h | 4 +- sources/c/main/common/type/rule.h | 2 +- sources/c/main/common/type/thread.c | 8 +- sources/c/main/common/type/thread.h | 13 ++-- sources/c/main/controller.h | 3 + sources/c/main/path.c | 40 ++++++++++ sources/c/main/path.h | 58 +++++++++++++++ sources/c/main/print/debug.c | 20 +++++ sources/c/main/print/debug.h | 28 +++++++ sources/c/main/print/error.c | 14 ++++ sources/c/main/print/error.h | 35 +++++++++ sources/c/main/print/lock.c | 69 +++++++++++++++++ sources/c/main/print/lock.h | 89 ++++++++++++++++++++++ sources/c/main/print/message.c | 1 - sources/c/main/thread.h | 2 + 27 files changed, 573 insertions(+), 65 deletions(-) create mode 100644 sources/c/main/path.c create mode 100644 sources/c/main/path.h create mode 100644 sources/c/main/print/lock.c create mode 100644 sources/c/main/print/lock.h diff --git a/data/build/defines b/data/build/defines index 260609f..345bd45 100644 --- a/data/build/defines +++ b/data/build/defines @@ -1,23 +1,27 @@ # fss-0000 -_di_libcap_ Disable libcap support, allow for compiling and linking without libcap (-lcap). +_di_libcap_ Disable libcap support, allow for compiling and linking without libcap (-lcap). _di_thread_support_ Disables thread support. _libcap_legacy_only_ Disable functionality provided by later versions of libcap (2.43 and later). -_override_controller_default_engine_ Provide a custom scripting engine name string to execute (such as php). -_override_controller_default_engine_length_ The number of bytes representing the string in _override_controller_default_engine_ (not including the terminating NULL). -_override_controller_path_pid_ Use this as the default custom directory path representing the location of the controller program pid. -_override_controller_path_pid_length_ The number of bytes representing the string in _override_controller_path_pid_ (not including the terminating NULL). -_override_controller_path_pid_prefix_ Use this as the default custom prefix prepended to the file name of the file representing the controller program pid. -_override_controller_path_pid_prefix_length_ The number of bytes representing the string in _override_controller_path_pid_prefix_ (not including the terminating NULL). -_override_controller_path_pid_suffix_ Use this as the default custom prefix prepended to the file name of the file representing the controller program pid. -_override_controller_path_pid_suffix_length_ The number of bytes representing the string in _override_controller_path_pid_suffix_ (not including the terminating NULL). -_override_controller_path_socket_ Use this as the default custom directory path representing the location of the controller program socket. -_override_controller_path_socket_length_ The number of bytes representing the string in _override_controller_path_socket_ (not including the terminating NULL). -_override_controller_path_socket_prefix_ Use this as the default custom prefix prepended to the file name of the file representing the controller program socket. + +_override_controller_default_engine_ Provide a custom scripting engine name string to execute (such as php). +_override_controller_path_pid_ Use this as the default custom directory path representing the location of the controller program pid. +_override_controller_path_pid_prefix_ Use this as the default custom prefix prepended to the file name of the file representing the controller program pid. +_override_controller_path_pid_suffix_ Use this as the default custom prefix prepended to the file name of the file representing the controller program pid. +_override_controller_path_settings_ Use this as the default custom settings path, such as /etc/settings. +_override_controller_path_socket_ Use this as the default custom directory path representing the location of the controller program socket. +_override_controller_path_socket_prefix_ Use this as the default custom prefix prepended to the file name of the file representing the controller program socket. +_override_controller_path_socket_suffix_ Use this as the default custom prefix prepended to the file name of the file representing the controller program socket. + +_override_controller_default_engine_length_ The number of bytes representing the string in _override_controller_default_engine_ (not including the terminating NULL). +_override_controller_path_pid_length_ The number of bytes representing the string in _override_controller_path_pid_ (not including the terminating NULL). +_override_controller_path_pid_prefix_length_ The number of bytes representing the string in _override_controller_path_pid_prefix_ (not including the terminating NULL). +_override_controller_path_pid_suffix_length_ The number of bytes representing the string in _override_controller_path_pid_suffix_ (not including the terminating NULL). +_override_controller_path_settings_length_ The number of bytes representing the string in _override_controller_path_settings_ (not including the terminating NULL). +_override_controller_path_socket_length_ The number of bytes representing the string in _override_controller_path_socket_ (not including the terminating NULL). _override_controller_path_socket_prefix_length_ The number of bytes representing the string in _override_controller_path_socket_prefix_ (not including the terminating NULL). -_override_controller_path_socket_suffix_ Use this as the default custom prefix prepended to the file name of the file representing the controller program socket. _override_controller_path_socket_suffix_length_ The number of bytes representing the string in _override_controller_path_socket_suffix_ (not including the terminating NULL). -_pthread_attr_unsupported_ Disable non-portable functionality associated with pthread_attr. +_pthread_attr_unsupported_ Disable non-portable functionality associated with pthread_attr. _pthread_sigqueue_unsupported_ Disable GNU specific sigqueue(). diff --git a/data/build/settings b/data/build/settings index d1ef3f9..bbaed75 100644 --- a/data/build/settings +++ b/data/build/settings @@ -43,7 +43,8 @@ build_libraries-monolithic -lfll build_sources_library main/common.c main/common/define.c main/common/enumeration.c main/common/print.c main/common/string.c main/common/type.c build_sources_library main/common/type/cache.c main/common/type/control.c main/common/type/entry.c main/common/type/lock.c main/common/type/process.c main/common/type/rule.c main/common/type/thread.c build_sources_library main/common/string/general.c main/common/string/rule.c -build_sources_library main/print/data.c main/print/debug.c main/print/error.c main/print/message.c main/print/verbose.c main/print/warning.c +build_sources_library main/path.c +build_sources_library main/print/data.c main/print/debug.c main/print/error.c main/print/lock.c main/print/message.c main/print/verbose.c main/print/warning.c build_sources_library main/signal.c main/thread.c build_sources_headers main/common.h main/controller.h main/common/define.h main/common/enumeration.h main/common/print.h main/common/string.h main/common/type.h @@ -51,7 +52,8 @@ build_sources_headers main/common/define/control.h main/common/define/entry.h ma build_sources_headers main/common/enumeration/control.h main/common/enumeration/entry.h main/common/enumeration/process.h main/common/enumeration/rule.h main/common/enumeration/thread.h build_sources_headers main/common/string/general.h main/common/string/rule.h build_sources_headers main/common/type/cache.h main/common/type/control.h main/common/type/entry.h main/common/type/lock.h main/common/type/process.h main/common/type/rule.h main/common/type/thread.h -build_sources_headers main/print/data.h main/print/debug.h main/print/error.h main/print/message.h main/print/verbose.h main/print/warning.h +build_sources_headers main/path.h +build_sources_headers main/print/data.h main/print/debug.h main/print/error.h main/print/lock.h main/print/message.h main/print/verbose.h main/print/warning.h build_sources_headers main/signal.h main/thread.h build_sources_documentation man diff --git a/sources/c/controller/controller.h b/sources/c/controller/controller.h index 000a2b6..94832c5 100644 --- a/sources/c/controller/controller.h +++ b/sources/c/controller/controller.h @@ -51,6 +51,7 @@ // FLL-1 includes. #include +#include #include // FLL-2 includes. @@ -83,9 +84,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include diff --git a/sources/c/controller/main.c b/sources/c/controller/main.c index 01ef621..b424ea8 100644 --- a/sources/c/controller/main.c +++ b/sources/c/controller/main.c @@ -26,6 +26,8 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { data.program.pipe = fll_program_data_pipe_input_e; } + data.setting.flag |= controller_main_flag_interruptible_e; + fll_program_standard_set_up(&data.program); f_file_umask_get(&data.program.umask); diff --git a/sources/c/init/init.h b/sources/c/init/init.h index f47ded6..1e639bf 100644 --- a/sources/c/init/init.h +++ b/sources/c/init/init.h @@ -51,6 +51,7 @@ // FLL-1 includes. #include +#include #include // FLL-2 includes. @@ -83,9 +84,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include diff --git a/sources/c/init/main.c b/sources/c/init/main.c index aeee890..deb3e07 100644 --- a/sources/c/init/main.c +++ b/sources/c/init/main.c @@ -26,6 +26,10 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { data.program.pipe = fll_program_data_pipe_input_e; } + data.setting.flag &= ~controller_main_flag_interruptible_e; + process.entry.pid = controller_entry_pid_disable_e; + process.entry.show = controller_entry_show_init_e; + fll_program_standard_set_up(&data.program); f_file_umask_get(&data.program.umask); diff --git a/sources/c/main/common.c b/sources/c/main/common.c index cadd124..89ba734 100644 --- a/sources/c/main/common.c +++ b/sources/c/main/common.c @@ -7,7 +7,7 @@ extern "C" { #ifndef _di_controller_main_setting_load_ void controller_main_setting_load(const f_console_arguments_t arguments, controller_main_t * const main, controller_process_t * const process) { - if (!main) return; + if (!main || !process) return; main->setting.state.step_small = controller_allocation_console_d; @@ -89,6 +89,7 @@ extern "C" { } f_string_static_t * const args = main->program.parameters.arguments.array; + f_number_unsigned_t index = 0; process->control.server.domain = f_socket_protocol_family_local_e; process->control.server.type = f_socket_type_stream_e; @@ -96,6 +97,37 @@ extern "C" { memset(&process->control.server.address, 0, sizeof(f_socket_address_t)); + { + const uint8_t codes[] = { + controller_parameter_cgroup_e, + controller_parameter_daemon_e, + controller_parameter_pid_e, + controller_parameter_settings_e, + }; + + const f_string_static_t strings[] = { + controller_long_cgroup_s, + controller_long_daemon_s, + controller_long_pid_s, + controller_long_settings_s, + }; + + for (index = 0; index < 4; ++index) { + + if (main->program.parameters.array[controller_parameter_settings_e].result & codes[index]) { + main->setting.state.status = F_status_set_error(F_parameter); + + if ((main->setting.flag & controller_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) { + fll_print_dynamic_raw(f_string_eol_s, main->program.message.to); + } + + fll_program_print_error_parameter_missing_value(&main->program.error, f_console_symbol_long_normal_s, strings[index]); + + return; + } + } // for + } + // The first remaining argument represents the entry name. main->setting.state.status = f_string_dynamic_append(main->program.parameters.remaining.used ? args[main->program.parameters.remaining.array[0]] : controller_default_s, &process->name_entry); @@ -120,6 +152,112 @@ extern "C" { return; } + + process->path_setting.used = 0; + + if (main->program.parameters.array[controller_parameter_settings_e].locations.used) { + index = main->program.parameters.array[controller_parameter_settings_e].values.array[main->program.parameters.array[controller_parameter_settings_e].values.used - 1]; + + controller_path_canonical_relative(main, process->path_current, args[index], &process->path_setting); + } + else { + main->setting.state.status = f_string_dynamic_append(controller_default_path_settings_s, &process->path_setting); + } + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & controller_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) { + fll_print_dynamic_raw(f_string_eol_s, main->program.message.to); + } + + if (main->program.parameters.array[controller_parameter_settings_e].locations.used) { + controller_main_print_error_file(&main->program.error, macro_controller_f(controller_path_canonical_relative), args[index], f_file_operation_verify_s, fll_error_file_type_path_e); + } + else { + controller_main_print_error(&main->program.error, macro_controller_f(f_string_dynamic_append)); + } + + return; + } + + if (!process->path_pid.used && !main->program.parameters.array[controller_parameter_pid_e].locations.used) { + main->setting.state.status = f_string_dynamic_append(controller_default_path_pid_s, &process->path_pid); + + if (F_status_is_error_not(main->setting.state.status)) { + main->setting.state.status = f_string_dynamic_append(f_path_separator_s, &process->path_pid); + } + + if (F_status_is_error_not(main->setting.state.status)) { + main->setting.state.status = f_string_dynamic_append(controller_default_path_pid_prefix_s, &process->path_pid); + } + + if (F_status_is_error_not(main->setting.state.status)) { + main->setting.state.status = f_string_dynamic_append(process->name_entry, &process->path_pid); + } + + if (F_status_is_error_not(main->setting.state.status)) { + main->setting.state.status = f_string_dynamic_append(controller_default_path_pid_suffix_s, &process->path_pid); + } + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & controller_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) { + fll_print_dynamic_raw(f_string_eol_s, main->program.message.to); + } + + controller_main_print_error(&main->program.error, macro_controller_f(f_string_dynamic_append)); + + return; + } + } + + if (main->program.parameters.array[controller_parameter_cgroup_e].locations.used) { + index = main->program.parameters.array[controller_parameter_cgroup_e].values.array[main->program.parameters.array[controller_parameter_cgroup_e].values.used - 1]; + + if (args[index].used) { + controller_path_canonical_relative(main, process->path_current, args[index], &process->path_cgroup); + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & controller_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) { + fll_print_dynamic_raw(f_string_eol_s, main->program.message.to); + } + + controller_main_print_error_file(&main->program.error, macro_controller_f(controller_path_canonical_relative), args[index], f_file_operation_verify_s, fll_error_file_type_path_e); + + return; + } + + main->setting.state.status = f_string_append_assure(F_path_separator_s, 1, &process->path_cgroup); + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & controller_main_flag_print_first_e) && main->program.message.verbosity > f_console_verbosity_error_e) { + fll_print_dynamic_raw(f_string_eol_s, main->program.message.to); + } + + controller_main_print_error(&main->program.error, macro_controller_f(f_string_append_assure)); + + return; + } + } + else { + controller_main_print_debug_directory_path_empty(&main->program.warning, f_console_symbol_long_normal_s, controller_long_cgroup_s); + } + } + + if (main->program.parameters.array[controller_parameter_interruptible_e].result & f_console_result_found_e) { + if (main->program.parameters.array[controller_parameter_uninterruptible_e].result & f_console_result_found_e) { + if (main->program.parameters.array[controller_parameter_interruptible_e].location < main->program.parameters.array[controller_parameter_uninterruptible_e].location) { + main->setting.flag &= ~controller_main_flag_interruptible_e; + } + else { + main->setting.flag |= controller_main_flag_interruptible_e; + } + } + else { + main->setting.flag |= controller_main_flag_interruptible_e; + } + } + else if (main->program.parameters.array[controller_parameter_uninterruptible_e].result & f_console_result_found_e) { + main->setting.flag &= ~controller_main_flag_interruptible_e; + } } #endif // _di_controller_main_setting_load_ diff --git a/sources/c/main/common.h b/sources/c/main/common.h index 1ed8582..e320498 100644 --- a/sources/c/main/common.h +++ b/sources/c/main/common.h @@ -28,6 +28,8 @@ extern "C" { * @param main * The program and settings data. * + * Must not be NULL. + * * This alters setting.state.status: * F_okay on success. * diff --git a/sources/c/main/common/enumeration.h b/sources/c/main/common/enumeration.h index 1f8ae3b..590e897 100644 --- a/sources/c/main/common/enumeration.h +++ b/sources/c/main/common/enumeration.h @@ -27,6 +27,7 @@ extern "C" { * - error: Check if status is "error". * - fine: Check if status is "fine". * - help: Print help. + * - interruptible: The process is interruptible. * - pipe: Use the input pipe. * - print_first: When set, print new line to message output on program begin after loading settings. * - print_last: When set, print new line to message output on program end. @@ -41,12 +42,13 @@ extern "C" { controller_main_flag_error_e = 0x2, controller_main_flag_fine_e = 0x4, controller_main_flag_help_e = 0x8, - controller_main_flag_pipe_e = 0x10, - controller_main_flag_print_first_e = 0x20, - controller_main_flag_print_last_e = 0x40, - controller_main_flag_version_e = 0x80, - controller_main_flag_version_copyright_help_e = 0x89, - controller_main_flag_warning_e = 0x100, + controller_main_flag_interruptible_e = 0x10, + controller_main_flag_pipe_e = 0x20, + controller_main_flag_print_first_e = 0x40, + controller_main_flag_print_last_e = 0x80, + controller_main_flag_version_e = 0x100, + controller_main_flag_version_copyright_help_e = 0x181, + controller_main_flag_warning_e = 0x200, }; // enum #endif // _di_controller_main_flag_e_ @@ -55,7 +57,15 @@ extern "C" { */ #ifndef _di_controller_parameter_e_ enum { - controller_parameter_controller_e = f_console_standard_parameter_last_e, + controller_parameter_cgroup_e = f_console_standard_parameter_last_e, + controller_parameter_daemon_e, + controller_parameter_interruptible_e, + controller_parameter_pid_e, + controller_parameter_settings_e, + controller_parameter_simulate_e, + controller_parameter_socket_e, + controller_parameter_uninterruptible_e, + controller_parameter_validate_e, }; // enum #define controller_console_parameter_t_initialize \ diff --git a/sources/c/main/common/print.c b/sources/c/main/common/print.c index a259bf2..c3cef5e 100644 --- a/sources/c/main/common/print.c +++ b/sources/c/main/common/print.c @@ -6,8 +6,10 @@ extern "C" { #ifndef _di_controller_f_a_ const f_string_t controller_f_a[] = { + "f_controller_path_canonical_relative", "f_console_parameter_process", "f_path_current", + "f_string_append_assure", "f_string_dynamic_append", "f_thread_create", "fll_program_parameter_process_context_standard", diff --git a/sources/c/main/common/print.h b/sources/c/main/common/print.h index df22450..09640ba 100644 --- a/sources/c/main/common/print.h +++ b/sources/c/main/common/print.h @@ -39,8 +39,10 @@ extern "C" { */ #ifndef _di_controller_f_e_ enum { + controller_f_controller_path_canonical_relative_e, controller_f_f_console_parameter_process_e, controller_f_f_path_current_e, + controller_f_f_string_append_assure_e, controller_f_f_string_dynamic_append_e, controller_f_f_thread_create_e, controller_f_fll_program_parameter_process_context_standard_e, diff --git a/sources/c/main/common/string.h b/sources/c/main/common/string.h index 03a7b9a..72f1d19 100644 --- a/sources/c/main/common/string.h +++ b/sources/c/main/common/string.h @@ -123,6 +123,8 @@ extern "C" { /** * The program defaults. + * + * These are defines inside the programs utilizing this rather than in the library itself. */ #ifndef _di_controller_default_s_ @@ -135,15 +137,6 @@ extern "C" { #define CONTROLLER_default_path_pid_s_length 5 #endif // defined(_override_controller_path_pid_) && defined(_override_controller_path_pid_length_) - // The init pid path is a system-specific path and needs to be more easily controlled at compile time. - #if defined(_override_controller_path_pid_init_) && defined(_override_controller_path_pid_init_length_) - #define CONTROLLER_default_path_pid_init_s _override_controller_path_pid_init_ - #define CONTROLLER_default_path_pid_init_s_length _override_controller_path_pid_init_length_ - #else - #define CONTROLLER_default_path_pid_init_s "/var/run/controller" - #define CONTROLLER_default_path_pid_init_s_length 19 - #endif // defined(_override_controller_path_pid_init_) && defined(_override_controller_path_pid_init_length_) - // The pid prefix is a system-specific path part and needs to be more easily controlled at compile time. #if defined(_override_controller_path_pid_prefix_) && defined(_override_controller_path_pid_prefix_length_) #define CONTROLLER_default_path_pid_prefix_s _override_controller_path_pid_prefix_ @@ -172,15 +165,6 @@ extern "C" { #define CONTROLLER_default_path_settings_s_length 2 #endif // defined(_override_controller_path_settings_) && defined(_override_controller_path_settings_length_) - // The init settings path is a system-specific path part and needs to be more easily controlled at compile time. - #if defined(_override_controller_path_settings_init_) && defined(_override_controller_path_settings_init_length_) - #define CONTROLLER_default_path_settings_init_s _override_controller_path_settings_init_ - #define CONTROLLER_default_path_settings_init_s_length _override_controller_path_settings_init_length_ - #else - #define CONTROLLER_default_path_settings_init_s "/etc/controller" - #define CONTROLLER_default_path_settings_init_s_length 15 - #endif // defined(_override_controller_path_settings_init_) && defined(_override_controller_path_settings_init_length_) - // The socket path is a system-specific path and needs to be more easily controlled at compile time. #if defined(_override_controller_path_socket_) && defined(_override_controller_path_socket_length_) #define CONTROLLER_default_path_socket_s _override_controller_path_socket_ @@ -190,15 +174,6 @@ extern "C" { #define CONTROLLER_default_path_socket_s_length 5 #endif // defined(_override_controller_path_socket_) && defined(_override_controller_path_socket_length_) - // The socket path is a system-specific path and needs to be more easily controlled at compile time. - #if defined(_override_controller_path_socket_init_) && defined(_override_controller_path_socket_init_length_) - #define CONTROLLER_default_path_socket_init_s _override_controller_path_socket_init_ - #define CONTROLLER_default_path_socket_init_s_length _override_controller_path_socket_init_length_ - #else - #define CONTROLLER_default_path_socket_init_s "/var/run/controller" - #define CONTROLLER_default_path_socket_init_s_length 19 - #endif // defined(_override_controller_path_socket_init_) && defined(_override_controller_path_socket_init_length_) - // The socket prefix path is a system-specific path part and needs to be more easily controlled at compile time. #if defined(_override_controller_path_socket_prefix_) && defined(_override_controller_path_socket_prefix_length_) #define CONTROLLER_default_path_socket_prefix_s _override_controller_path_socket_prefix_ @@ -227,13 +202,10 @@ extern "C" { extern const f_string_static_t controller_default_engine_s; extern const f_string_static_t controller_default_path_pid_s; - extern const f_string_static_t controller_default_path_pid_init_s; extern const f_string_static_t controller_default_path_pid_prefix_s; extern const f_string_static_t controller_default_path_pid_suffix_s; extern const f_string_static_t controller_default_path_settings_s; - extern const f_string_static_t controller_default_path_settings_init_s; extern const f_string_static_t controller_default_path_socket_s; - extern const f_string_static_t controller_default_path_socket_init_s; extern const f_string_static_t controller_default_path_socket_prefix_s; extern const f_string_static_t controller_default_path_socket_suffix_s; #endif // _di_controller_default_s_ diff --git a/sources/c/main/common/type/process.h b/sources/c/main/common/type/process.h index 170d610..b5db1bd 100644 --- a/sources/c/main/common/type/process.h +++ b/sources/c/main/common/type/process.h @@ -77,7 +77,9 @@ extern "C" { * Delete the Controller process data. * * @param process - * The controller process data. + * A pointer to the current process settings. + * + * Must not be NULL. * * @return * F_okay on success. diff --git a/sources/c/main/common/type/rule.h b/sources/c/main/common/type/rule.h index 2ffcbac..f05607a 100644 --- a/sources/c/main/common/type/rule.h +++ b/sources/c/main/common/type/rule.h @@ -25,7 +25,7 @@ extern "C" { */ #ifndef _di_controller_rule_rerun_item_t_ typedef struct { - bool reset; + uint8_t reset; f_number_unsigned_t count; f_number_unsigned_t delay; diff --git a/sources/c/main/common/type/thread.c b/sources/c/main/common/type/thread.c index 00cf7b6..8a97919 100644 --- a/sources/c/main/common/type/thread.c +++ b/sources/c/main/common/type/thread.c @@ -4,14 +4,16 @@ extern "C" { #endif -#ifndef _di_controller_thread_delete_simple_ - void controller_thread_delete_simple(controller_thread_t * const thread) { +#ifndef _di_controller_thread_delete_ + void controller_thread_delete(controller_thread_t * const thread) { + + if (!thread) return; controller_lock_delete(&thread->lock); controller_process_delete(&thread->process); controller_cache_delete(&thread->cache); } -#endif // _di_controller_thread_delete_simple_ +#endif // _di_controller_thread_delete_ #ifdef __cplusplus } // extern "C" diff --git a/sources/c/main/common/type/thread.h b/sources/c/main/common/type/thread.h index 41c2fc7..a3ddd4d 100644 --- a/sources/c/main/common/type/thread.h +++ b/sources/c/main/common/type/thread.h @@ -33,9 +33,9 @@ extern "C" { * id_rule: The thread ID representing the Rule Process. * id_signal: The thread ID representing the Signal Process. * - * lock: A r/w lock for operating on this structure. + * lock: A r/w lock for operating on this structure. * process: All Rule Process thread data. - * cache: A cache used by the main entry/rule processing thread for synchronous operations. + * cache: A cache used by the main entry/rule processing thread for synchronous operations. */ #ifndef _di_controller_thread_t_ typedef struct { @@ -75,12 +75,15 @@ extern "C" { * @param thread * The thread to deallocate. * + * Must not be NULL. + * * @see controller_asynchronouss_resize() + * * @see f_thread_mutex_unlock() */ -#ifndef _di_controller_thread_delete_simple_ - extern void controller_thread_delete_simple(controller_thread_t * const thread); -#endif // _di_controller_thread_delete_simple_ +#ifndef _di_controller_thread_delete_ + extern void controller_thread_delete(controller_thread_t * const thread); +#endif // _di_controller_thread_delete_ #ifdef __cplusplus } // extern "C" diff --git a/sources/c/main/controller.h b/sources/c/main/controller.h index 73de6cc..0d63508 100644 --- a/sources/c/main/controller.h +++ b/sources/c/main/controller.h @@ -51,6 +51,7 @@ // FLL-1 includes. #include +#include #include // FLL-2 includes. @@ -83,9 +84,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include diff --git a/sources/c/main/path.c b/sources/c/main/path.c new file mode 100644 index 0000000..d113367 --- /dev/null +++ b/sources/c/main/path.c @@ -0,0 +1,40 @@ +#include "controller.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_controller_path_canonical_relative_ + void controller_path_canonical_relative(controller_main_t * const main, const f_string_static_t current, const f_string_static_t source, f_string_dynamic_t * const destination) { + + if (!main || !destination) return; + + main->setting.state.status = fl_path_canonical(source, destination); + if (F_status_is_error(main->setting.state.status)) return; + + if (destination->used >= current.used) { + const f_range_t range = macro_f_range_t_initialize_2(current.used); + + if (f_compare_dynamic_partial_string(destination->string, current, destination->used, range) == F_equal_to) { + f_number_unsigned_t length = destination->used - current.used; + + if (length) { + memmove(destination->string, destination->string + current.used + 1, sizeof(f_char_t) * (--length)); + + destination->string[length] = 0; + destination->used = length; + } + else { + destination->used = 0; + } + } + } + + main->setting.state.status = F_okay; + } +#endif // _di_controller_path_canonical_relative_ + + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/sources/c/main/path.h b/sources/c/main/path.h new file mode 100644 index 0000000..782c161 --- /dev/null +++ b/sources/c/main/path.h @@ -0,0 +1,58 @@ +/** + * FLL - Level 3 + * + * Project: Controller + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides path functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _controller_main_path_h +#define _controller_main_path_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Determine a canonical path and then, if it is relative to the current working directory, make it a relative path. + * + * For example, given the paths "../hello/world/" and "../controller/files/" with a current working directory of "/tmp/controller", then a canonical path for these might look like: + * - "/tmp/hello/world/" + * - "/tmp/controller/files/" + * + * This function would instead result in the following: + * - "/tmp/hello/world/" + * - "files/" + * @param main + * The program and settings data. + * + * Must not be NULL. + * + * This alters setting.state.status: + * F_okay on success. + * + * Errors (with error bit) from: fl_path_canonical(). + * @param current + * The current path, such as process.path_current. + * @param source + * The source path to determine the relative canonical from. + * @param destination + * The resulting relative canonical path. + * The destination will be completely replaced on success. + * + * @see fl_path_canonical() + * + * @see memmove() + */ +#ifndef _di_controller_path_canonical_relative_ + extern void controller_path_canonical_relative(controller_main_t * const main, const f_string_static_t current, const f_string_static_t source, f_string_dynamic_t * const destination); +#endif // _di_controller_path_canonical_relative_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _controller_main_path_h diff --git a/sources/c/main/print/debug.c b/sources/c/main/print/debug.c index 61f0547..62f8447 100644 --- a/sources/c/main/print/debug.c +++ b/sources/c/main/print/debug.c @@ -4,6 +4,26 @@ extern "C" { #endif +#ifndef _di_controller_main_print_debug_directory_path_empty_ + f_status_t controller_main_print_debug_directory_path_empty(fl_print_t * const print, const f_string_static_t symbol, const f_string_static_t name) { + + if (!print || !print->custom) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_debug_e) return F_output_not; + + controller_main_t * const main = (controller_main_t *) print->custom; + + controller_lock_print(print->to, 0); + + fl_print_format("%r%[%QThe parameter '%]", print->to, f_string_eol_s, print->context, print->prefix, print->context); + fl_print_format(f_string_format_rr_single_s.string, print->to, print->set->notable, symbol, name, print->set->notable); + fl_print_format("%[' must be a file directory path but instead is an empty string, falling back to the default.%]%r", print->to, print->context, print->context, f_string_eol_s); + + controller_unlock_print_flush(print->to, 0); + + return F_okay; + } +#endif // _di_controller_main_print_debug_directory_path_empty_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/main/print/debug.h b/sources/c/main/print/debug.h index 1eb6491..2263455 100644 --- a/sources/c/main/print/debug.h +++ b/sources/c/main/print/debug.h @@ -16,6 +16,34 @@ extern "C" { #endif +/** + * Print a debug message about the directory path string being empty. + * + * @param print + * The output structure to print to. + * + * Must not be NULL. + * + * This does not alter print.custom.setting.state.status. + * @param symbol + * The symbol string prepended to the parameter. + * This locks, uses, and unlocks the file stream. + * This is usually f_console_symbol_long_normal_s. + * @param name + * The parameter name. + * + * @return + * F_okay on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + * + * @see fll_error_print() + */ +#ifndef _di_controller_main_print_debug_directory_path_empty_ + extern f_status_t controller_main_print_debug_directory_path_empty(fl_print_t * const print, const f_string_static_t symbol, const f_string_static_t name); +#endif // _di_controller_main_print_debug_directory_path_empty_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/main/print/error.c b/sources/c/main/print/error.c index 23a2be1..0ee495f 100644 --- a/sources/c/main/print/error.c +++ b/sources/c/main/print/error.c @@ -18,6 +18,20 @@ extern "C" { } #endif // _di_controller_main_print_error_ +#ifndef _di_controller_main_print_error_file_ + f_status_t controller_main_print_error_file(fl_print_t * const print, const f_string_t function, const f_string_static_t name, const f_string_static_t operation, const uint8_t type) { + + if (!print || !print->custom) return F_status_set_error(F_output_not); + if (print->verbosity == f_console_verbosity_quiet_e) return F_output_not; + + controller_main_t * const main = (controller_main_t *) print->custom; + + fll_error_file_print(print, F_status_set_fine(main->setting.state.status), function, fll_error_file_flag_fallback_e, name, operation, type); + + return F_okay; + } +#endif // _di_controller_main_print_error_file_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/main/print/error.h b/sources/c/main/print/error.h index 3f67c87..c29205b 100644 --- a/sources/c/main/print/error.h +++ b/sources/c/main/print/error.h @@ -22,6 +22,8 @@ extern "C" { * @param print * The output structure to print to. * + * Must not be NULL. + * * This does not alter print.custom.setting.state.status. * @param function * The name of the function associated with the error. @@ -38,6 +40,39 @@ extern "C" { extern f_status_t controller_main_print_error(fl_print_t * const print, const f_string_t function); #endif // _di_controller_main_print_error_ +/** + * Print file related error or warning messages. + * + * @param print + * The output structure to print to. + * + * Must not be NULL. + * + * The print.custom is expected to be of type fss_read_main_t. + * + * This does not alter print.custom.setting.state.status. + * @param function + * The name of the function where the error happened. + * Set to 0 to disable. + * @param name + * The name of the file or directory. + * @param operation + * The operation that fails, such as 'create' or 'access'. + * @param type + * A valid file type code from the fll_error_file_type enum. + * + * @return + * F_okay on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if a parameter is NULL. + * + * @see fll_error_file_print() + */ +#ifndef _di_controller_main_print_error_file_ + extern f_status_t controller_main_print_error_file(fl_print_t * const print, const f_string_t function, const f_string_static_t name, const f_string_static_t operation, const uint8_t type); +#endif // _di_controller_main_print_error_file_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/main/print/lock.c b/sources/c/main/print/lock.c new file mode 100644 index 0000000..4ff7b13 --- /dev/null +++ b/sources/c/main/print/lock.c @@ -0,0 +1,69 @@ +#include "../controller.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_controller_lock_print_error_critical_ + void controller_lock_print_error_critical(fl_print_t * const print, const f_status_t status, const uint8_t is_read, controller_thread_t *thread) { + + // A signal is not an error. + if (status == F_interrupt) return; + + if (print->verbosity != f_console_verbosity_quiet_e) { + controller_lock_print(print->to, thread); + + fl_print_format("%r%[%QThe pid file '%]", print->to, f_string_eol_s, print->context, print->prefix, print->context); + fl_print_format("%['Critical failure while attempting to establish '%]", print->to, print->context, print->context); + fl_print_format("%[%r lock%]", print->to, print->notable, is_read ? f_file_operation_read_s : f_file_operation_write_s, print->notable); + + if (status != F_failure) { + fl_print_format(" %['due to%] ", print->to, print->context, print->context); + + if (status == F_parameter) { + fl_print_format("%[Invalid Parameter%]", print->to, print->notable, print->notable); + } + else if (status == F_deadlock) { + fl_print_format("%[Deadlock%]", print->to, print->notable, print->notable); + } + else if (status == F_resource_not) { + fl_print_format("%[Too Many Locks%]", print->to, print->notable, print->notable); + } + else { + fl_print_format("%[Unknown Error%]", print->to, print->notable, print->notable); + } + } + + fl_print_format(f_string_format_sentence_end_quote_s.string, print->to, print->context, print->context, f_string_eol_s); + + controller_unlock_print_flush(print->to, thread); + } + } +#endif // _di_controller_lock_print_error_critical_ + +#ifndef _di_controller_lock_print_ + void controller_lock_print(const f_file_t to, controller_thread_t * const thread) { + + if (thread) { + f_thread_mutex_lock(&thread->lock.print); + } + + f_file_stream_lock(to); + } +#endif // _di_controller_lock_print_ + +#ifndef _di_controller_unlock_print_flush_ + void controller_unlock_print_flush(const f_file_t to, controller_thread_t * const thread) { + + f_file_stream_flush(to); + f_file_stream_unlock(to); + + if (thread) { + f_thread_mutex_unlock(&thread->lock.print); + } + } +#endif // _di_controller_unlock_print_flush_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/sources/c/main/print/lock.h b/sources/c/main/print/lock.h new file mode 100644 index 0000000..bf8b41b --- /dev/null +++ b/sources/c/main/print/lock.h @@ -0,0 +1,89 @@ +/** + * FLL - Level 3 + * + * Project: Controller + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the print lock functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _controller_main_print_lock_h +#define _controller_main_print_lock_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print a r/w lock related error message, locking the print mutex during the print. + * + * This will ignore F_interrupt and not print any messages, if passed. + * + * @param print + * The output structure to print to. + * + * Must not be NULL. + * + * This does not alter print.custom.setting.state.status. + * @param status + * The status code to process. + * Make sure this has F_status_set_fine() called if the status code has any error or warning bits. + * @param is_read + * If TRUE, then this is for a read lock. + * If FALSE, then this is for a write lock. + * @param thread + * The thread data. + */ +#ifndef _di_controller_lock_print_error_critical_ + extern void controller_lock_print_error_critical(fl_print_t * const print, const f_status_t status, const uint8_t is_read, controller_thread_t *thread); +#endif // _di_controller_lock_print_error_critical_ + +/** + * Lock the mutex and the stream. + * + * This is implemented as a compliment to controller_unlock_print_flush() for consistency reasons. + * + * @param to + * The file stream to lock. + * @param thread + * (optonal) The thread containing the print mutex to lock. + * Set to NULL to not use. + * + * @see f_file_stream_lock() + * @see f_thread_mutex_unlock() + */ +#ifndef _di_controller_lock_print_ + extern void controller_lock_print(const f_file_t to, controller_thread_t * const thread); +#endif // _di_controller_lock_print_ + +/** + * Flush the stream buffer and then unlock the mutex. + * + * This unlocks both the stream and the mutex locks. + * + * Weird behavior was observed when piping data from this program. + * The behavior appears related to how this handles locks in addition to the file streams own locking mechanisms. + * + * As a work-around, this performs a flush immediately before unlocking the print mutex. + * + * @param to + * The file stream to unlock and flush. + * @param thread + * (optonal) The thread containing the print mutex to unlock. + * Set to NULL to not use. + * + * @see f_file_stream_unlock() + * + * @see f_thread_mutex_unlock() + */ +#ifndef _di_controller_unlock_print_flush_ + void controller_unlock_print_flush(const f_file_t to, controller_thread_t * const thread); +#endif // _di_controller_unlock_print_flush_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _controller_main_print_lock_h diff --git a/sources/c/main/print/message.c b/sources/c/main/print/message.c index d163d08..c04fbcf 100644 --- a/sources/c/main/print/message.c +++ b/sources/c/main/print/message.c @@ -47,7 +47,6 @@ extern "C" { } #endif // _di_controller_main_print_message_help_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/main/thread.h b/sources/c/main/thread.h index 088e795..d6fa55e 100644 --- a/sources/c/main/thread.h +++ b/sources/c/main/thread.h @@ -26,6 +26,8 @@ * @param main * The program and settings data. * + * Must not be NULL. + * * Must be of type controller_main_t. * * @return -- 1.8.3.1