From: Kevin Day Date: Fri, 4 Aug 2023 04:54:38 +0000 (-0500) Subject: Update: Control program to latest design practices, migrating from 0.6.x to 0.7.x... X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=3b78e1e8d482bac8b0ade6748a1836ae3e38e700;p=fll Update: Control program to latest design practices, migrating from 0.6.x to 0.7.x design. This gets the control program to compile under the latest design practices. I did not to an in depth review as this program does not currently do anything. Once the controller program is updated I will eventually come back to this. --- diff --git a/level_3/control/c/common.c b/level_3/control/c/common.c deleted file mode 100644 index a08cbf2..0000000 --- a/level_3/control/c/common.c +++ /dev/null @@ -1,308 +0,0 @@ -#include "control.h" -#include "private-common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _di_control_program_version_s_ - const f_string_static_t control_program_version_s = macro_f_string_static_t_initialize_1(CONTROL_program_version_s, 0, CONTROL_program_version_s_length); -#endif // _di_control_program_version_s_ - -#ifndef _di_control_program_name_s_ - const f_string_static_t control_program_name_s = macro_f_string_static_t_initialize_1(CONTROL_program_name_s, 0, CONTROL_program_name_s_length); - const f_string_static_t control_program_name_long_s = macro_f_string_static_t_initialize_1(CONTROL_program_name_long_s, 0, CONTROL_program_name_long_s_length); -#endif // _di_control_program_name_s_ - -#ifndef _di_control_parameter_d_ - const f_string_static_t control_short_name_s = macro_f_string_static_t_initialize_1(CONTROL_short_name_s, 0, CONTROL_short_name_s_length); - const f_string_static_t control_short_return_s = macro_f_string_static_t_initialize_1(CONTROL_short_return_s, 0, CONTROL_short_return_s_length); - const f_string_static_t control_short_settings_s = macro_f_string_static_t_initialize_1(CONTROL_short_settings_s, 0, CONTROL_short_settings_s_length); - const f_string_static_t control_short_socket_s = macro_f_string_static_t_initialize_1(CONTROL_short_socket_s, 0, CONTROL_short_socket_s_length); - - const f_string_static_t control_long_name_s = macro_f_string_static_t_initialize_1(CONTROL_long_name_s, 0, CONTROL_long_name_s_length); - const f_string_static_t control_long_return_s = macro_f_string_static_t_initialize_1(CONTROL_long_return_s, 0, CONTROL_long_return_s_length); - const f_string_static_t control_long_settings_s = macro_f_string_static_t_initialize_1(CONTROL_long_settings_s, 0, CONTROL_long_settings_s_length); - const f_string_static_t control_long_socket_s = macro_f_string_static_t_initialize_1(CONTROL_long_socket_s, 0, CONTROL_long_socket_s_length); -#endif // _di_control_parameter_d_ - -#ifndef _di_control_action_type_identify_ - uint8_t control_action_type_identify(const f_string_static_t action) { - - if (f_compare_dynamic(action, control_freeze_s) == F_equal_to) { - return control_action_type_freeze_e; - } - - if (f_compare_dynamic(action, control_kexec_s) == F_equal_to) { - return control_action_type_kexec_e; - } - - if (f_compare_dynamic(action, control_kill_s) == F_equal_to) { - return control_action_type_kill_e; - } - - if (f_compare_dynamic(action, control_pause_s) == F_equal_to) { - return control_action_type_pause_e; - } - - if (f_compare_dynamic(action, control_reboot_s) == F_equal_to) { - return control_action_type_reboot_e; - } - - if (f_compare_dynamic(action, control_reload_s) == F_equal_to) { - return control_action_type_reload_e; - } - - if (f_compare_dynamic(action, control_rerun_s) == F_equal_to) { - return control_action_type_rerun_e; - } - - if (f_compare_dynamic(action, control_restart_s) == F_equal_to) { - return control_action_type_restart_e; - } - - if (f_compare_dynamic(action, control_resume_s) == F_equal_to) { - return control_action_type_resume_e; - } - - if (f_compare_dynamic(action, control_shutdown_s) == F_equal_to) { - return control_action_type_shutdown_e; - } - - if (f_compare_dynamic(action, control_start_s) == F_equal_to) { - return control_action_type_start_e; - } - - if (f_compare_dynamic(action, control_stop_s) == F_equal_to) { - return control_action_type_stop_e; - } - - if (f_compare_dynamic(action, control_thaw_s) == F_equal_to) { - return control_action_type_thaw_e; - } - - return 0; - } -#endif // _di_control_action_type_identify_ - -#ifndef _di_control_action_type_name_ - f_string_static_t control_action_type_name(const uint8_t type) { - - switch (type) { - case control_action_type_freeze_e: - return control_freeze_s; - - case control_action_type_kexec_e: - return control_kexec_s; - - case control_action_type_kill_e: - return control_kill_s; - - case control_action_type_pause_e: - return control_pause_s; - - case control_action_type_reboot_e: - return control_reboot_s; - - case control_action_type_reload_e: - return control_reload_s; - - case control_action_type_rerun_e: - return control_rerun_s; - - case control_action_type_restart_e: - return control_restart_s; - - case control_action_type_resume_e: - return control_resume_s; - - case control_action_type_shutdown_e: - return control_shutdown_s; - - case control_action_type_start_e: - return control_start_s; - - case control_action_type_stop_e: - return control_stop_s; - - case control_action_type_thaw_e: - return control_thaw_s; - } - - return f_string_empty_s; - } -#endif // _di_control_action_type_name_ - -#ifndef _di_control_payload_type_identify_ - uint8_t control_payload_type_identify(const f_string_static_t payload) { - - if (f_compare_dynamic(payload, control_controller_s) == F_equal_to) { - return control_payload_type_controller_e; - } - - if (f_compare_dynamic(payload, control_error_s) == F_equal_to) { - return control_payload_type_error_e; - } - - if (f_compare_dynamic(payload, control_init_s) == F_equal_to) { - return control_payload_type_init_e; - } - - return 0; - } -#endif // _di_control_payload_type_identify_ - -#ifndef _di_control_payload_type_name_ - f_string_static_t control_payload_type_name(const uint8_t type) { - - switch (type) { - case control_payload_type_controller_e: - return control_controller_s; - - case control_payload_type_error_e: - return control_error_s; - - case control_payload_type_init_e: - return control_init_s; - } - - return f_string_empty_s; - } -#endif // _di_control_payload_type_name_ - -#ifndef _di_control_setting_delete_ - f_status_t control_setting_delete(control_setting_t * const setting) { - - if (!setting) return F_status_set_error(F_parameter); - - return F_none; - } -#endif // _di_control_setting_delete_ - -#ifndef _di_control_setting_load_ - void control_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, control_setting_t * const setting) { - - if (!main) return; - - setting->state.step_small = control_allocation_console_d; - - f_console_parameter_process(arguments, &main->parameters, &setting->state, 0); - - setting->state.step_small = control_write_allocation_small_d; - - // Identify and process first/last parameters. - if (main->parameters.array[control_parameter_line_first_no_e].result & f_console_result_found_e) { - setting->flag -= setting->flag & control_main_flag_print_first_e; - } - else { - setting->flag |= control_main_flag_print_first_e; - } - - if (main->parameters.array[control_parameter_line_last_no_e].result & f_console_result_found_e) { - setting->flag -= setting->flag & control_main_flag_print_last_e; - } - else { - setting->flag |= control_main_flag_print_last_e; - } - - if (F_status_is_error(setting->state.status)) { - fll_error_print(main->error, F_status_set_fine(setting->state.status), "f_console_parameter_process", fll_error_file_flag_fallback_e); - - if (main->error.verbosity > f_console_verbosity_quiet_e) { - fll_print_dynamic_raw(f_string_eol_s, main->error); - } - - return; - } - - { - f_number_unsigned_t choice = 0; - f_uint16s_t choices = f_uint16s_t_initialize; - - // Identify and prioritize "color context" parameters. - { - uint16_t choices_array[3] = { control_parameter_no_color_e, control_parameter_light_e, control_parameter_dark_e }; - choices.array = choices_array; - choices.used = 3; - - static const uint8_t modes[3] = { f_color_mode_not_e, f_color_mode_light_e, f_color_mode_dark_e }; - - setting->state.status = fll_program_parameter_process_context(choices, modes, F_true, &main->program); - - if (F_status_is_error(setting->state.status)) { - fll_error_print(main->error, F_status_set_fine(setting->state.status), "fll_program_parameter_process_context", fll_error_file_flag_fallback_e); - - if (main->error.verbosity > f_console_verbosity_quiet_e) { - fll_print_dynamic_raw(f_string_eol_s, main->error); - } - - return; - } - } - - // Identify and prioritize "verbosity" parameters. - { - uint16_t choices_array[5] = { control_parameter_verbosity_quiet_e, control_parameter_verbosity_error_e, control_parameter_verbosity_verbose_e, control_parameter_verbosity_debug_e, control_parameter_verbosity_normal_e }; - choices.array = choices_array; - choices.used = 5; - - static const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; - - setting->state.status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, &main->program); - - if (F_status_is_error(setting->state.status)) { - fll_error_print(main->error, F_status_set_fine(setting->state.status), "fll_program_parameter_process_verbosity", fll_error_file_flag_fallback_e); - - if (main->error.verbosity > f_console_verbosity_quiet_e) { - fll_print_dynamic_raw(f_string_eol_s, main->error); - } - - return; - } - } - } - - main->output.to.id = F_type_descriptor_output_d; - main->output.to.stream = F_type_output_d; - main->output.to.flag = F_file_flag_create_d | F_file_flag_write_only_d | F_file_flag_append_d; - - if (main->parameters.array[control_parameter_help_e].result & f_console_result_found_e) { - setting->flag |= control_main_flag_help_e; - - return; - } - - if (main->parameters.array[control_parameter_version_e].result & f_console_result_found_e) { - setting->flag |= control_main_flag_version_e; - - return; - } - - if (main->parameters.array[control_parameter_copyright_e].result & f_console_result_found_e) { - setting->flag |= control_main_flag_copyright_e; - - return; - } - - f_string_static_t * const args = main->parameters.arguments.array; - - if (main->parameters.array[control_parameter_strip_invalid_e].result & f_console_result_found_e) { - setting->flag |= control_main_flag_strip_invalid_e; - } - } -#endif // _di_control_setting_load_ - -#ifndef _di_control_setting_unload_ - f_status_t control_setting_unload(control_main_t * const main) { - - if (!main) return F_status_set_error(F_parameter); - - control_setting_delete(&control_main_t->setting); - - return F_none; - } -#endif // _di_control_setting_unload_ - -#ifdef __cplusplus -} // extern "C" -#endif diff --git a/level_3/control/c/common.h b/level_3/control/c/common.h deleted file mode 100644 index d3f1cd0..0000000 --- a/level_3/control/c/common.h +++ /dev/null @@ -1,380 +0,0 @@ -/** - * FLL - Level 3 - * - * Project: Control - * API Version: 0.7 - * Licenses: lgpl-2.1-or-later - * - * Provides the common data structures. - * - * This is auto-included and should not need to be explicitly included. - */ -#ifndef _control_common_h -#define _control_common_h - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The program version. - */ -#ifndef _di_control_program_version_s_ - #define CONTROL_program_version_major_s F_string_ascii_0_s - #define CONTROL_program_version_minor_s F_string_ascii_7_s - #define CONTROL_program_version_micro_s F_string_ascii_0_s - - #define CONTROL_program_version_major_s_length F_string_ascii_0_s_length - #define CONTROL_program_version_minor_s_length F_string_ascii_7_s_length - #define CONTROL_program_version_micro_s_length F_string_ascii_0_s_length - - #if !(defined(CONTROL_program_version_nano_prefix_s) && defined(CONTROL_program_version_nano_prefix_s_length)) - #define CONTROL_program_version_nano_prefix_s - #define CONTROL_program_version_nano_prefix_s_length 0 - #endif // !(defined(CONTROL_program_version_nano_prefix_s) && defined(CONTROL_program_version_nano_prefix_s_length)) - - #if !(defined(CONTROL_program_version_nano_s) && defined(CONTROL_program_version_nano_s_length)) - #define CONTROL_program_version_nano_s - #define CONTROL_program_version_nano_s_length 0 - #endif // !(defined(CONTROL_program_version_nano_s) && defined(CONTROL_program_version_nano_s_length)) - - #define CONTROL_program_version_s CONTROL_program_version_major_s F_string_ascii_period_s CONTROL_program_version_minor_s F_string_ascii_period_s CONTROL_program_version_micro_s CONTROL_program_version_nano_prefix_s CONTROL_program_version_nano_s - - #define CONTROL_program_version_s_length CONTROL_program_version_major_s_length + F_string_ascii_period_s_length + CONTROL_program_version_minor_s_length + F_string_ascii_period_s_length + CONTROL_program_version_micro_s_length + CONTROL_program_version_nano_prefix_s_length + CONTROL_program_version_nano_s_length - - extern const f_string_static_t control_program_version_s; -#endif // _di_control_program_version_s_ - -/** - * The program name. - */ -#ifndef _di_control_program_name_s_ - #define CONTROL_program_name_s "control" - #define CONTROL_program_name_long_s "Control Program" - - #define CONTROL_program_name_s_length 7 - #define CONTROL_program_name_long_s_length 15 - - extern const f_string_static_t control_program_name_s; - extern const f_string_static_t control_program_name_long_s; -#endif // _di_control_program_name_s_ - -/** - * The program defines. - * - * control_*_d: - * - allocation_console: An allocation step used for small buffers specifically for console parameter. - * - allocation_large: An allocation step used for buffers that are anticipated to have large buffers. - * - allocation_small: An allocation step used for buffers that are anticipated to have small buffers. - * - signal_check: Number of iterations before performing signal check in non-threaded signal handling. - */ -#ifndef _di_control_d_ - #define control_allocation_console_d 4 - #define control_allocation_large_d 256 - #define control_allocation_small_d 16 - #define control_signal_check_d 20000 -#endif // _di_control_d_ - -/** - * The main program parameters. - */ -#ifndef _di_control_parameter_d_ - #define CONTROL_short_name_s "n" - #define CONTROL_short_return_s "R" - #define CONTROL_short_settings_s "s" - #define CONTROL_short_socket_s "k" - - #define CONTROL_long_name_s "name" - #define CONTROL_long_return_s "return" - #define CONTROL_long_settings_s "settings" - #define CONTROL_long_socket_s "socket" - - #define CONTROL_short_name_s_length 1 - #define CONTROL_short_return_s_length 1 - #define CONTROL_short_settings_s_length 1 - #define CONTROL_short_socket_s_length 1 - - #define CONTROL_long_name_s_length 4 - #define CONTROL_long_return_s_length 6 - #define CONTROL_long_settings_s_length 8 - #define CONTROL_long_socket_s_length 6 - - extern const f_string_static_t control_short_name_s; - extern const f_string_static_t control_short_return_s; - extern const f_string_static_t control_short_settings_s; - extern const f_string_static_t control_short_socket_s; - - extern const f_string_static_t control_long_name_s; - extern const f_string_static_t control_long_return_s; - extern const f_string_static_t control_long_settings_s; - extern const f_string_static_t control_long_socket_s; - - enum { - control_parameter_help_e = 0, - control_parameter_copyright_e, - control_parameter_light_e, - control_parameter_dark_e, - control_parameter_no_color_e, - control_parameter_verbosity_quiet_e, - control_parameter_verbosity_error_e, - control_parameter_verbosity_normal_e, - control_parameter_verbosity_verbose_e, - control_parameter_verbosity_debug_e, - control_parameter_version_e, - control_parameter_line_first_no_e, - control_parameter_line_last_no_e, - - control_parameter_name_e, - control_parameter_return_e, - control_parameter_settings_e, - control_parameter_socket_e, - }; // enum - - #define control_console_parameter_t_initialize \ - { \ - macro_fll_program_console_parameter_standard_initialize, \ - \ - macro_f_console_parameter_t_initialize_3(control_short_name_s, control_long_name_s, 1, f_console_flag_normal_e), \ - macro_f_console_parameter_t_initialize_3(control_short_return_s, control_long_return_s, 1, f_console_flag_normal_e), \ - macro_f_console_parameter_t_initialize_3(control_short_settings_s, control_long_settings_s, 1, f_console_flag_normal_e), \ - macro_f_console_parameter_t_initialize_3(control_short_socket_s, control_long_socket_s, 1, f_console_flag_normal_e), \ - } - - #define control_parameter_total_d 17 -#endif // _di_control_parameter_d_ - -/** - * Codes representing supported actions. - * - * freeze: Perform the freeze controller operation. - * kexec: Perform the kexec controller operation (only for init mode). - * kill: Perform the kill controller operation. - * pause: Perform the pause controller operation. - * reboot: Perform the reboot controller operation (only for init mode). - * reload: Perform the reload controller operation. - * rerun: Perform the rerun controller operation. - * restart: Perform the restart controller operation. - * resume: Perform the resume controller operation. - * shutdown: Perform the shutdown controller operation (only for init mode). - * start: Perform the start controller operation. - * stop: Perform the stop controller operation. - * thaw: Perform the thaw controller operation. - */ -#ifndef _di_control_action_type_e_ - enum { - control_action_type_freeze_e = 1, - control_action_type_kexec_e, - control_action_type_kill_e, - control_action_type_pause_e, - control_action_type_reboot_e, - control_action_type_reload_e, - control_action_type_rerun_e, - control_action_type_restart_e, - control_action_type_resume_e, - control_action_type_shutdown_e, - control_action_type_start_e, - control_action_type_stop_e, - control_action_type_thaw_e, - }; // enum -#endif // _di_control_action_type_e_ - -/** - * Supported payload types. - * - * controller: The payload is a controller payload. - * error: The payload is an error payload. - * init: The payload is an init payload (only available when operating in "init" mode). - */ -#ifndef _di_control_payload_type_e_ - enum { - control_payload_type_controller_e = 1, - control_payload_type_error_e, - control_payload_type_init_e, - }; // enum -#endif // _di_control_payload_type_e_ - -/** - * Flags passed to the main function or program. - * - * control_main_flag_*_e: - * - none: No flags set. - * - copyright: Print copyright. - * - file_from: Using a specified source file. - * - file_to: Using a specified destination file. - * - header: Enable printing of headers. - * - help: Print help. - * - 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. - * - separate: Enable printing of separators. - * - strip_invalid: Using strip invalid character mode. - * - verify: Using verify mode. - * - version: Print version. - */ -#ifndef _di_control_main_flag_e_ - enum { - control_main_flag_none_e = 0x0, - control_main_flag_copyright_e = 0x1, - control_main_flag_file_from_e = 0x2, - control_main_flag_file_to_e = 0x4, - control_main_flag_header_e = 0x8, - control_main_flag_help_e = 0x10, - control_main_flag_print_first_e = 0x20, - control_main_flag_print_last_e = 0x40, - control_main_flag_separate_e = 0x80, - control_main_flag_strip_invalid_e = 0x100, - control_main_flag_verify_e = 0x200, - control_main_flag_version_e = 0x400, - }; // enum -#endif // _di_control_main_flag_e_ - -/** - * The control main program settings. - * - * This is passed to the program-specific main entry point to designate program settings. - * These program settings are often processed from the program arguments (often called the command line arguments). - * - * flag: Flags passed to the main function. - * - * state: The state information. - */ -#ifndef _di_control_setting_t_ - typedef struct { - uint16_t flag; - - f_state_t state; - } control_setting_t; - - #define control_setting_t_initialize \ - { \ - control_main_flag_none_e, \ - f_state_t_initialize, \ - } -#endif // _di_control_setting_t_ - -/** - * Identify the action code the given name represents. - * - * @param action - * The string representing an action. - * - * @return - * The action type code on success. - * 0 if name is unknown. - */ -#ifndef _di_control_action_type_identify_ - extern uint8_t control_action_type_identify(const f_string_static_t action); -#endif // _di_control_action_type_identify_ - -/** - * Get a string representing the action type. - * - * @param type - * The action type id. - * - * @return - * The string with used > 0 on success. - * The string with used == 0 if no match was found. - */ -#ifndef _di_control_action_type_name_ - extern f_string_static_t control_action_type_name(const uint8_t type); -#endif // _di_control_action_type_name_ - -/** - * Identify the payload code the given name represents. - * - * @param payload - * The string representing a payload. - * - * @return - * The payload type code on success. - * 0 if name is unknown. - */ -#ifndef _di_control_payload_type_identify_ - extern uint8_t control_payload_type_identify(const f_string_static_t payload); -#endif // _di_control_payload_type_identify_ - -/** - * Get a string representing the payload type. - * - * @param type - * The payload type id. - * - * @return - * The string with used > 0 on success. - * The string with used == 0 if no match was found. - */ -#ifndef _di_control_payload_type_name_ - extern f_string_static_t control_payload_type_name(const uint8_t type); -#endif // _di_control_payload_type_name_ - -/** - * Delete the program main setting data. - * - * @param setting - * The program main setting data. - * - * This does not alter setting.state.status. - * - * @return - * F_none on success. - * - * F_parameter (with error bit) if a parameter is invalid. - */ -#ifndef _di_control_setting_delete_ - extern f_status_t control_setting_delete(control_setting_t * const setting); -#endif // _di_control_setting_delete_ - -/** - * Perform the standard program setting load process. - * - * This prints error messages as appropriate. - * - * If either main or setting is NULL, then this immediately returns without doing anything. - * - * @param arguments - * The parameters passed to the process (often referred to as command line arguments). - * @param main - * The main program data. - * @param setting - * The main program settings. - * - * This alters setting.state.status: - * F_none on success. - * - * Errors (with error bit) from: f_console_parameter_process(). - * Errors (with error bit) from: fll_program_parameter_process_context(). - * - * @see f_console_parameter_process() - * @see fll_program_parameter_process_context() - */ -#ifndef _di_control_setting_load_ - extern void control_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, control_setting_t * const setting); -#endif // _di_control_setting_load_ - -/** - * Perform the standard program setting unload process. - * - * @param main - * The main program and setting data. - * All buffers are deallocated. - * - * This does not alter main.setting.state.status. - * - * @return - * F_none on success. - * - * F_parameter (with error bit) if a parameter is invalid. - * - * Errors (with error bit) from: control_setting_delete(). - * - * @see control_setting_delete() - */ -#ifndef _di_control_setting_unload_ - extern f_status_t control_setting_unload(control_main_t * const main); -#endif // _di_control_setting_unload_ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // _control_common_h diff --git a/level_3/control/c/control.c b/level_3/control/c/control.c deleted file mode 100644 index 3774ccb..0000000 --- a/level_3/control/c/control.c +++ /dev/null @@ -1,233 +0,0 @@ -#include "control.h" -#include "private-common.h" -#include "private-control.h" -#include "private-print.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _di_control_main_ - f_status_t control_main(fll_program_data_t * const main, control_setting_t * const setting) { - - f_status_t status = F_none; - - setting->state.step_small = control_allocation_console_d; - - status = f_console_parameter_process(arguments, &main->parameters, &setting->state, 0); - - setting->state.step_small = control_allocation_small_d; - - if (F_status_is_error(status)) return; - - { - f_number_unsigned_t choice = 0; - f_uint16s_t choices = f_uint16s_t_initialize; - - // Identify and prioritize "color context" parameters. - { - uint16_t choices_array[3] = { control_parameter_no_color_e, control_parameter_light_e, control_parameter_dark_e }; - choices.array = choices_array; - choices.used = 3; - - static const uint8_t modes[3] = { f_color_mode_not_e, f_color_mode_light_e, f_color_mode_dark_e }; - - status = fll_program_parameter_process_context(choices, modes, F_true, &main->program); - - if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "fll_program_parameter_process_context", fll_error_file_flag_fallback_e); - - if (main->error.verbosity > f_console_verbosity_quiet_e) { - fll_print_dynamic_raw(f_string_eol_s, main->error); - } - - return; - } - } - - // Identify and prioritize "verbosity" parameters. - { - uint16_t choices_array[5] = { control_parameter_verbosity_quiet_e, control_parameter_verbosity_error_e, control_parameter_verbosity_verbose_e, control_parameter_verbosity_debug_e, control_parameter_verbosity_normal_e }; - choices.array = choices_array; - choices.used = 5; - - const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; - - status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, &main->program); - - if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "fll_program_parameter_process_verbosity", fll_error_file_flag_fallback_e); - - if (main->error.verbosity > f_console_verbosity_quiet_e) { - fll_print_dynamic_raw(f_string_eol_s, main->error); - } - - return; - } - } - } - - if (main->parameters.array[control_parameter_help_e].result & f_console_result_found_e) { - control_print_help(main); - - return F_none; - } - - if (main->parameters.array[control_parameter_version_e].result & f_console_result_found_e) { - fll_program_print_version(&main->message, control_program_version_s); - - return F_none; - } - - if (main->parameters.array[control_parameter_copyright_e].result & f_console_result_found_e) { - fll_program_print_copyright(&main->message); - - return F_none; - } - - status = F_none; - - { - uint8_t ids[] = { - control_parameter_name_e, - control_parameter_settings_e, - control_parameter_socket_e - }; - - f_string_static_t names[] = { - control_long_name_s, - control_long_settings_s, - control_long_socket_s - }; - - f_number_unsigned_t index = f_number_unsigned_t_initialize; - - for (uint8_t i = 0; i < 3; ++i) { - - if (main->parameters.array[ids[i]].result & f_console_result_found_e) { - control_print_error_parameter_value_not(main, names[i]); - - status = F_status_set_error(F_parameter); - } - else if (main->parameters.array[ids[i]].result & f_console_result_value_e) { - index = main->parameters.array[ids[i]].values.array[main->parameters.array[ids[i]].values.used - 1]; - - if (!main->parameters.arguments.array[index].used) { - control_print_error_parameter_value_empty(main, names[i]); - - status = F_status_set_error(F_parameter); - } - } - } // for - } - - if (F_status_is_error_not(status)) { - if (main->pipe & fll_program_data_pipe_input_e) { - control_print_error_pipe_supported_not(main); - - status = F_status_set_error(F_support_not); - } - else if (main->parameters.remaining.used) { - control_data_t data = control_data_t_initialize; - data.argv = main->parameters.arguments.array; - - data.action = control_action_type_identify(data.argv[main->parameters.remaining.array[0]]); - - if (data.action) { - status = control_action_verify(main, &data); - } - else { - control_print_error_parameter_action_not(main, data.argv[main->parameters.remaining.array[0]]); - - status = F_status_set_error(F_parameter); - } - - if (F_status_is_error_not(status)) { - struct sockaddr_un socket_address; - - memset(&socket_address, 0, sizeof(struct sockaddr_un)); - - data.socket.address = (struct sockaddr *) &socket_address; - data.socket.domain = f_socket_protocol_family_local_e; - data.socket.type = f_socket_type_stream_d; - data.socket.length = sizeof(struct sockaddr_un); - - status = control_settings_load(main, &data); - - if (F_status_is_error_not(status)) { - status = control_packet_build(main, &data); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_too_large) { - control_print_error_request_packet_too_large(main); - } - else { - fll_error_print(main->error, F_status_set_fine(status), "control_packet_build", fll_error_file_flag_fallback_e); - } - } - } - - if (F_status_is_error_not(status)) { - status = control_packet_send(main, &data); - - if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "control_packet_send", fll_error_file_flag_fallback_e); - } - } - - if (F_status_is_error_not(status)) { - control_payload_header_t header = control_payload_header_t_initialize; - - status = control_packet_receive(main, &data, &header); - - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_too_large) { - control_print_error_response_packet_valid_not(main); - } - else { - fll_error_print(main->error, F_status_set_fine(status), "control_packet_receive", fll_error_file_flag_fallback_e); - } - } - else { - status = control_packet_process(main, &data, &header); - - // Print the error message only if the error message is not already printed. - if (F_status_is_error(status)) { - if (header.type != control_payload_type_error_e && (header.type != control_payload_type_controller_e || F_status_set_fine(status) != header.status || (header.status != F_failure && header.status != F_busy))) { - fll_error_print(main->error, F_status_set_fine(status), "control_packet_process", fll_error_file_flag_fallback_e); - } - } - } - } - - if (data.socket.id != -1) { - f_socket_disconnect(&data.socket, f_socket_close_fast_e); - } - } - - control_data_delete(&data); - } - else { - control_print_error_parameter_actions_none(main); - - status = F_status_set_error(F_data_not); - } - } - - // Ensure a newline is always put at the end of the program execution, unless in quiet mode. - if (main->output.verbosity != f_console_verbosity_quiet_e) { - if (F_status_is_error(status)) { - f_file_stream_flush(main->output.to); - f_file_stream_flush(main->error.to); - - fll_print_dynamic_raw(f_string_eol_s, main->output.to); - } - } - - return status; - } -#endif // _di_control_main_ - -#ifdef __cplusplus -} // extern "C" -#endif diff --git a/level_3/control/c/main.c b/level_3/control/c/main.c deleted file mode 100644 index 5f2c556..0000000 --- a/level_3/control/c/main.c +++ /dev/null @@ -1,44 +0,0 @@ -#include "control.h" - -int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - - control_main_t data = control_main_t_initialize; - - data.program.debug.flag |= control_print_flag_debug_e | control_print_flag_out_e; - data.program.error.flag |= control_print_flag_error_e | control_print_flag_out_e; - data.program.output.flag |= control_print_flag_out_e; - data.program.message.flag |= control_print_flag_message_e | control_print_flag_out_e; - data.program.warning.flag |= control_print_flag_warning_e | control_print_flag_out_e; - data.program.error.custom = (void *) &data; - data.program.debug.custom = (void *) &data; - data.program.message.custom = (void *) &data; - data.program.output.custom = (void *) &data; - data.program.warning.custom = (void *) &data; - - f_console_parameter_t parameters[] = control_console_parameter_t_initialize; - data.program.parameters.array = parameters; - data.program.parameters.used = control_parameter_total_d; - data.program.environment = envp; - - if (f_pipe_input_exists()) { - data.program.pipe = fll_program_data_pipe_input_e; - } - - fll_program_standard_set_up(&data.program); - - { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp); - - control_setting_load(arguments, &data); - } - - control_main(&data); - - control_setting_unload(&data); - - fll_program_data_delete(&data.program); - - fll_program_standard_set_down(&data.program); - - return F_status_is_error(data.setting.state.status) ? 1 : 0; -} diff --git a/level_3/control/c/main/action.c b/level_3/control/c/main/action.c new file mode 100644 index 0000000..8328380 --- /dev/null +++ b/level_3/control/c/main/action.c @@ -0,0 +1,233 @@ +#include "control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_control_action_type_identify_ + const uint8_t control_action_type_identify(const f_string_static_t action) { + + if (f_compare_dynamic(action, control_freeze_s) == F_equal_to) return control_action_type_freeze_e; + if (f_compare_dynamic(action, control_kexec_s) == F_equal_to) return control_action_type_kexec_e; + if (f_compare_dynamic(action, control_kill_s) == F_equal_to) return control_action_type_kill_e; + if (f_compare_dynamic(action, control_pause_s) == F_equal_to) return control_action_type_pause_e; + if (f_compare_dynamic(action, control_reboot_s) == F_equal_to) return control_action_type_reboot_e; + if (f_compare_dynamic(action, control_reload_s) == F_equal_to) return control_action_type_reload_e; + if (f_compare_dynamic(action, control_rerun_s) == F_equal_to) return control_action_type_rerun_e; + if (f_compare_dynamic(action, control_restart_s) == F_equal_to) return control_action_type_restart_e; + if (f_compare_dynamic(action, control_resume_s) == F_equal_to) return control_action_type_resume_e; + if (f_compare_dynamic(action, control_shutdown_s) == F_equal_to) return control_action_type_shutdown_e; + if (f_compare_dynamic(action, control_start_s) == F_equal_to) return control_action_type_start_e; + if (f_compare_dynamic(action, control_stop_s) == F_equal_to) return control_action_type_stop_e; + if (f_compare_dynamic(action, control_thaw_s) == F_equal_to) return control_action_type_thaw_e; + + return 0; + } +#endif // _di_control_action_type_identify_ + +#ifndef _di_control_action_type_name_ + const f_string_static_t control_action_type_name(const uint8_t type) { + + switch (type) { + case control_action_type_freeze_e: + return control_freeze_s; + + case control_action_type_kexec_e: + return control_kexec_s; + + case control_action_type_kill_e: + return control_kill_s; + + case control_action_type_pause_e: + return control_pause_s; + + case control_action_type_reboot_e: + return control_reboot_s; + + case control_action_type_reload_e: + return control_reload_s; + + case control_action_type_rerun_e: + return control_rerun_s; + + case control_action_type_restart_e: + return control_restart_s; + + case control_action_type_resume_e: + return control_resume_s; + + case control_action_type_shutdown_e: + return control_shutdown_s; + + case control_action_type_start_e: + return control_start_s; + + case control_action_type_stop_e: + return control_stop_s; + + case control_action_type_thaw_e: + return control_thaw_s; + } + + return f_string_empty_s; + } +#endif // _di_control_action_type_name_ + +#ifndef _di_control_action_verify_ + void control_action_verify(control_main_t * const main) { + + if (!main) return; + + switch (main->setting.action) { + case control_action_type_freeze_e: + case control_action_type_kill_e: + case control_action_type_pause_e: + case control_action_type_reload_e: + case control_action_type_rerun_e: + case control_action_type_restart_e: + case control_action_type_resume_e: + case control_action_type_start_e: + case control_action_type_stop_e: + case control_action_type_thaw_e: + if (main->setting.actions.used < 3) { + control_print_error_parameter_action_rule_not(&main->program.error, main->setting.actions.array[0]); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + + if (main->setting.actions.used > 3) { + if (f_compare_dynamic(control_at_s, main->setting.actions.array[3]) == F_equal_to) { + if (main->setting.actions.used < 5) { + control_print_error_parameter_action_rule_too_few_with(&main->program.error, main->setting.actions.array[0], control_at_s); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + + if (main->setting.actions.used > 5) { + control_print_error_parameter_action_rule_too_many_with(&main->program.error, main->setting.actions.array[0], control_at_s); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + } + else if (f_compare_dynamic(control_in_s, main->setting.actions.array[3]) == F_equal_to) { + if (main->setting.actions.used < 6) { + control_print_error_parameter_action_rule_too_few_with(&main->program.error, main->setting.actions.array[0], control_in_s); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + } + else if (f_compare_dynamic(control_now_s, main->setting.actions.array[3]) == F_equal_to) { + if (main->setting.actions.used > 4) { + control_print_error_parameter_action_rule_too_many_with(&main->program.error, main->setting.actions.array[0], control_now_s); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + } + else { + control_print_error_parameter_action_rule_with_unknown(&main->program.error, main->setting.actions.array[0], main->setting.actions.array[2]); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + } + + if (!main->setting.actions.array[1].used) { + if (main->setting.actions.used == 3) { + control_print_error_parameter_action_rule_empty(&main->program.error, main->setting.actions.array[0]); + } + else { + control_print_error_parameter_action_rule_directory_empty(&main->program.error, main->setting.actions.array[0]); + } + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + + if (main->setting.actions.used == 3) { + if (!main->setting.actions.array[2].used) { + control_print_error_parameter_action_rule_basename_empty(&main->program.error, main->setting.actions.array[0]); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + } + + main->setting.state.status = F_none; + + return; + + case control_action_type_kexec_e: + case control_action_type_reboot_e: + case control_action_type_shutdown_e: + if (main->setting.actions.used < 2) { + control_print_error_parameter_action_rule_too_few(&main->program.error, main->setting.actions.array[0]); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + + if (f_compare_dynamic(control_at_s, main->setting.actions.array[1]) == F_equal_to) { + if (main->setting.actions.used < 3) { + control_print_error_parameter_action_rule_too_few_with(&main->program.error, main->setting.actions.array[0], control_at_s); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + + if (main->setting.actions.used > 3) { + control_print_error_parameter_action_rule_too_many_with(&main->program.error, main->setting.actions.array[0], control_at_s); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + } + else if (f_compare_dynamic(control_in_s, main->setting.actions.array[1]) == F_equal_to) { + if (main->setting.actions.used < 4) { + control_print_error_parameter_action_rule_too_few_with(&main->program.error, main->setting.actions.array[0], control_in_s); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + } + else if (f_compare_dynamic(control_now_s, main->setting.actions.array[1]) == F_equal_to) { + if (main->setting.actions.used > 2) { + control_print_error_parameter_action_rule_too_many_with(&main->program.error, main->setting.actions.array[0], control_now_s); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + } + else { + control_print_error_parameter_action_rule_with_unknown(&main->program.error, main->setting.actions.array[0], main->setting.actions.array[1]); + + main->setting.state.status = F_status_set_error(F_parameter); + + return; + } + } + + main->setting.state.status = F_none; + } +#endif // _di_control_action_verify_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/action.h b/level_3/control/c/main/action.h new file mode 100644 index 0000000..71cf354 --- /dev/null +++ b/level_3/control/c/main/action.h @@ -0,0 +1,66 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the action functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_action_h +#define _control_action_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Identify the action code the given name represents. + * + * @param action + * The string representing an action. + * + * @return + * The action type code on success. + * 0 if name is unknown. + */ +#ifndef _di_control_action_type_identify_ + extern const uint8_t control_action_type_identify(const f_string_static_t action); +#endif // _di_control_action_type_identify_ + +/** + * Get a string representing the action type. + * + * @param type + * The action type id. + * + * @return + * The string with used > 0 on success. + * The string with used == 0 if no match was found. + */ +#ifndef _di_control_action_type_name_ + extern const f_string_static_t control_action_type_name(const uint8_t type); +#endif // _di_control_action_type_name_ + +/** + * Verify that the additional parameters are reasonably correct for the identified action. + * + * @param main + * The main program data. + * + * This alters main.setting.state.status: + * F_none on success. + * + * F_parameter (with error bit) on parameter validation/verification failure. + */ +#ifndef _di_control_action_verify_ + extern void control_action_verify(control_main_t * const main); +#endif // _di_control_action_verify_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_action_h diff --git a/level_3/control/c/main/common.c b/level_3/control/c/main/common.c new file mode 100644 index 0000000..10f1e9e --- /dev/null +++ b/level_3/control/c/main/common.c @@ -0,0 +1,492 @@ +#include "control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_control_setting_load_ + void control_setting_load(const f_console_arguments_t arguments, control_main_t * const main) { + + if (!main) return; + + main->setting.state.step_small = control_allocation_console_d; + + f_console_parameter_process(arguments, &main->program.parameters, &main->setting.state, 0); + + main->setting.state.step_small = control_allocation_small_d; + + // Identify and process first/last parameters. + if (main->program.parameters.array[f_console_standard_parameter_line_first_no_e].result & f_console_result_found_e) { + main->setting.flag -= main->setting.flag & control_main_flag_print_first_e; + } + else { + main->setting.flag |= control_main_flag_print_first_e; + } + + if (main->program.parameters.array[f_console_standard_parameter_line_last_no_e].result & f_console_result_found_e) { + main->setting.flag -= main->setting.flag & control_main_flag_print_last_e; + } + else { + main->setting.flag |= control_main_flag_print_last_e; + } + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_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); + } + + control_print_error(&main->program.error, macro_control_f(f_console_parameter_process)); + + return; + } + + main->setting.state.status = fll_program_parameter_process_context_standard(F_true, &main->program); + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_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); + } + + control_print_error(&main->program.error, macro_control_f(fll_program_parameter_process_context_standard)); + + return; + } + + main->setting.state.status = fll_program_parameter_process_verbosity_standard(F_true, &main->program); + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_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); + } + + control_print_error(&main->program.error, macro_control_f(fll_program_parameter_process_verbosity_standard)); + + return; + } + + if (main->program.parameters.array[f_console_standard_parameter_help_e].result & f_console_result_found_e) { + main->setting.flag |= control_main_flag_help_e; + + return; + } + + if (main->program.parameters.array[f_console_standard_parameter_version_e].result & f_console_result_found_e) { + main->setting.flag |= control_main_flag_version_e; + + return; + } + + if (main->program.parameters.array[f_console_standard_parameter_copyright_e].result & f_console_result_found_e) { + main->setting.flag |= control_main_flag_copyright_e; + + return; + } + + if (main->program.parameters.array[control_parameter_return_e].result & f_console_result_found_e) { + main->setting.flag |= control_main_flag_return_e; + + return; + } + + f_number_unsigned_t index = 0; + + if (main->program.pipe & fll_program_data_pipe_input_e) { + main->setting.flag |= control_main_flag_pipe_e; + } + else { + main->setting.flag -= main->setting.flag & control_main_flag_pipe_e; + } + + // The settings path is statically allocated. + if (main->program.parameters.array[control_parameter_settings_e].result & f_console_result_value_e) { + index = main->program.parameters.array[control_parameter_settings_e].values.array[main->program.parameters.array[control_parameter_settings_e].values.used - 1]; + + main->setting.path_settings.string = main->program.parameters.arguments.array[index].string; + main->setting.path_settings.used = main->program.parameters.arguments.array[index].used; + main->setting.path_settings.size = 0; + } + else { + main->setting.path_settings.string = control_path_settings_s.string; + main->setting.path_settings.used = control_path_settings_s.used; + main->setting.path_settings.size = 0; + } + + { + f_file_t file = f_file_t_initialize; + + main->setting.state.status = f_file_stream_open(main->setting.path_settings, f_file_open_mode_read_s, &file); + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_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); + } + + control_print_error_file(&main->program.error, macro_control_f(f_file_stream_open), main->setting.path_settings, f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + main->setting.state.status = f_file_stream_read(file, &main->cache.large); + + f_file_stream_flush(file); + f_file_stream_close(&file); + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_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); + } + + control_print_error_file(&main->program.error, macro_control_f(f_file_stream_read), main->setting.path_settings, f_file_operation_read_s, fll_error_file_type_file_e); + + return; + } + } + + if (main->cache.large.used) { + main->setting.range.start = 0; + main->setting.range.stop = main->cache.large.used - 1; + } + else { + main->setting.range.start = 1; + main->setting.range.stop = 0; + } + + fll_fss_extended_read(main->cache.large, &main->setting.range, &main->cache.objects, &main->cache.contents, 0, 0, &main->cache.delimits, 0, &main->setting.state); + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_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); + } + + control_print_error_file(&main->program.error, macro_control_f(fll_fss_extended_read), main->setting.path_settings, f_file_operation_process_s, fll_error_file_type_file_e); + + return; + } + + f_fss_apply_delimit(main->cache.delimits, &main->cache.large, &main->setting.state); + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_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); + } + + control_print_error_file(&main->program.error, macro_control_f(f_fss_apply_delimit), main->setting.path_settings, f_file_operation_process_s, fll_error_file_type_file_e); + + return; + } + + uint8_t i = 0; + uint8_t parameter_hass[] = { 0, 0, 0, 0 }; + f_number_unsigned_t parameter_ats[] = { 0, 0, 0, 0 }; + + { + const f_string_static_t parameter_names[] = { + control_name_socket_s, + control_path_socket_s, + control_path_socket_prefix_s, + control_path_socket_suffix_s, + }; + + f_number_unsigned_t j = 0; + uint8_t k = 0; + + for (; j < main->cache.objects.used; ++j) { + + for (k = 0; k < 4; ++k) { + + if (!parameter_names[k].used) continue; + + main->setting.range.start = 0; + main->setting.range.stop = parameter_names[k].used - 1; + + if (f_compare_dynamic_partial(parameter_names[k], main->cache.large, main->setting.range, main->cache.objects.array[j]) == F_equal_to) { + parameter_hass[k] = F_true; + parameter_ats[k] = j; + + break; + } + } // for + } // for + } + + // The settings path is statically allocated, except when read from the settings file. + if (main->program.parameters.array[control_parameter_socket_e].result & f_console_result_value_e) { + index = main->program.parameters.array[control_parameter_settings_e].values.array[main->program.parameters.array[control_parameter_settings_e].values.used - 1]; + + main->setting.path_socket.string = main->program.parameters.arguments.array[index].string; + main->setting.path_socket.used = main->program.parameters.arguments.array[index].used; + main->setting.path_socket.size = 0; + } + else if (parameter_hass[1]) { + main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.large, main->cache.objects.array[parameter_ats[1]], &main->setting.path_socket); + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_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); + } + + control_print_error_file(&main->program.error, macro_control_f(f_string_dynamic_partial_append_nulless), main->setting.path_socket, f_file_operation_process_s, fll_error_file_type_file_e); + + return; + } + } + else { + main->setting.path_socket.string = controller_path_socket_s.string; + main->setting.path_socket.used = controller_path_socket_s.used; + main->setting.path_socket.size = 0; + } + + main->setting.state.status = f_file_exists(main->setting.path_socket, F_true); + + if (F_status_is_error(main->setting.state.status) || main->setting.state.status == F_false) { + if ((main->setting.flag & control_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 (F_status_is_error(main->setting.state.status)) { + control_print_error_file(&main->program.error, macro_control_f(f_file_exists), main->setting.path_socket, f_file_operation_find_s, fll_error_file_type_directory_e); + + if (main->program.error.verbosity > f_console_verbosity_quiet_e) { + fll_print_dynamic_raw(f_string_eol_s, main->program.error.to); + } + } + + main->setting.state.status = F_status_set_error(F_socket_not); + + control_print_error_socket_file_missing(&main->program.error, main->setting.path_socket); + + return; + } + + // Construct the file name when the socket path is a directory. + if (f_file_is(main->setting.path_socket, F_file_type_directory_d, F_true) == F_true) { + main->setting.state.status = f_string_dynamic_append_assure(f_path_separator_s, &main->setting.path_socket); + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_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); + } + + control_print_error(&main->program.error, macro_control_f(f_string_dynamic_append_assure)); + + return; + } + + { + const uint8_t append_ids[] = { + 0, + control_parameter_name_e, + 0, + }; + + const uint8_t append_hass[] = { + parameter_hass[2], + parameter_hass[0], + parameter_hass[3], + }; + + const f_string_static_t append_defaults[] = { + controller_path_socket_prefix_s, + controller_name_socket_s, + controller_path_socket_suffix_s, + }; + + for (i = 0; i < 3; ++i) { + + if (append_ids[i] && main->program.parameters.array[append_ids[i]].result & f_console_result_value_e) { + index = main->program.parameters.array[append_ids[i]].values.array[main->program.parameters.array[append_ids[i]].values.used - 1]; + + main->setting.state.status = f_string_dynamic_append(main->program.parameters.arguments.array[index], &main->setting.path_socket); + } + else if (append_hass[i]) { + main->setting.state.status = f_string_dynamic_partial_append_nulless(main->cache.large, main->cache.objects.array[append_hass[i]], &main->setting.path_socket); + } + else { + main->setting.state.status = f_string_dynamic_append_nulless(append_defaults[i], &main->setting.path_socket); + } + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_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); + } + + control_print_error( + &main->program.error, + ((append_ids[i] && main->program.parameters.array[append_ids[i]].result & f_console_result_value_e) || !append_hass[i]) + ? macro_control_f(f_string_dynamic_append) + : macro_control_f(f_string_dynamic_partial_append_nulless) + ); + + return; + } + } // for + + main->setting.state.status = f_file_exists(main->setting.path_socket, F_true); + + if (F_status_is_error(main->setting.state.status) || main->setting.state.status == F_false) { + if ((main->setting.flag & control_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 (F_status_is_error(main->setting.state.status)) { + control_print_error_file(&main->program.error, macro_control_f(f_file_exists), main->setting.path_socket, f_file_operation_find_s, fll_error_file_type_directory_e); + + if (main->program.error.verbosity > f_console_verbosity_quiet_e) { + fll_print_dynamic_raw(f_string_eol_s, main->program.error.to); + } + } + + main->setting.state.status = F_status_set_error(F_socket_not); + + control_print_error_socket_file_missing(&main->program.error, main->setting.path_socket); + + return; + } + } + } + + if (f_file_is(main->setting.path_socket, F_file_type_socket_d, F_true) == F_false) { + main->setting.state.status = F_status_set_error(F_socket_not); + + if ((main->setting.flag & control_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); + } + + control_print_error_socket_file_not(&main->program.error, main->setting.path_socket); + + return; + } + + main->setting.state.status = f_socket_create(&main->setting.socket); + + if (F_status_is_error(main->setting.state.status)) { + control_print_error(&main->program.error, macro_control_f(f_socket_create)); + + if ((main->setting.flag & control_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); + } + + control_print_error_socket_file_failed(&main->program.error, main->setting.path_socket); + + return; + } + + main->setting.state.status = f_socket_connect(main->setting.socket); + + if (F_status_is_error(main->setting.state.status)) { + control_print_error(&main->program.error, macro_control_f(f_socket_connect)); + + if ((main->setting.flag & control_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); + } + + control_print_error_socket_file_failed(&main->program.error, main->setting.path_socket); + + return; + } + + f_string_ranges_resize(0, &main->cache.objects); + f_string_rangess_resize(0, &main->cache.contents); + f_number_unsigneds_resize(0, &main->cache.delimits); + + { + const uint8_t ids[] = { + control_parameter_name_e, + control_parameter_settings_e, + control_parameter_socket_e + }; + + const f_string_static_t names[] = { + control_long_name_s, + control_long_settings_s, + control_long_socket_s + }; + + f_status_t error_printed_not = F_false; + + for (i = 0; i < 3; ++i) { + + if (main->program.parameters.array[ids[i]].result & f_console_result_found_e) { + main->setting.state.status = F_status_set_error(F_parameter); + + if (error_printed_not) { + error_printed_not = F_true; + + if ((main->setting.flag & control_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); + } + } + + control_print_error_parameter_value_not(&main->program.error, names[i]); + } + else if (main->program.parameters.array[ids[i]].result & f_console_result_value_e) { + index = main->program.parameters.array[ids[i]].values.array[main->program.parameters.array[ids[i]].values.used - 1]; + + if (!main->program.parameters.arguments.array[index].used) { + main->setting.state.status = F_status_set_error(F_parameter); + + if (error_printed_not) { + error_printed_not = F_true; + + if ((main->setting.flag & control_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); + } + } + + control_print_error_parameter_value_empty(&main->program.error, names[i]); + } + } + } // for + } + + main->cache.large.used = 0; + + if (main->cache.large.size > control_default_buffer_limit_soft_large_d) { + main->setting.state.status = f_string_dynamic_resize(control_default_buffer_limit_soft_large_d, &main->cache.large); + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_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); + } + + control_print_error(&main->program.error, macro_control_f(f_string_dynamic_resize)); + + return; + } + } + + if (main->program.parameters.remaining.used) { + main->setting.state.status = f_string_dynamics_increase_by(main->program.parameters.remaining.used, &main->setting.actions); + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_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); + } + + control_print_error(&main->program.error, macro_control_f(f_string_dynamics_increase_by)); + + return; + } + + index = 0; + + for (f_number_unsigned_t number = 0; index < main->program.parameters.remaining.used; ++index) { + + if (control_signal_check(main)) return; + + number = main->program.parameters.remaining.array[index]; + + // Statically allocate the inner strings. + main->setting.actions.array[main->setting.actions.used].string = main->program.parameters.arguments.array[number].string; + main->setting.actions.array[main->setting.actions.used].used = main->program.parameters.arguments.array[number].used; + main->setting.actions.array[main->setting.actions.used++].size = 0; + } // for + } + + main->setting.state.status = F_none; + } +#endif // _di_control_setting_load_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/common.h b/level_3/control/c/main/common.h new file mode 100644 index 0000000..4abdc52 --- /dev/null +++ b/level_3/control/c/main/common.h @@ -0,0 +1,48 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the common data structures. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_common_h +#define _control_common_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately returns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data and settings. + * + * This alters main.setting.state.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_control_setting_load_ + extern void control_setting_load(const f_console_arguments_t arguments, control_main_t * const main); +#endif // _di_control_setting_load_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_common_h diff --git a/level_3/control/c/main/common/define.c b/level_3/control/c/main/common/define.c new file mode 100644 index 0000000..39790a2 --- /dev/null +++ b/level_3/control/c/main/common/define.c @@ -0,0 +1,9 @@ +#include "../control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/common/define.h b/level_3/control/c/main/common/define.h new file mode 100644 index 0000000..eeebe70 --- /dev/null +++ b/level_3/control/c/main/common/define.h @@ -0,0 +1,67 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the common define types. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_common_define_h +#define _control_common_define_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The program allocation defines. + * + * control_allocation_*_d: + * - console: An allocation step used for small buffers specifically for console parameter. + * - large: An allocation step used for buffers that are anticipated to have large buffers. + * - pipe: A buffer size used for processing piped data. + * - small: An allocation step used for buffers that are anticipated to have small buffers. + */ +#ifndef _di_control_allocation_d_ + #define control_allocation_console_d 4 + #define control_allocation_large_d 256 + #define control_allocation_pipe_d 16384 + #define control_allocation_small_d 16 +#endif // _di_control_allocation_d_ + +/** + * General defines used throughout the program. + * + * control_default_*_d: + * - buffer_limit_soft_large: The preferred maximum size of buffers intended for large data sets such that sizes exceeding this will be shrunk when operations are complete (aka: a soft limit). + * - buffer_limit_soft_small: The preferred maximum size of buffers intended for small data sets such that sizes exceeding this will be shrunk when operations are complete (aka: a soft limit). + */ +#ifndef _di_control_default_d_ + #define control_default_buffer_limit_soft_large_d 2048 + #define control_default_buffer_limit_soft_small_d 64 +#endif // _di_control_default_d_ + +/** + * The program signal defines. + * + * control_signal_*_d: + * - check: Number of iterations before performing signal check in non-threaded signal handling. + * - check_failsafe: When using threads, how many consecutive failures to check signal before aborting (as a recursion failsafe). + * - check_tiny: The tiny check. + * - check_short: The short signal check. + */ +#ifndef _di_control_signal_d_ + #define control_signal_check_d 500000 + #define control_signal_check_failsafe_d 20000 + #define control_signal_check_tiny_d 4 + #define control_signal_check_short_d 16 +#endif // _di_control_signal_d_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_common_define_h diff --git a/level_3/control/c/main/common/enumeration.c b/level_3/control/c/main/common/enumeration.c new file mode 100644 index 0000000..39790a2 --- /dev/null +++ b/level_3/control/c/main/common/enumeration.c @@ -0,0 +1,9 @@ +#include "../control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/common/enumeration.h b/level_3/control/c/main/common/enumeration.h new file mode 100644 index 0000000..90d0999 --- /dev/null +++ b/level_3/control/c/main/common/enumeration.h @@ -0,0 +1,161 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the common enumeration types. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_common_enumeration_h +#define _control_common_enumeration_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Codes representing supported actions. + * + * freeze: Perform the freeze controller operation. + * kexec: Perform the kexec controller operation (only for init mode). + * kill: Perform the kill controller operation. + * pause: Perform the pause controller operation. + * reboot: Perform the reboot controller operation (only for init mode). + * reload: Perform the reload controller operation. + * rerun: Perform the rerun controller operation. + * restart: Perform the restart controller operation. + * resume: Perform the resume controller operation. + * shutdown: Perform the shutdown controller operation (only for init mode). + * start: Perform the start controller operation. + * stop: Perform the stop controller operation. + * thaw: Perform the thaw controller operation. + */ +#ifndef _di_control_action_type_e_ + enum { + control_action_type_freeze_e = 1, + control_action_type_kexec_e, + control_action_type_kill_e, + control_action_type_pause_e, + control_action_type_reboot_e, + control_action_type_reload_e, + control_action_type_rerun_e, + control_action_type_restart_e, + control_action_type_resume_e, + control_action_type_shutdown_e, + control_action_type_start_e, + control_action_type_stop_e, + control_action_type_thaw_e, + }; // enum +#endif // _di_control_action_type_e_ + +/** + * Supported payload types. + * + * controller: The payload is a controller payload. + * error: The payload is an error payload. + * init: The payload is an init payload (only available when operating in "init" mode). + */ +#ifndef _di_control_payload_type_e_ + enum { + control_payload_type_controller_e = 1, + control_payload_type_error_e, + control_payload_type_init_e, + }; // enum +#endif // _di_control_payload_type_e_ + +/** + * A codes repesent different flags associated with a packet. + * + * control_packet_flag_*: + * - binary: Designate that the packet is in binary mode (when not set then packet is in string mode). + * - endian_big: Designate that the packet is in big endian order (when not set then packet is in little endian order). + */ +#ifndef _di_control_packet_flag_e_ + #define control_packet_flag_binary_d 0x80 + #define control_packet_flag_endian_big_d 0x40 +#endif // _di_control_packet_flag_e_ + +/** + * Flags passed to the main function or program. + * + * control_main_flag_*_e: + * - none: No flags set. + * - copyright: Print copyright. + * - header: Enable printing of headers. + * - help: Print help. + * - 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. + * - return: The parameter is specified. + * - version: Print version. + */ +#ifndef _di_control_main_flag_e_ + enum { + control_main_flag_none_e = 0x0, + control_main_flag_copyright_e = 0x1, + control_main_flag_help_e = 0x2, + control_main_flag_pipe_e = 0x4, + control_main_flag_print_first_e = 0x8, + control_main_flag_print_last_e = 0x10, + control_main_flag_return_e = 0x20, + control_main_flag_version_e = 0x40, + }; // enum +#endif // _di_control_main_flag_e_ + +/** + * The main program parameters. + */ +#ifndef _di_control_parameter_d_ + enum { + control_parameter_name_e = f_console_standard_parameter_last_e, + control_parameter_return_e, + control_parameter_settings_e, + control_parameter_socket_e, + }; // enum + + #define control_console_parameter_t_initialize \ + { \ + macro_fll_program_console_parameter_standard_initialize, \ + \ + macro_f_console_parameter_t_initialize_3(control_short_name_s, control_long_name_s, 1, f_console_flag_normal_e), \ + macro_f_console_parameter_t_initialize_3(control_short_return_s, control_long_return_s, 1, f_console_flag_normal_e), \ + macro_f_console_parameter_t_initialize_3(control_short_settings_s, control_long_settings_s, 1, f_console_flag_normal_e), \ + macro_f_console_parameter_t_initialize_3(control_short_socket_s, control_long_socket_s, 1, f_console_flag_normal_e), \ + } + + #define control_parameter_total_d 17 +#endif // _di_control_parameter_d_ + +/** + * Flags for fine-tuned print control. + * + * control_print_flag_*_e: + * - none: No flags set. + * - debug: Stream is for debug printing. + * - error: Stream is for error printing. + * - in: Stream is a source file. + * - message: Stream is for message printing. + * - out: Stream is a destination file. + * - warning: Stream is for warning printing. + */ +#ifndef _di_control_print_flag_e_ + enum { + control_print_flag_none_e = 0x0, + control_print_flag_debug_e = 0x1, + control_print_flag_error_e = 0x2, + control_print_flag_file_e = 0x4, + control_print_flag_in_e = 0x8, + control_print_flag_out_e = 0x10, + control_print_flag_message_e = 0x20, + control_print_flag_warning_e = 0x40, + }; // enum +#endif // _di_control_print_flag_e_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_common_enumeration_h diff --git a/level_3/control/c/main/common/print.c b/level_3/control/c/main/common/print.c new file mode 100644 index 0000000..99c5491 --- /dev/null +++ b/level_3/control/c/main/common/print.c @@ -0,0 +1,34 @@ +#include "../control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_control_f_a_ + const f_string_t control_f_a[] = { + "control_packet_build", + "control_packet_process", + "control_packet_receive", + "control_packet_send", + "f_console_parameter_process", + "f_file_exists", + "f_file_stream_open", + "f_file_stream_read", + "f_fss_apply_delimit", + "f_socket_connect", + "f_socket_create", + "f_string_dynamic_append", + "f_string_dynamic_append_assure", + "f_string_dynamic_partial_append_nulless", + "f_string_dynamic_resize", + "f_string_dynamics_increase_by", + "f_thread_create", + "fll_fss_extended_read", + "fll_program_parameter_process_context_standard", + "fll_program_parameter_process_verbosity_standard", + }; +#endif // _di_control_f_a_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/common/print.h b/level_3/control/c/main/common/print.h new file mode 100644 index 0000000..5826af1 --- /dev/null +++ b/level_3/control/c/main/common/print.h @@ -0,0 +1,69 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the common print functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_common_print_h +#define _control_common_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * A special array of strings intended for representing funciton names. + * + * These are primarily used for printing errors with the function names. + * + * The macro macro_control_f() is used to reference the array index by the enum name. + * + * macro_control_f(): + * - name: The name of the function. + */ +#ifndef _di_control_f_a_ + extern const f_string_t control_f_a[]; + + #define macro_control_f(name) control_f_a[control_f_##name##_e] +#endif // _di_control_f_a_ + +/** + * An enum representing specific indexes within the above array. + * + * This is a convenience enum used to make code slightly more readable. + */ +#ifndef _di_control_f_e_ + enum { + control_f_control_packet_build_e, + control_f_control_packet_process_e, + control_f_control_packet_receive_e, + control_f_control_packet_send_e, + control_f_f_console_parameter_process_e, + control_f_f_file_exists_e, + control_f_f_file_stream_open_e, + control_f_f_file_stream_read_e, + control_f_f_fss_apply_delimit_e, + control_f_f_socket_connect_e, + control_f_f_socket_create_e, + control_f_f_string_dynamic_append_e, + control_f_f_string_dynamic_append_assure_e, + control_f_f_string_dynamic_partial_append_nulless_e, + control_f_f_string_dynamic_resize_e, + control_f_f_string_dynamics_increase_by_e, + control_f_f_thread_create_e, + control_f_fll_fss_extended_read_e, + control_f_fll_program_parameter_process_context_standard_e, + control_f_fll_program_parameter_process_verbosity_standard_e, + }; // enum +#endif // _di_control_f_e_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_common_print_h diff --git a/level_3/control/c/private-common.c b/level_3/control/c/main/common/string.c similarity index 70% rename from level_3/control/c/private-common.c rename to level_3/control/c/main/common/string.c index 5c5e280..a9ab36b 100644 --- a/level_3/control/c/private-common.c +++ b/level_3/control/c/main/common/string.c @@ -1,17 +1,29 @@ -#include "control.h" -#include "private-common.h" -#include "private-print.h" +#include "../control.h" #ifdef __cplusplus extern "C" { #endif -#ifndef _di_controller_strings_ - const f_string_static_t controller_name_socket_s = macro_f_string_static_t_initialize_1(CONTROLLER_name_socket_s, 0, CONTROLLER_name_socket_s_length); - const f_string_static_t controller_path_socket_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_s, 0, CONTROLLER_path_socket_s_length); - const f_string_static_t controller_path_socket_prefix_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_prefix_s, 0, CONTROLLER_path_socket_prefix_s_length); - const f_string_static_t controller_path_socket_suffix_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_suffix_s, 0, CONTROLLER_path_socket_suffix_s_length); -#endif // _di_controller_strings_ +#ifndef _di_control_program_version_s_ + const f_string_static_t control_program_version_s = macro_f_string_static_t_initialize_1(CONTROL_program_version_s, 0, CONTROL_program_version_s_length); +#endif // _di_control_program_version_s_ + +#ifndef _di_control_program_name_s_ + const f_string_static_t control_program_name_s = macro_f_string_static_t_initialize_1(CONTROL_program_name_s, 0, CONTROL_program_name_s_length); + const f_string_static_t control_program_name_long_s = macro_f_string_static_t_initialize_1(CONTROL_program_name_long_s, 0, CONTROL_program_name_long_s_length); +#endif // _di_control_program_name_s_ + +#ifndef _di_control_parameter_s_ + const f_string_static_t control_short_name_s = macro_f_string_static_t_initialize_1(CONTROL_short_name_s, 0, CONTROL_short_name_s_length); + const f_string_static_t control_short_return_s = macro_f_string_static_t_initialize_1(CONTROL_short_return_s, 0, CONTROL_short_return_s_length); + const f_string_static_t control_short_settings_s = macro_f_string_static_t_initialize_1(CONTROL_short_settings_s, 0, CONTROL_short_settings_s_length); + const f_string_static_t control_short_socket_s = macro_f_string_static_t_initialize_1(CONTROL_short_socket_s, 0, CONTROL_short_socket_s_length); + + const f_string_static_t control_long_name_s = macro_f_string_static_t_initialize_1(CONTROL_long_name_s, 0, CONTROL_long_name_s_length); + const f_string_static_t control_long_return_s = macro_f_string_static_t_initialize_1(CONTROL_long_return_s, 0, CONTROL_long_return_s_length); + const f_string_static_t control_long_settings_s = macro_f_string_static_t_initialize_1(CONTROL_long_settings_s, 0, CONTROL_long_settings_s_length); + const f_string_static_t control_long_socket_s = macro_f_string_static_t_initialize_1(CONTROL_long_socket_s, 0, CONTROL_long_socket_s_length); +#endif // _di_control_parameter_s_ #ifndef _di_control_strings_s_ const f_string_static_t control_path_settings_s = macro_f_string_static_t_initialize_1(CONTROL_path_settings_s, 0, CONTROL_path_settings_s_length); @@ -47,22 +59,12 @@ extern "C" { const f_string_static_t control_thaw_s = macro_f_string_static_t_initialize_1(CONTROL_thaw_s, 0, CONTROL_thaw_s_length); #endif // _di_control_strings_s_ -#ifndef _di_control_data_delete_ - void control_data_delete(control_data_t * const data) { - - f_string_dynamic_resize(0, &data->cache.large); - f_string_dynamic_resize(0, &data->cache.small); - f_string_dynamic_resize(0, &data->cache.packet); - - f_string_ranges_resize(0, &data->cache.packet_objects); - f_string_rangess_resize(0, &data->cache.packet_contents); - - f_string_ranges_resize(0, &data->cache.header_objects); - f_string_rangess_resize(0, &data->cache.header_contents); - - f_number_unsigneds_resize(0, &data->cache.delimits); - } -#endif // _di_control_data_delete_ +#ifndef _di_controller_strings_s_ + const f_string_static_t controller_name_socket_s = macro_f_string_static_t_initialize_1(CONTROLLER_name_socket_s, 0, CONTROLLER_name_socket_s_length); + const f_string_static_t controller_path_socket_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_s, 0, CONTROLLER_path_socket_s_length); + const f_string_static_t controller_path_socket_prefix_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_prefix_s, 0, CONTROLLER_path_socket_prefix_s_length); + const f_string_static_t controller_path_socket_suffix_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_suffix_s, 0, CONTROLLER_path_socket_suffix_s_length); +#endif // _di_controller_strings_s_ #ifdef __cplusplus } // extern "C" diff --git a/level_3/control/c/private-common.h b/level_3/control/c/main/common/string.h similarity index 63% rename from level_3/control/c/private-common.h rename to level_3/control/c/main/common/string.h index 89505dd..d5c6116 100644 --- a/level_3/control/c/private-common.h +++ b/level_3/control/c/main/common/string.h @@ -4,114 +4,95 @@ * Project: Control * API Version: 0.7 * Licenses: lgpl-2.1-or-later + * + * Provides the common string structures. + * + * This is auto-included and should not need to be explicitly included. */ -#ifndef _PRIVATE_common_h -#define _PRIVATE_common_h +#ifndef _control_common_string_h +#define _control_common_string_h #ifdef __cplusplus extern "C" { #endif /** - * General defines used throughout the program. - * - * control_default_*: - * - buffer_limit_soft_large: The preferred maximum size of buffers intended for large data sets such that sizes exceeding this will be shrunk when operations are complete (aka: a soft limit). - * - buffer_limit_soft_small: The preferred maximum size of buffers intended for small data sets such that sizes exceeding this will be shrunk when operations are complete (aka: a soft limit). - * - * control_signal_*: - * - check: The interval in which callbacks checking signal should actually perform the signal check (significantly improves perfomance). - * - * control_allocation_*: - * - large: Default allocation buffer size for buffers expected to work with large data sets. - * - small: Default allocation buffer size for buffers expected to work with small data sets. - */ -#ifndef _di_control_defines_s_ - #define control_default_buffer_limit_soft_large_d 2048 - #define control_default_buffer_limit_soft_small_d 64 - - #define control_signal_check_d 20000 - - #define control_allocation_large_d 256 - #define control_allocation_small_d 16 -#endif // _di_control_defines_s_ - -/** - * A codes repesent different flags associated with a packet. - * - * control_packet_flag_*: - * - binary: Designate that the packet is in binary mode (when not set then packet is in string mode). - * - endian_big: Designate that the packet is in big endian order (when not set then packet is in little endian order). - */ -#ifndef _di_control_packet_flag_ - #define control_packet_flag_binary_d 0x80 - #define control_packet_flag_endian_big_d 0x40 -#endif // _di_control_packet_flag_ - -/** - * Controller defines that the control program utilizes. - * - * These are intended to exactly match the relevant controller string defines. + * The program version. */ -#ifndef _di_controller_strings_ +#ifndef _di_control_program_version_s_ + #define CONTROL_program_version_major_s F_string_ascii_0_s + #define CONTROL_program_version_minor_s F_string_ascii_7_s + #define CONTROL_program_version_micro_s F_string_ascii_0_s - // The name_socket is a system-specific path and should match the path compiled into the controller program. - #if defined(_override_controller_name_socket_) && defined(_override_controller_name_socket_length_) - #define CONTROLLER_name_socket_s _override_controller_name_socket_ + #define CONTROL_program_version_major_s_length F_string_ascii_0_s_length + #define CONTROL_program_version_minor_s_length F_string_ascii_7_s_length + #define CONTROL_program_version_micro_s_length F_string_ascii_0_s_length - #define CONTROLLER_name_socket_s_length _override_controller_name_socket_length_ - #else - #define CONTROLLER_name_socket_s "default" + #if !(defined(CONTROL_program_version_nano_prefix_s) && defined(CONTROL_program_version_nano_prefix_s_length)) + #define CONTROL_program_version_nano_prefix_s + #define CONTROL_program_version_nano_prefix_s_length 0 + #endif // !(defined(CONTROL_program_version_nano_prefix_s) && defined(CONTROL_program_version_nano_prefix_s_length)) - #define CONTROLLER_name_socket_s_length 7 - #endif // defined(_override_controller_name_socket_) && defined(_override_controller_name_socket_length_) + #if !(defined(CONTROL_program_version_nano_s) && defined(CONTROL_program_version_nano_s_length)) + #define CONTROL_program_version_nano_s + #define CONTROL_program_version_nano_s_length 0 + #endif // !(defined(CONTROL_program_version_nano_s) && defined(CONTROL_program_version_nano_s_length)) - // The path_socket is a system-specific path and should match the path compiled into the controller program. - #if defined(_override_controller_path_socket_) && defined(_override_controller_path_socket_length_) - #define CONTROLLER_path_socket_s _override_controller_path_socket_ + #define CONTROL_program_version_s CONTROL_program_version_major_s F_string_ascii_period_s CONTROL_program_version_minor_s F_string_ascii_period_s CONTROL_program_version_micro_s CONTROL_program_version_nano_prefix_s CONTROL_program_version_nano_s - #define CONTROLLER_path_socket_s_length _override_controller_path_socket_length_ - #elif defined(_controller_as_init_) - #define CONTROLLER_path_socket_s "/var/run/init" + #define CONTROL_program_version_s_length CONTROL_program_version_major_s_length + F_string_ascii_period_s_length + CONTROL_program_version_minor_s_length + F_string_ascii_period_s_length + CONTROL_program_version_micro_s_length + CONTROL_program_version_nano_prefix_s_length + CONTROL_program_version_nano_s_length - #define CONTROLLER_path_socket_s_length 13 - #else - #define CONTROLLER_path_socket_s "/var/run/controller" + extern const f_string_static_t control_program_version_s; +#endif // _di_control_program_version_s_ - #define CONTROLLER_path_socket_s_length 19 - #endif // defined(_override_controller_path_socket_) && defined(_override_controller_path_socket_length_) - - // The name_socket_prefix is a system-specific path and should match the path compiled into the controller program. - #if defined(_override_controller_path_socket_prefix_) && defined(_override_controller_path_socket_prefix_length_) - #define CONTROLLER_path_socket_prefix_s _override_controller_path_socket_prefix_ - - #define CONTROLLER_path_socket_prefix_s_length _override_controller_path_socket_prefix_length_ - #elif defined(_controller_as_init_) - #define CONTROLLER_path_socket_prefix_s "init-" - - #define CONTROLLER_path_socket_prefix_s_length 5 - #else - #define CONTROLLER_path_socket_prefix_s "" - - #define CONTROLLER_path_socket_prefix_s_length 0 - #endif // defined(_override_controller_name_socket_prefix_) && defined(_override_controller_name_socket_prefix_length_) - - // The name_socket_suffix is a system-specific path and should match the path compiled into the controller program. - #if defined(_override_controller_path_socket_suffix_) && defined(_override_controller_path_socket_suffix_length_) - #define CONTROLLER_path_socket_suffix_s _override_controller_path_socket_suffix_ +/** + * The program name. + */ +#ifndef _di_control_program_name_s_ + #define CONTROL_program_name_s "control" + #define CONTROL_program_name_long_s "Control Program" - #define CONTROLLER_path_socket_suffix_s_length _override_controller_path_socket_suffix_length_ - #else - #define CONTROLLER_path_socket_suffix_s ".socket" + #define CONTROL_program_name_s_length 7 + #define CONTROL_program_name_long_s_length 15 - #define CONTROLLER_path_socket_suffix_s_length 7 - #endif // defined(_override_controller_name_socket_suffix_) && defined(_override_controller_name_socket_suffix_length_) + extern const f_string_static_t control_program_name_s; + extern const f_string_static_t control_program_name_long_s; +#endif // _di_control_program_name_s_ - extern const f_string_static_t controller_name_socket_s; - extern const f_string_static_t controller_path_socket_s; - extern const f_string_static_t controller_path_socket_prefix_s; - extern const f_string_static_t controller_path_socket_suffix_s; -#endif // _di_controller_strings_ +/** + * The main program parameters. + */ +#ifndef _di_control_parameter_s_ + #define CONTROL_short_name_s "n" + #define CONTROL_short_return_s "R" + #define CONTROL_short_settings_s "s" + #define CONTROL_short_socket_s "k" + + #define CONTROL_long_name_s "name" + #define CONTROL_long_return_s "return" + #define CONTROL_long_settings_s "settings" + #define CONTROL_long_socket_s "socket" + + #define CONTROL_short_name_s_length 1 + #define CONTROL_short_return_s_length 1 + #define CONTROL_short_settings_s_length 1 + #define CONTROL_short_socket_s_length 1 + + #define CONTROL_long_name_s_length 4 + #define CONTROL_long_return_s_length 6 + #define CONTROL_long_settings_s_length 8 + #define CONTROL_long_socket_s_length 6 + + extern const f_string_static_t control_short_name_s; + extern const f_string_static_t control_short_return_s; + extern const f_string_static_t control_short_settings_s; + extern const f_string_static_t control_short_socket_s; + + extern const f_string_static_t control_long_name_s; + extern const f_string_static_t control_long_return_s; + extern const f_string_static_t control_long_settings_s; + extern const f_string_static_t control_long_socket_s; +#endif // _di_control_parameter_s_ /** * All special strings used within this program. @@ -221,115 +202,72 @@ extern "C" { #endif // _di_control_strings_s_ /** - * The control cache. - * - * large: A buffer for storing large sets of data. - * small: A buffer for storing small sets of data. - * packet: A buffer for storing the send packet or the response payload. - * - * packet_objects: The FSS Objects for a packet. - * packet_contents: The FSS Contents for a packet. - * - * header_objects: The FSS Objects for a packet payload header. - * header_contents: The FSS Contents for a packet payload header. + * Controller defines that the control program utilizes. * - * delimits: The delimits cache. + * These are intended to exactly match the relevant controller string defines. */ -#ifndef _di_control_cache_t_ - typedef struct { - f_string_dynamic_t large; - f_string_dynamic_t small; - f_string_dynamic_t packet; - - f_string_ranges_t packet_objects; - f_string_rangess_t packet_contents; - - f_string_ranges_t header_objects; - f_string_rangess_t header_contents; - - f_number_unsigneds_t delimits; - } control_cache_t; - - #define control_cache_initialize \ - { \ - f_string_dynamic_t_initialize, \ - f_string_dynamic_t_initialize, \ - f_string_dynamic_t_initialize, \ - f_string_ranges_t_initialize, \ - f_string_rangess_t_initialize, \ - f_string_ranges_t_initialize, \ - f_string_rangess_t_initialize, \ - f_number_unsigneds_t_initialize, \ - } -#endif // _di_control_cache_t_ +#ifndef _di_controller_strings_s_ -/** - * The control data. - * - * action: The action type code. - * argv: The argument structure in the progam data parameters for simplifying syntax. - * cache: A cache. - * socket: A socket used to connect to the controller. - */ -#ifndef _di_control_data_t_ - typedef struct { - uint8_t action; + // The name_socket is a system-specific path and should match the path compiled into the controller program. + #if defined(_override_controller_name_socket_) && defined(_override_controller_name_socket_length_) + #define CONTROLLER_name_socket_s _override_controller_name_socket_ - control_cache_t cache; + #define CONTROLLER_name_socket_s_length _override_controller_name_socket_length_ + #else + #define CONTROLLER_name_socket_s "default" - f_socket_t socket; + #define CONTROLLER_name_socket_s_length 7 + #endif // defined(_override_controller_name_socket_) && defined(_override_controller_name_socket_length_) - f_string_static_t *argv; - } control_data_t; + // The path_socket is a system-specific path and should match the path compiled into the controller program. + #if defined(_override_controller_path_socket_) && defined(_override_controller_path_socket_length_) + #define CONTROLLER_path_socket_s _override_controller_path_socket_ - #define control_data_t_initialize \ - { \ - 0, \ - f_string_dynamic_t_initialize, \ - f_socket_t_initialize, \ - 0, \ - } -#endif // _di_control_data_t_ + #define CONTROLLER_path_socket_s_length _override_controller_path_socket_length_ + #elif defined(_controller_as_init_) + #define CONTROLLER_path_socket_s "/var/run/init" -/** - * The packet payload header data. - * - * The FSS-000E (Payload) supports multiple objects, but the Control packet does not support this, yet. - * - * action: The action type code, for any valid action (see: control_action_types enumeration). - * type: The packet type represented by the payload packet. - * status: The status code represented by the payload packet. - * length: The length of the payload content within the payload packet. - */ -#ifndef _di_control_payload_header_t_ - typedef struct { - uint8_t action; - uint8_t type; - f_status_t status; - uint16_t length; - } control_payload_header_t; - - #define control_payload_header_t_initialize \ - { \ - 0, \ - 0, \ - f_status_t_initialize, \ - f_number_unsigned_t_initialize, \ - } -#endif // _di_control_payload_header_t_ + #define CONTROLLER_path_socket_s_length 13 + #else + #define CONTROLLER_path_socket_s "/var/run/controller" -/** - * Deallocate the control data. - * - * @param data - * The control data. - */ -#ifndef _di_control_data_delete_ - extern void control_data_delete(control_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_control_data_delete_ + #define CONTROLLER_path_socket_s_length 19 + #endif // defined(_override_controller_path_socket_) && defined(_override_controller_path_socket_length_) + + // The name_socket_prefix is a system-specific path and should match the path compiled into the controller program. + #if defined(_override_controller_path_socket_prefix_) && defined(_override_controller_path_socket_prefix_length_) + #define CONTROLLER_path_socket_prefix_s _override_controller_path_socket_prefix_ + + #define CONTROLLER_path_socket_prefix_s_length _override_controller_path_socket_prefix_length_ + #elif defined(_controller_as_init_) + #define CONTROLLER_path_socket_prefix_s "init-" + + #define CONTROLLER_path_socket_prefix_s_length 5 + #else + #define CONTROLLER_path_socket_prefix_s "" + + #define CONTROLLER_path_socket_prefix_s_length 0 + #endif // defined(_override_controller_name_socket_prefix_) && defined(_override_controller_name_socket_prefix_length_) + + // The name_socket_suffix is a system-specific path and should match the path compiled into the controller program. + #if defined(_override_controller_path_socket_suffix_) && defined(_override_controller_path_socket_suffix_length_) + #define CONTROLLER_path_socket_suffix_s _override_controller_path_socket_suffix_ + + #define CONTROLLER_path_socket_suffix_s_length _override_controller_path_socket_suffix_length_ + #else + #define CONTROLLER_path_socket_suffix_s ".socket" + + #define CONTROLLER_path_socket_suffix_s_length 7 + #endif // defined(_override_controller_name_socket_suffix_) && defined(_override_controller_name_socket_suffix_length_) + + extern const f_string_static_t controller_name_socket_s; + extern const f_string_static_t controller_path_socket_s; + extern const f_string_static_t controller_path_socket_prefix_s; + extern const f_string_static_t controller_path_socket_suffix_s; +#endif // _di_controller_strings_s_ #ifdef __cplusplus } // extern "C" #endif -#endif // _PRIVATE_common_h +#endif // _control_common_string_h diff --git a/level_3/control/c/main/common/type.c b/level_3/control/c/main/common/type.c new file mode 100644 index 0000000..2193092 --- /dev/null +++ b/level_3/control/c/main/common/type.c @@ -0,0 +1,49 @@ +#include "../control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_control_main_delete_ + void control_main_delete(control_main_t * const main) { + + if (!main) return; + + fll_program_data_delete(&main->program); + control_setting_delete(&main->setting); + + f_string_dynamic_resize(0, &main->cache.large); + f_string_dynamic_resize(0, &main->cache.small); + f_string_dynamic_resize(0, &main->cache.packet); + + f_string_ranges_resize(0, &main->cache.objects); + f_string_rangess_resize(0, &main->cache.contents); + + f_string_ranges_resize(0, &main->cache.packet_objects); + f_string_rangess_resize(0, &main->cache.packet_contents); + + f_string_ranges_resize(0, &main->cache.header_objects); + f_string_rangess_resize(0, &main->cache.header_contents); + + f_number_unsigneds_resize(0, &main->cache.delimits); + } +#endif // _di_control_main_delete_ + +#ifndef _di_control_setting_delete_ + f_status_t control_setting_delete(control_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + f_string_dynamic_resize(0, &setting->name_socket); + f_string_dynamic_resize(0, &setting->path_settings); + f_string_dynamic_resize(0, &setting->path_socket); + + f_string_dynamics_resize(0, &setting->actions); + + return F_none; + } +#endif // _di_control_setting_delete_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/common/type.h b/level_3/control/c/main/common/type.h new file mode 100644 index 0000000..63ae8ad --- /dev/null +++ b/level_3/control/c/main/common/type.h @@ -0,0 +1,218 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the common type structures. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_common_type_h +#define _control_common_type_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The control cache. + * + * large: A buffer for storing large sets of data. + * small: A buffer for storing small sets of data. + * packet: A buffer for storing the send packet or the response payload. + * + * objects: An array of ranges representing objects. + * contents: An array of ranges representing contents. + * delimits: An array of ranges representing delimits. + * + * packet_objects: The FSS Objects for a packet. + * packet_contents: The FSS Contents for a packet. + * + * header_objects: The FSS Objects for a packet payload header. + * header_contents: The FSS Contents for a packet payload header. + * + * delimits: The delimits cache. + */ +#ifndef _di_control_cache_t_ + typedef struct { + f_string_dynamic_t large; + f_string_dynamic_t small; + f_string_dynamic_t packet; + + f_string_ranges_t objects; + f_string_rangess_t contents; + f_number_unsigneds_t delimits; + + f_string_ranges_t packet_objects; + f_string_rangess_t packet_contents; + + f_string_ranges_t header_objects; + f_string_rangess_t header_contents; + } control_cache_t; + + #define control_cache_t_initialize \ + { \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_ranges_t_initialize, \ + f_string_rangess_t_initialize, \ + f_number_unsigneds_t_initialize, \ + f_string_ranges_t_initialize, \ + f_string_rangess_t_initialize, \ + f_string_ranges_t_initialize, \ + f_string_rangess_t_initialize, \ + } +#endif // _di_control_cache_t_ + +/** + * The packet payload header data. + * + * The FSS-000E (Payload) supports multiple objects, but the Control packet does not support this, yet. + * + * action: The action type code, for any valid action (see: control_action_types enumeration). + * type: The packet type represented by the payload packet. + * status: The status code represented by the payload packet. + * length: The length of the payload content within the payload packet. + */ +#ifndef _di_control_payload_header_t_ + typedef struct { + uint8_t action; + uint8_t type; + f_status_t status; + uint16_t length; + } control_payload_header_t; + + #define control_payload_header_t_initialize \ + { \ + 0, \ + 0, \ + f_status_t_initialize, \ + f_number_unsigned_t_initialize, \ + } +#endif // _di_control_payload_header_t_ + +/** + * The control main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * Properties: + * - flag: Flags passed to the main function. + * - action: The action type code. + * - size_write: The write size of a packet request or response. + * + * - status_signal: A status used eclusively by the threaded signal handler. + * - state: The state data used when processing the data. + * + * - range: A range for any particular use. + * - socket: A socket used to connect to the controller. + * + * - name_socket: The name of the socket file. + * - path_settings: The path to the settings file. + * - path_socket: The path to the socket file. + * - actions: The requested actions. + */ +#ifndef _di_control_setting_t_ + typedef struct { + uint16_t flag; + uint8_t action; + f_number_unsigned_t size_write; + + f_status_t status_signal; + f_state_t state; + + f_string_range_t range; + f_socket_t socket; + + f_string_dynamic_t name_socket; + f_string_dynamic_t path_settings; + f_string_dynamic_t path_socket; + f_string_dynamics_t actions; + } control_setting_t; + + #define control_setting_t_initialize \ + { \ + control_main_flag_none_e, \ + 0, \ + 0, \ + F_none, \ + f_state_t_initialize, \ + f_string_range_t_initialize, \ + f_socket_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_dynamics_t_initialize, \ + } +#endif // _di_control_setting_t_ + +/** + * The main program data as a single structure. + * + * Properties: + * - program: The main program data. + * - setting: The settings data. + * - cache: The cache data. + */ +#ifndef _di_control_main_t_ + typedef struct { + fll_program_data_t program; + control_setting_t setting; + control_cache_t cache; + } control_main_t; + + #define control_main_t_initialize \ + { \ + fll_program_data_t_initialize, \ + control_setting_t_initialize, \ + control_cache_t_initialize, \ + } +#endif // _di_control_main_t_ + +/** + * Deallocate main program data. + * + * @param setting_make + * The make setting data. + * + * This does not alter main.setting.state.status. + * + * @see f_number_unsigneds_resize() + * @see f_string_dynamic_resize() + * @see f_string_ranges_resize() + * @see f_string_rangess_resize() + * @see fll_program_data_delete() + */ +#ifndef _di_control_main_delete_ + extern void control_main_delete(control_main_t * const main); +#endif // _di_control_main_delete_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * + * This does not alter setting.state.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * @see f_string_dynamic_resize() + * @see f_string_dynamics_resize() + */ +#ifndef _di_control_setting_delete_ + extern f_status_t control_setting_delete(control_setting_t * const setting); +#endif // _di_control_setting_delete_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_common_type_h diff --git a/level_3/control/c/main/control.c b/level_3/control/c/main/control.c new file mode 100644 index 0000000..a84c778 --- /dev/null +++ b/level_3/control/c/main/control.c @@ -0,0 +1,129 @@ +#include "control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_control_main_ + void control_main(control_main_t * const main) { + + if (!main) return; + + if (F_status_is_error(main->setting.state.status)) { + if ((main->setting.flag & control_main_flag_print_last_e) && main->program.message.verbosity > f_console_verbosity_error_e) { + fll_print_dynamic_raw(f_string_eol_s, main->program.message.to); + } + + return; + } + + if ((main->setting.flag & control_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); + } + + main->setting.state.status = F_none; + + if (main->setting.flag & (control_main_flag_help_e | control_main_flag_version_e | control_main_flag_copyright_e)) { + if (main->setting.flag & control_main_flag_help_e) { + control_print_message_help(&main->program.message); + } + else if (main->setting.flag & control_main_flag_version_e) { + fll_program_print_version(&main->program.message, control_program_version_s); + } + else if (main->setting.flag & control_main_flag_copyright_e) { + fll_program_print_copyright(&main->program.message); + } + + if ((main->setting.flag & control_main_flag_print_last_e) && main->program.message.verbosity > f_console_verbosity_error_e) { + fll_print_dynamic_raw(f_string_eol_s, main->program.message.to); + } + + return; + } + + if (main->setting.flag & control_main_flag_pipe_e) { + control_print_error_pipe_supported_not(&main->program.error); + + main->setting.state.status = F_status_set_error(F_support_not); + } + else if (main->setting.actions.used) { + main->setting.action = control_action_type_identify(main->setting.actions.array[0]); + + if (main->setting.action) { + control_action_verify(main); + } + else { + control_print_error_parameter_action_not(&main->program.error, main->setting.actions.array[0]); + + main->setting.state.status = F_status_set_error(F_parameter); + } + + if (F_status_is_error_not(main->setting.state.status)) { + control_packet_build(main); + + if (F_status_is_error(main->setting.state.status)) { + if (F_status_set_fine(main->setting.state.status) == F_too_large) { + control_print_error_request_packet_too_large(&main->program.error); + } + else { + control_print_error(&main->program.error, macro_control_f(control_packet_build)); + } + } + + if (F_status_is_error_not(main->setting.state.status)) { + control_packet_send(main); + + if (F_status_is_error(main->setting.state.status)) { + control_print_error(&main->program.error, macro_control_f(control_packet_send)); + } + } + + if (F_status_is_error_not(main->setting.state.status)) { + control_payload_header_t header = control_payload_header_t_initialize; + + control_packet_receive(main, &header); + + if (F_status_is_error(main->setting.state.status)) { + if (F_status_set_fine(main->setting.state.status) == F_too_large) { + control_print_error_response_packet_valid_not(&main->program.error); + } + else { + control_print_error(&main->program.error, macro_control_f(control_packet_receive)); + } + } + else { + control_packet_process(main, &header); + + // Print the error message only if the error message is not already printed. + if (F_status_is_error(main->setting.state.status)) { + if (header.type != control_payload_type_error_e && (header.type != control_payload_type_controller_e || F_status_set_fine(main->setting.state.status) != header.status || (header.status != F_failure && header.status != F_busy))) { + control_print_error(&main->program.error, macro_control_f(control_packet_process)); + } + } + } + } + } + + if (main->setting.socket.id != -1) { + f_socket_disconnect(&main->setting.socket, f_socket_close_fast_e); + } + } + else { + control_print_error_parameter_actions_none(&main->program.error); + + main->setting.state.status = F_status_set_error(F_data_not); + } + + if ((main->setting.flag & control_main_flag_print_last_e) && main->program.message.verbosity > f_console_verbosity_error_e) { + fll_print_dynamic_raw(f_string_eol_s, main->program.message.to); + } + + if (F_status_is_error(main->setting.state.status)) return; + + main->setting.state.status = F_none; + } +#endif // _di_control_main_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/control.h b/level_3/control/c/main/control.h similarity index 57% rename from level_3/control/c/control.h rename to level_3/control/c/main/control.h index ec77cc7..dd17517 100644 --- a/level_3/control/c/control.h +++ b/level_3/control/c/main/control.h @@ -4,11 +4,6 @@ * Project: Control * API Version: 0.7 * Licenses: lgpl-2.1-or-later - * - * This is the Control program. - * - * This program utilizes the Featureless Linux Library. - * This program is used to communicate with the "controller" program that exists as a system init (an alternative to sysvinit, initng, etc..). */ #ifndef _control_h #define _control_h @@ -35,6 +30,7 @@ #include #include #include +#include #include // FLL-1 includes. @@ -52,8 +48,22 @@ #include // Control includes. -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -71,19 +81,18 @@ extern "C" { * - F_signal_termination * * @param main - * The main program data. - * @param arguments - * The parameters passed to the process. - * - * @return - * F_none on success. + * The main program data and settings. * - * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal. + * This alters main.setting.state.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. * - * Status codes (with error bit) are returned on any problem. + * F_interrupt (with error bit) on (exit) signal received. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_control_main_ - extern f_status_t control_main(fll_program_data_t * const main, control_setting_t * const setting); + extern void control_main(control_main_t * const main); #endif // _di_control_main_ #ifdef __cplusplus diff --git a/level_3/control/c/main/main.c b/level_3/control/c/main/main.c new file mode 100644 index 0000000..bfde226 --- /dev/null +++ b/level_3/control/c/main/main.c @@ -0,0 +1,77 @@ +#include "control.h" + +int main(const int argc, const f_string_t *argv, const f_string_t *envp) { + + control_main_t data = control_main_t_initialize; + + data.program.debug.flag |= control_print_flag_debug_e | control_print_flag_out_e; + data.program.error.flag |= control_print_flag_error_e | control_print_flag_out_e; + data.program.output.flag |= control_print_flag_out_e; + data.program.message.flag |= control_print_flag_message_e | control_print_flag_out_e; + data.program.warning.flag |= control_print_flag_warning_e | control_print_flag_out_e; + data.program.error.custom = (void *) &data; + data.program.debug.custom = (void *) &data; + data.program.message.custom = (void *) &data; + data.program.output.custom = (void *) &data; + data.program.warning.custom = (void *) &data; + + f_console_parameter_t parameters[] = control_console_parameter_t_initialize; + + data.program.parameters.array = parameters; + data.program.parameters.used = control_parameter_total_d; + data.program.environment = envp; + + data.setting.socket.domain = f_socket_protocol_family_local_e; + data.setting.socket.type = f_socket_type_stream_e; + data.setting.socket.length = sizeof(struct sockaddr_un); + + if (f_pipe_input_exists()) { + data.program.pipe = fll_program_data_pipe_input_e; + } + + fll_program_standard_set_up(&data.program); + + f_file_umask_get(&data.program.umask); + + #ifdef _di_thread_support_ + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp); + + control_setting_load(arguments, &data); + } + + control_main(&data); + #else + { + f_thread_id_t id_signal; + + memset(&id_signal, 0, sizeof(f_thread_id_t)); + + data.setting.state.status = f_thread_create(0, &id_signal, &control_thread_signal, (void *) &data); + + if (F_status_is_error(data.setting.state.status)) { + control_print_error(&data.program.error, macro_control_f(f_thread_create)); + } + else { + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp); + + control_setting_load(arguments, &data); + } + + if (!control_signal_check(&data)) { + control_main(&data); + } + + f_thread_cancel(id_signal); + f_thread_join(id_signal, 0); + } + } + #endif // _di_thread_support_ + + control_main_delete(&data); + + fll_program_standard_set_down(&data.program); + + return (F_status_is_error(data.setting.state.status) || data.setting.state.status == F_false) ? 1 : 0; +} diff --git a/level_3/control/c/main.h b/level_3/control/c/main/main.h similarity index 100% rename from level_3/control/c/main.h rename to level_3/control/c/main/main.h diff --git a/level_3/control/c/main/packet.c b/level_3/control/c/main/packet.c new file mode 100644 index 0000000..56c11d5 --- /dev/null +++ b/level_3/control/c/main/packet.c @@ -0,0 +1,561 @@ +#include "control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_control_packet_build_ + void control_packet_build(control_main_t * const main) { + + if (!main) return; + + main->cache.packet.used = 0; + main->cache.large.used = 0; + main->cache.small.used = 0; + + f_number_unsigned_t i = 0; + + { + f_number_unsigned_t length = 5 + f_fss_header_s.used + f_fss_payload_s.used; + length += control_action_s.used + control_length_s.used + control_type_s.used; + length += (f_fss_payload_list_open_s.used + f_fss_payload_list_close_s.used) * 2; + length += (f_fss_payload_header_open_s.used + f_fss_payload_header_close_s.used) * 3; + length += main->setting.actions.array[0].used + f_string_ascii_0_s.used; + + // @todo This should properly handle escaping the FSS-0001 (Extended) Content and then count that length. + for (i = 1; i < main->setting.actions.used; ++i) { + length += f_fss_payload_header_next_s.used + main->setting.actions.array[i].used; + } // for + + if (main->setting.action == control_action_type_kexec_e || main->setting.action == control_action_type_reboot_e || main->setting.action == control_action_type_shutdown_e) { + length += control_init_s.used; + } + else { + length += control_controller_s.used; + } + + if (length > 0xffffffffu) { + main->setting.state.status = F_status_set_error(F_too_large); + + return; + } + + main->setting.state.status = f_string_dynamic_resize(length, &main->cache.packet); + if (F_status_is_error(main->setting.state.status)) return; + } + + f_state_t state = macro_f_state_t_initialize_1(control_allocation_large_d, control_allocation_small_d, F_none, 0, 0, 0, &fll_program_standard_signal_handle, 0, (void *) main, 0); + + f_string_static_t contents_array[main->setting.actions.used]; + f_string_statics_t contents = macro_f_string_statics_t_initialize_1(contents_array, 0, main->setting.actions.used); + + // The Packet Control Block. + { + f_char_t block_control = (f_char_t) control_packet_flag_binary_d; + + #ifdef _is_F_endian_big + block_control |= (f_char_t) control_packet_flag_endian_big_d; + #endif // _is_F_endian_big + + main->setting.state.status = f_string_append(&block_control, 1, &main->cache.packet); + if (F_status_is_error(main->setting.state.status)) return; + } + + // Reserve the Packet Size Block to be calculated later. + main->cache.packet.used = 5; + + // Payload Header: type. + if (main->setting.action == control_action_type_kexec_e || main->setting.action == control_action_type_reboot_e || main->setting.action == control_action_type_shutdown_e) { + contents_array[0] = control_init_s; + } + else { + contents_array[0] = control_controller_s; + } + + contents.used = 1; + + fll_fss_extended_write(control_type_s, contents, 0, &main->cache.large, &state); + + // Payload Header: action. + if (F_status_is_error_not(state.status)) { + for (contents.used = 0; contents.used < main->setting.actions.used; ++contents.used) { + contents_array[contents.used] = main->setting.actions.array[contents.used]; + } // for + + fll_fss_extended_write(control_action_s, contents, 0, &main->cache.large, &state); + } + + // Payload Header: length. + if (F_status_is_error_not(state.status)) { + contents_array[0] = f_string_ascii_0_s; + contents.used = 1; + + fll_fss_extended_write(control_length_s, contents, 0, &main->cache.large, &state); + } + + // Payload Packet: Header. + if (F_status_is_error_not(state.status)) { + fll_fss_payload_write(f_fss_header_s, main->cache.large, F_false, 0, &main->cache.packet, &state); + } + + // Payload Packet: Payload. + if (F_status_is_error_not(state.status)) { + main->cache.large.used = 0; + + fll_fss_payload_write(f_fss_payload_s, main->cache.large, F_false, 0, &main->cache.packet, &state); + } + + if (F_status_is_error(state.status)) { + main->setting.state.status = state.status; + + return; + } + + // Construct Packet Size Block. + #ifdef _is_F_endian_big + main->cache.packet.string[1] = main->cache.packet.used & 0xffu; + main->cache.packet.string[2] = main->cache.packet.used & 0xff00u; + main->cache.packet.string[3] = main->cache.packet.used & 0xff0000u; + main->cache.packet.string[4] = main->cache.packet.used & 0xff000000u; + #else + main->cache.packet.string[1] = main->cache.packet.used & 0xff000000u; + main->cache.packet.string[2] = main->cache.packet.used & 0xff0000u; + main->cache.packet.string[3] = main->cache.packet.used & 0xff00u; + main->cache.packet.string[4] = main->cache.packet.used & 0xffu; + #endif // _is_F_endian_big + + main->setting.state.status = F_none; + } +#endif // _di_control_packet_build_ + +#ifndef _di_control_packet_header_flag_ + uint8_t control_packet_header_flag(const uint8_t buffer[]) { + return (uint8_t) (((buffer[0] & 0x8u) ? control_packet_flag_binary_d : 0) | ((buffer[0] & 0x4u) ? control_packet_flag_endian_big_d : 0)); + } +#endif // _di_control_packet_header_flag_ + +#ifndef _di_control_packet_header_length_ + uint32_t control_packet_header_length(const bool is_big, const uint8_t buffer[]) { + + #ifdef _is_F_endian_big + if (is_big) return (buffer[1] << 24u) | (buffer[2] << 16u) | (buffer[3] << 8u) | buffer[4]; + #else + if (!is_big) return (buffer[1] << 24u) | (buffer[2] << 16u) | (buffer[3] << 8u) | buffer[4]; + #endif // _is_F_endian_big + + return (buffer[4] << 24u) | (buffer[3] << 16u) | (buffer[2] << 8u) | buffer[1]; + } +#endif // _di_control_packet_header_length_ + +#ifndef _di_control_packet_receive_ + void control_packet_receive(control_main_t * const main, control_payload_header_t * const header) { + + if (!main || !header) return; + + main->cache.large.used = 0; + main->cache.small.used = 0; + main->cache.packet.used = 0; + main->cache.packet_objects.used = 0; + main->cache.packet_contents.used = 0; + main->cache.header_objects.used = 0; + main->cache.header_contents.used = 0; + main->cache.delimits.used = 0; + + header->action = 0; + header->type = 0; + header->status = F_none; + header->length = 0; + + f_number_unsigned_t i = 0; + f_string_range_t range_header = f_string_range_t_initialize; + f_string_range_t range_payload = f_string_range_t_initialize; + + { + f_number_unsigned_t length = 5; + uint8_t head[length]; + + memset(head, 0, sizeof(uint8_t) * length); + + main->setting.state.status = f_socket_read(&main->setting.socket, f_socket_flag_peek_e, (void *) head, &length); + if (F_status_is_error(main->setting.state.status)) return; + + if (length < 5) { + main->setting.state.status = F_status_set_error(F_packet_not); + + return; + } + + // Only the first two bits of the 8 Control bits are allowed to be set to 1 for this Packet. + if (head[0] & (~(control_packet_flag_binary_d | control_packet_flag_endian_big_d))) { + main->setting.state.status = F_status_set_error(F_packet_not); + + return; + } + + length = control_packet_header_length(head[0] & control_packet_flag_endian_big_d, head); + + if (length > 0xffffffffu) { + main->setting.state.status = F_status_set_error(F_too_large); + + return; + } + + main->setting.state.status = f_string_dynamic_increase_by(length, &main->cache.large); + if (F_status_is_error(main->setting.state.status)) return; + + main->setting.state.status = f_socket_read(&main->setting.socket, f_socket_flag_wait_all_e, (void *) head, &length); + if (F_status_is_error(main->setting.state.status)) return; + + if (length < main->cache.large.used) { + main->setting.state.status = F_status_set_error(F_too_small); + + return; + } + + if (length > main->cache.large.used) { + main->setting.state.status = F_status_set_error(F_too_large); + + return; + } + } + + { + f_state_t state = macro_f_state_t_initialize_1(control_allocation_large_d, control_allocation_small_d, F_none, 0, 0, 0, &fll_program_standard_signal_handle, 0, (void *) main, 0); + f_string_range_t range_packet = macro_f_string_range_t_initialize_2(main->cache.large.used); + + fll_fss_basic_list_read(main->cache.large, &range_packet, &main->cache.packet_objects, &main->cache.packet_contents, &main->cache.delimits, 0, 0, &state); + + if (F_status_is_error(main->setting.state.status)) { + control_print_debug_packet_message(&main->program.debug, "Failure while reading FSS Basic List in the response packet", 0, 0); + + if (F_status_set_fine(main->setting.state.status) == F_memory_not) return; + + main->setting.state.status = F_status_set_error(F_header); + + return; + } + + f_fss_apply_delimit(main->cache.delimits, &main->cache.large, &state); + + if (F_status_is_error(state.status)) { + main->setting.state.status = state.status; + + control_print_debug_packet_message(&main->program.debug, "Failure while processing delimits for the FSS Basic List in the response packet", 0, 0); + + main->setting.state.status = F_status_set_error(F_header); + + return; + } + + main->cache.delimits.used = 0; + + { + f_string_ranges_t *content_header = 0; + f_string_ranges_t *content_payload = 0; + + for (; i < main->cache.packet_objects.used; ++i) { + + if (f_compare_dynamic_partial_string(f_fss_header_s.string, main->cache.large, f_fss_header_s.used, main->cache.packet_objects.array[i]) == F_equal_to) { + + // The FSS-000E (Payload) standard does not prohibit multiple "header", but such cases are not supported by the controller and the control programs. + if (content_header) { + control_print_debug_packet_message(&main->program.debug, "Multiple %[" F_fss_header_s "%] found in response packet", 0, 0); + + main->setting.state.status = F_status_set_error(F_payload_not); + + return; + } + + content_header = &main->cache.packet_contents.array[i]; + } + else if (f_compare_dynamic_partial_string(f_fss_payload_s.string, main->cache.large, f_fss_payload_s.used, main->cache.packet_objects.array[i]) == F_equal_to) { + + // Only a single "payload" is supported by the FSS-000E (Payload) standard. + if (content_payload) { + control_print_debug_packet_message(&main->program.debug, "Multiple %[" F_fss_payload_s "%] found in response packet", 0, 0); + + main->setting.state.status = F_status_set_error(F_payload_not); + + return; + } + + if (i + 1 < main->cache.packet_contents.used) { + control_print_debug_packet_message(&main->program.debug, "Invalid FSS Payload format, the %[" F_fss_payload_s "%] is required to be the last FSS Basic List Object", 0, 0); + + main->setting.state.status = F_status_set_error(F_payload_not); + + return; + } + + content_payload = &main->cache.packet_contents.array[i]; + } + } // for + + if (!content_header) { + control_print_debug_packet_message(&main->program.debug, "Did not find a %[" F_fss_header_s "%] in the response packet", 0, 0); + + main->setting.state.status = F_status_set_error(F_payload_not); + + return; + } + + if (!content_payload) { + control_print_debug_packet_message(&main->program.debug, "Did not find a %[" F_fss_payload_s "%] in the response packet", 0, 0); + + main->setting.state.status = F_status_set_error(F_payload_not); + + return; + } + + range_header = content_header->array[0]; + range_payload = content_payload->array[0]; + } + + { + // 0x1 = found action, 0x2 = found length, 0x4 = found status, 0x8 = found_type. + uint8_t found = 0; + f_number_unsigned_t number = 0; + f_string_range_t range = range_header; + + fll_fss_extended_read(main->cache.large, &range, &main->cache.header_objects, &main->cache.header_contents, 0, 0, &main->cache.delimits, 0, &state); + + if (F_status_is_error(main->setting.state.status)) { + control_print_debug_packet_message(&main->program.debug, "Failure while reading FSS Extended in the response packet", 0, 0); + + if (F_status_set_fine(main->setting.state.status) == F_memory_not) return; + + main->setting.state.status = F_status_set_error(F_header_not); + + return; + } + + f_fss_apply_delimit(main->cache.delimits, &main->cache.large, &state); + + if (F_status_is_error(state.status)) { + main->setting.state.status = state.status; + + control_print_debug_packet_message(&main->program.debug, "Failure while processing delimits for the FSS Basic List in the response packet", 0, 0); + + main->setting.state.status = F_status_set_error(F_header_not); + + return; + } + + if (!main->cache.header_contents.used) { + control_print_debug_packet_message(&main->program.debug, "Did not find any Content within the %[" F_fss_header_s "%]", 0, 0); + + main->setting.state.status = F_status_set_error(F_header_not); + + return; + } + + for (i = 0; i < main->cache.header_objects.used; ++i) { + + if (f_compare_dynamic_partial_string(control_action_s.string, main->cache.large, control_action_s.used, main->cache.header_objects.array[i]) == F_equal_to) { + if (!(found & 0x1)) { + const f_number_unsigned_t action_length = (main->cache.header_contents.array[i].array[0].stop - main->cache.header_contents.array[i].array[0].start) + 1; + char action_string[action_length + 1]; + const f_string_static_t action = macro_f_string_static_t_initialize_1(action_string, 0, action_length); + + memcpy(action_string, main->cache.large.string + main->cache.header_contents.array[i].array[0].start, action_length); + action_string[action_length] = 0; + + found |= 0x1; + + control_print_debug_packet_header_object_and_content(&main->program.debug, control_action_s, main->cache.large, main->cache.header_contents.array[i].array[0]); + + header->action = control_action_type_identify(action); + + if (!header->action) { + control_print_debug_packet_message(&main->program.debug, "Failed to identify %[" CONTROL_action_s "%] from: ", &main->cache.large, &main->cache.header_contents.array[i].array[0]); + + main->setting.state.status = F_status_set_error(F_header_not); + + return; + } + } + else { + control_print_warning_packet_header_duplicate_object(&main->program.warning, control_action_s); + } + } + else if (f_compare_dynamic_partial_string(control_length_s.string, main->cache.large, control_length_s.used, main->cache.header_objects.array[i]) == F_equal_to) { + if (!(found & 0x2)) { + found |= 0x2; + number = 0; + + control_print_debug_packet_header_object_and_content(&main->program.debug, control_length_s, main->cache.large, main->cache.header_contents.array[i].array[0]); + + main->setting.state.status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, main->cache.large, main->cache.header_contents.array[i].array[0], &number); + + if (F_status_is_error(main->setting.state.status)) { + control_print_debug_packet_message(&main->program.debug, "Failed to process number for %[" CONTROL_length_s "%] in the response packet, number is:", &main->cache.large, &main->cache.header_contents.array[i].array[0]); + + main->setting.state.status = F_status_set_error(F_header_not); + + return; + } + + if (number > F_type_size_max_32_unsigned_d) { + control_print_debug_packet_message(&main->program.debug, "Processed number for %[" CONTROL_length_s "%] exceeds allowed size in the response packet, number is:", &main->cache.large, &main->cache.header_contents.array[i].array[0]); + + main->setting.state.status = F_status_set_error(F_header_not); + + return; + } + + header->length = (uint16_t) number; + } + else { + control_print_warning_packet_header_duplicate_object(&main->program.warning, control_length_s); + } + } + else if (f_compare_dynamic_partial_string(control_status_s.string, main->cache.large, control_status_s.used, main->cache.header_objects.array[i]) == F_equal_to) { + if (!(found & 0x4)) { + found |= 0x4; + number = 0; + + control_print_debug_packet_header_object_and_content(&main->program.debug, control_status_s, main->cache.large, main->cache.header_contents.array[i].array[0]); + + // Attempt to get packet status as a number. + main->setting.state.status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, main->cache.large, main->cache.header_contents.array[i].array[0], &number); + + if (F_status_set_fine(main->setting.state.status) == F_number) { + + // Not a number, so attempt get by packet status string name. + const f_number_unsigned_t name_length = (main->cache.header_contents.array[i].array[0].stop - main->cache.header_contents.array[i].array[0].start) + 1; + char name_string[name_length + 1]; + const f_string_static_t name = macro_f_string_static_t_initialize_1(name_string, 0, name_length); + + memcpy(name_string, main->cache.large.string + main->cache.header_contents.array[i].array[0].start, name_length); + name_string[name_length] = 0; + + main->setting.state.status = fl_status_string_from(name, &header->status); + + if (F_status_is_error(main->setting.state.status)) { + control_print_debug_packet_message(&main->program.debug, "Failed to process %[" CONTROL_status_s "%] in the response packet, Content is:", &main->cache.large, &main->cache.header_contents.array[i].array[0]); + + main->setting.state.status = F_status_set_error(F_header_not); + + return; + } + } + else if (F_status_is_error(main->setting.state.status)) { + control_print_debug_packet_message(&main->program.debug, "Failed to process number for %[" CONTROL_status_s "%] in the response packet, number is:", &main->cache.large, &main->cache.header_contents.array[i].array[0]); + + if (F_status_set_fine(main->setting.state.status) == F_memory_not) return; + + main->setting.state.status = F_status_set_error(F_header_not); + + return; + } + else { + if (number > F_status_size_max_with_bits_d) { + control_print_debug_packet_message(&main->program.debug, "Processed number for %[" CONTROL_status_s "%] exceeds allowed size in the response packet, number is:", &main->cache.large, &main->cache.header_contents.array[i].array[0]); + + main->setting.state.status = F_status_set_error(F_header_not); + + return; + } + } + } + else { + control_print_warning_packet_header_duplicate_object(&main->program.warning, control_length_s); + } + } + else if (f_compare_dynamic_partial_string(control_type_s.string, main->cache.large, control_type_s.used, main->cache.header_objects.array[i]) == F_equal_to) { + if (!(found & 0x8)) { + found |= 0x8; + + control_print_debug_packet_header_object_and_content(&main->program.debug, control_type_s, main->cache.large, main->cache.header_contents.array[i].array[0]); + + if (f_compare_dynamic_partial_string(control_controller_s.string, main->cache.large, control_controller_s.used, main->cache.header_contents.array[i].array[0]) == F_equal_to) { + header->type = control_payload_type_controller_e; + } + else if (f_compare_dynamic_partial_string(control_error_s.string, main->cache.large, control_error_s.used, main->cache.header_contents.array[i].array[0]) == F_equal_to) { + header->type = control_payload_type_error_e; + } + else { + control_print_debug_packet_message(&main->program.debug, "Unknown %[" CONTROL_type_s "%] in response packet, Content is:", &main->cache.large, &main->cache.header_contents.array[i].array[0]); + + main->setting.state.status = F_status_set_error(F_header_not); + + return; + } + } + else { + control_print_warning_packet_header_duplicate_object(&main->program.warning, control_type_s); + } + } + } + } + } + + main->setting.state.status = F_none; + } +#endif // _di_control_packet_receive_ + +#ifndef _di_control_packet_process_ + void control_packet_process(control_main_t * const main, control_payload_header_t * const header) { + + if (!main || !header) return; + + f_string_static_t string_status = f_string_static_t_initialize; + + { + main->setting.state.status = f_status_string_to(header->status, &string_status); + + if (F_status_is_error(main->setting.state.status)) { + control_print_warning_packet_process_string_to_failed(&main->program.warning, header->status, main->setting.state.status); + + return; + } + } + + if (main->setting.flag & control_main_flag_return_e) { + fll_print_format("response %q %q %q%r", main->program.output.to, control_payload_type_name(header->type), control_action_type_name(header->action), string_status, f_string_eol_s); + } + else if (header->type == control_payload_type_error_e) { + control_print_error_packet_response(&main->program.error, *header, string_status); + } + else if (header->status == F_failure) { + control_print_error_packet_response_failure(&main->program.error, *header, string_status); + } + else if (header->status == F_busy) { + control_print_warning_packet_response_busy(&main->program.warning, *header, string_status); + } + else if (header->status == F_done || header->status == F_success) { + control_print_message_packet_response(&main->program.output, *header, string_status); + } + else { + + // Set type to 0 to inform the caller to handle this error. + header->type = 0; + + main->setting.state.status = F_status_set_error(F_known_not); + + return; + } + + if (header->type == control_payload_type_error_e || header->status == F_failure || header->status == F_busy) { + main->setting.state.status = F_status_set_error(header->status); + } + else { + main->setting.state.status = header->status; + } + } +#endif // _di_control_packet_process_ + +#ifndef _di_control_packet_send_ + void control_packet_send(control_main_t * const main) { + + if (!main) return; + + main->setting.size_write = main->cache.packet.used; + + main->setting.state.status = f_socket_write(&main->setting.socket, 0, (void *) &main->cache.packet, 0); + } +#endif // _di_control_packet_send_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/packet.h b/level_3/control/c/main/packet.h new file mode 100644 index 0000000..e2e04ba --- /dev/null +++ b/level_3/control/c/main/packet.h @@ -0,0 +1,155 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the packet functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_packet_h +#define _control_packet_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Build the payload, storing it in the large cache. + * + * @param main + * The main program data. + * + * @return + * F_none on success. + * + * F_too_large (with error bit) If the message is too large for the packet format to transmit. + * + * Errors (with error bit) from: f_string_append(). + * Errors (with error bit) from: f_string_dynamic_append(). + * Errors (with error bit) from: f_string_dynamic_resize(). + * Errors (with error bit) from: fll_fss_extended_write(). + * Errors (with error bit) from: fll_fss_payload_write(). + * + * @see f_string_append() + * @see f_string_dynamic_append() + * @see f_string_dynamic_resize() + */ +#ifndef _di_control_packet_build_ + extern void control_packet_build(control_main_t * const main); +#endif // _di_control_packet_build_ + +/** + * Given the header buffer, get the flag bits. + * + * @param buffer + * The buffer to read the length of and get the + * + * @return + * The 8-bit number representing the flags. + */ +#ifndef _di_control_packet_header_flag_ + extern uint8_t control_packet_header_flag(const uint8_t buffer[]); +#endif // _di_control_packet_header_flag_ + +/** + * Given the header buffer, get the length bits. + * + * The endianness is automatically detected and swapped by this function to guarantee host order bytes. + * + * @param is_big + * If TRUE, then the length in the buffer is in big endian format. + * If FALSE, then the length in the buffer is in little endian format. + * @param buffer + * The buffer to read the length of and get the + * + * @return + * The 32-bit number representing the length. + */ +#ifndef _di_control_packet_header_length_ + extern uint32_t control_packet_header_length(const bool is_big, const uint8_t buffer[]); +#endif // _di_control_packet_header_length_ + +/** + * Receive the response from the remote socket, storing it in the large cache. + * + * @todo consider returning F_header (with error bit) fo most header processing errors rather than individual status codes. + * + * @param main + * The main program data. + * + * This alters main.setting.state.status: + * F_none on success. + * + * F_header_not (with error bit) If there is a problem processing the packet header. + * F_memory_not (with error bit) On out of memory issues (this is passed through from called functions). + * F_packet_not (with error bit) If the received packet is not a valid packet or not a supported packet structure. + * F_payload_not (with error bit) If there is a problem processing the packet payload. + * F_too_large (with error bit) If the received packet specifies a size that is too large or the actual size is larger than the specified size. + * F_too_small (with error bit) If the received packet actual size is smaller than the specified size. + * + * Errors (with error bit) from: f_socket_read(). + * Errors (with error bit) from: f_string_dynamic_increase_by(). + * Errors (with error bit) from: fl_conversion_dynamic_partial_to_unsigned_detect(). + * Errors (with error bit) from: fll_fss_extended_read(). + * Errors (with error bit) from: fll_fss_basic_list_read(). + * @param header + * The control payload packet header data. + * + * @see f_socket_read() + * @see f_string_dynamic_increase_by() + * @see fl_conversion_dynamic_partial_to_unsigned_detect() + * @see f_fss_apply_delimit() + * @see fl_status_string_from() + * @see fll_fss_extended_read() + * @see fll_fss_basic_list_read() + */ +#ifndef _di_control_packet_receive_ + extern void control_packet_receive(control_main_t * const main, control_payload_header_t * const header); +#endif // _di_control_packet_receive_ + +/** + * Process the received and loaded packet. + * + * @param main + * The main program data. + * + * This alters main.setting.state.status: + * F_done on success but action has no success or failure states. + * F_success on success. + * + * F_busy (with error bit) + * F_failure (with error bit) on success but controller returned failure for action. + * F_known_not (with error bit) if the Payload type is unknown. + * Any error (with error bit) on failure where the error is defined by the controller service. + * @param header + * The control payload packet header data. + */ +#ifndef _di_control_packet_process_ + extern void control_packet_process(control_main_t * const main, control_payload_header_t * const header); +#endif // _di_control_packet_process_ + +/** + * Send the payload to the remote socket, getting the payload from the large cache. + * + * @param main + * The main program data. + * + * This alters main.setting.state.status: + * F_none on success. + * + * Errors (with error bit) from: f_socket_write(). + * + * @see f_socket_write() + */ +#ifndef _di_control_packet_send_ + extern void control_packet_send(control_main_t * const main); +#endif // _di_control_packet_send_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_packet_h diff --git a/level_3/control/c/main/payload.c b/level_3/control/c/main/payload.c new file mode 100644 index 0000000..aa20e06 --- /dev/null +++ b/level_3/control/c/main/payload.c @@ -0,0 +1,38 @@ +#include "control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_control_payload_type_identify_ + const uint8_t control_payload_type_identify(const f_string_static_t payload) { + + if (f_compare_dynamic(payload, control_controller_s) == F_equal_to) return control_payload_type_controller_e; + if (f_compare_dynamic(payload, control_error_s) == F_equal_to) return control_payload_type_error_e; + if (f_compare_dynamic(payload, control_init_s) == F_equal_to) return control_payload_type_init_e; + + return 0; + } +#endif // _di_control_payload_type_identify_ + +#ifndef _di_control_payload_type_name_ + const f_string_static_t control_payload_type_name(const uint8_t type) { + + switch (type) { + case control_payload_type_controller_e: + return control_controller_s; + + case control_payload_type_error_e: + return control_error_s; + + case control_payload_type_init_e: + return control_init_s; + } + + return f_string_empty_s; + } +#endif // _di_control_payload_type_name_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/payload.h b/level_3/control/c/main/payload.h new file mode 100644 index 0000000..12142a0 --- /dev/null +++ b/level_3/control/c/main/payload.h @@ -0,0 +1,51 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the payload functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_payload_h +#define _control_payload_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Identify the payload code the given name represents. + * + * @param payload + * The string representing a payload. + * + * @return + * The payload type code on success. + * 0 if name is unknown. + */ +#ifndef _di_control_payload_type_identify_ + extern const uint8_t control_payload_type_identify(const f_string_static_t payload); +#endif // _di_control_payload_type_identify_ + +/** + * Get a string representing the payload type. + * + * @param type + * The payload type id. + * + * @return + * The string with used > 0 on success. + * The string with used == 0 if no match was found. + */ +#ifndef _di_control_payload_type_name_ + extern const f_string_static_t control_payload_type_name(const uint8_t type); +#endif // _di_control_payload_type_name_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_payload_h diff --git a/level_3/control/c/main/print/data.c b/level_3/control/c/main/print/data.c new file mode 100644 index 0000000..39790a2 --- /dev/null +++ b/level_3/control/c/main/print/data.c @@ -0,0 +1,9 @@ +#include "../control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/print/data.h b/level_3/control/c/main/print/data.h new file mode 100644 index 0000000..e075bff --- /dev/null +++ b/level_3/control/c/main/print/data.h @@ -0,0 +1,23 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the print data functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_print_data_h +#define _control_print_data_h + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_print_data_h diff --git a/level_3/control/c/main/print/debug.c b/level_3/control/c/main/print/debug.c new file mode 100644 index 0000000..d22d59e --- /dev/null +++ b/level_3/control/c/main/print/debug.c @@ -0,0 +1,59 @@ +#include "../control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_control_print_debug_packet_header_object_and_content_ + f_status_t control_print_debug_packet_header_object_and_content(fl_print_t * const print, const f_string_static_t object, const f_string_static_t content, const f_string_range_t content_range) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_debug_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("Packet header Object '%[%Q%]", print->to, print->set->notable, object, print->set->notable); + fl_print_format("' has value '%[%/Q%]'.%r", print->to, print->set->notable, content, content_range, print->set->notable, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_debug_packet_header_object_and_content_ + +#ifndef _di_control_print_debug_packet_message_ + f_status_t control_print_debug_packet_message(fl_print_t * const print, const f_string_t message, const f_string_static_t *buffer, const f_string_range_t *range) { + + if (!print || !print->custom) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_debug_e) return F_output_not; + + control_main_t * const main = (control_main_t *) print->custom; + + f_file_stream_lock(print->to); + + fl_print_format("%s", print->to, message); + + if (buffer) { + if (range) { + fl_print_format("'%[%/Q%]'", print->to, print->set->notable, *buffer, *range, print->set->notable); + } + else { + fl_print_format("'%[%/Q%]'", print->to, print->set->notable, *buffer, print->set->notable); + } + } + + if (main->setting.state.status) { + fl_print_format(", with status code %[%ui%]'", print->to, print->set->notable, main->setting.state.status, print->set->notable); + } + + fl_print_format(".%r", print->to, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_debug_packet_message_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/print/debug.h b/level_3/control/c/main/print/debug.h new file mode 100644 index 0000000..a27e4b4 --- /dev/null +++ b/level_3/control/c/main/print/debug.h @@ -0,0 +1,79 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the print functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_print_debug_h +#define _control_print_debug_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print a message displaying the object and content for some packet header. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param object + * The object string. + * @param content + * The content string. + * @param content_range + * The range representing the content where the content is found within the content string. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_debug_packet_header_object_and_content_ + extern f_status_t control_print_debug_packet_header_object_and_content(fl_print_t * const print, const f_string_static_t object, const f_string_static_t content, const f_string_range_t content_range); +#endif // _di_control_print_debug_packet_header_object_and_content_ + +/** + * Print a debug message regarding some packet. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param message + * The message to print. + * + * A single "%[" followed by a single "%]" is supported in the message and is replaced with "notable" context. + * @param buffer + * (optional) An additonal message to print (this is syntax highlighted). + * Set to NULL to not use. + * @param range + * (optional) The range within the buffer to print rather than printing the entire buffer. + * Set to NULL to not use. + * This is ignored when buffer is NULL. + * @param status + * (optional) A status code that triggered the failure (this is syntax highlighted). + * Set to NULL to not use. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_debug_packet_message_ + extern f_status_t control_print_debug_packet_message(fl_print_t * const print, const f_string_t message, const f_string_static_t *buffer, const f_string_range_t *range); +#endif // _di_control_print_debug_packet_message_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_print_debug_h diff --git a/level_3/control/c/main/print/error.c b/level_3/control/c/main/print/error.c new file mode 100644 index 0000000..f074e17 --- /dev/null +++ b/level_3/control/c/main/print/error.c @@ -0,0 +1,419 @@ +#include "../control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_control_print_error_ + f_status_t control_print_error(fl_print_t * const print, const f_string_t function) { + + if (!print || !print->custom) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + fll_error_print(print, F_status_set_fine(((control_main_t *) print->custom)->setting.state.status), function, fll_error_file_flag_fallback_e); + + return F_none; + } +#endif // _di_control_print_error_ + +#ifndef _di_control_print_error_file_ + f_status_t control_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_error_e) return F_output_not; + + control_main_t * const main = (control_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_none; + } +#endif // _di_control_print_error_file_ + +#ifndef _di_control_print_error_packet_response_ + f_status_t control_print_error_packet_response(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status) { + + if (!print || !print->custom) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + control_main_t * const main = (control_main_t *) print->custom; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QReceived error response for " CONTROL_action_s " '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%q%]", print->to, print->set->notable, control_action_type_name(header.action), print->set->notable); + fl_print_format("%[' with status '%]", print->to, print->set->error, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, string_status, print->set->notable); + fl_print_format("%[' (%]", print->to, print->set->error, print->set->error); + fl_print_format("%[%ui%]", print->to, print->set->notable, header.status, print->set->notable); + + if (header.length) { + fl_print_format("%[): %/Q%]%r", print->to, print->set->error, print->set->error, main->cache.large, main->cache.packet_contents.array[main->cache.packet_contents.used - 1].array[0], f_string_eol_s); + } + else { + fl_print_format("%[).%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + } + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_packet_response_ + +#ifndef _di_control_print_error_packet_response_failure_ + f_status_t control_print_error_packet_response_failure(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status) { + + if (!print || !print->custom) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + control_main_t * const main = (control_main_t *) print->custom; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe action '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, control_action_type_name(header.action), print->set->notable); + fl_print_format("%[' failed with status '%]", print->to, print->set->error, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, string_status, print->set->notable); + fl_print_format("%[' (%]", print->to, print->set->error, print->set->error); + fl_print_format("%[%ui%]", print->to, print->set->notable, header.status, print->set->notable); + + if (header.length) { + fl_print_format("%[): %/Q%]%r", print->to, print->set->error, print->set->error, main->cache.large, main->cache.packet_contents.array[main->cache.packet_contents.used - 1].array[0], f_string_eol_s); + } + else { + fl_print_format("%[).%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + } + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_packet_response_failure_ + +#ifndef _di_control_print_error_parameter_actions_none_ + f_status_t control_print_error_parameter_actions_none(fl_print_t * const print) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + fll_print_format("%[%QNo actions provided.%]%r", print->to, print->set->error, print->prefix, print->set->error, f_string_eol_s); + + return F_none; + } +#endif // _di_control_print_error_parameter_actions_none_ + +#ifndef _di_control_print_error_parameter_action_not_ + f_status_t control_print_error_parameter_action_not(fl_print_t * const print, const f_string_static_t action) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe parameter '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable); + fl_print_format("%[' is not a known controller action.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_parameter_action_not_ + +#ifndef _di_control_print_error_parameter_action_rule_basename_empty_ + f_status_t control_print_error_parameter_action_rule_basename_empty(fl_print_t * const print, const f_string_static_t action) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe action parameter '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable); + fl_print_format("%[' a rule base name cannot be an empty string.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_parameter_action_rule_basename_empty_ + +#ifndef _di_control_print_error_parameter_action_rule_directory_empty_ + f_status_t control_print_error_parameter_action_rule_directory_empty(fl_print_t * const print, const f_string_static_t action) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe action parameter '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable); + fl_print_format("%[' a rule directory path cannot be an empty string.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_parameter_action_rule_directory_empty_ + +#ifndef _di_control_print_error_parameter_action_rule_empty_ + f_status_t control_print_error_parameter_action_rule_empty(fl_print_t * const print, const f_string_static_t action) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe action parameter '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable); + fl_print_format("%[' a rule name cannot be an empty string.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_parameter_action_rule_empty_ + +#ifndef _di_control_print_error_parameter_action_rule_not_ + f_status_t control_print_error_parameter_action_rule_not(fl_print_t * const print, const f_string_static_t action) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe action parameter '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable); + fl_print_format("%[' requires either a full rule name or a rule directory path along with the rule base name.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_parameter_action_rule_not_ + +#ifndef _di_control_print_error_parameter_action_rule_too_few_ + f_status_t control_print_error_parameter_action_rule_too_few(fl_print_t * const print, const f_string_static_t action) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe action parameter '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable); + fl_print_format("%[' has too few arguments.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_parameter_action_rule_too_few_ + +#ifndef _di_control_print_error_parameter_action_rule_too_few_with_ + f_status_t control_print_error_parameter_action_rule_too_few_with(fl_print_t * const print, const f_string_static_t action, const f_string_static_t with) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe action parameter '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable); + fl_print_format("%[' when used with '%]", print->to, print->set->error, print->set->error, f_string_eol_s); + fl_print_format("%[%Q%]", print->to, print->set->notable, with, print->set->notable); + fl_print_format("%[' has too few arguments.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_parameter_action_rule_too_few_with_ + +#ifndef _di_control_print_error_parameter_action_rule_too_many_ + f_status_t control_print_error_parameter_action_rule_too_many(fl_print_t * const print, const f_string_static_t action) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe action parameter '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable); + fl_print_format("%[' has too many arguments.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_parameter_action_rule_too_many_ + +#ifndef _di_control_print_error_parameter_action_rule_too_many_with_ + f_status_t control_print_error_parameter_action_rule_too_many_with(fl_print_t * const print, const f_string_static_t action, const f_string_static_t with) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe action parameter '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable); + fl_print_format("%[' when used with '%]", print->to, print->set->error, print->set->error, f_string_eol_s); + fl_print_format("%[%Q%]", print->to, print->set->notable, with, print->set->notable); + fl_print_format("%[' has too many arguments.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_parameter_action_rule_too_many_with_ + +#ifndef _di_control_print_error_parameter_action_rule_with_unknown_ + f_status_t control_print_error_parameter_action_rule_with_unknown(fl_print_t * const print, const f_string_static_t action, const f_string_static_t with) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe action parameter '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, action, print->set->notable); + fl_print_format("%[' does not know the argument '%]", print->to, print->set->error, print->set->error, f_string_eol_s); + fl_print_format("%[%Q%]", print->to, print->set->notable, with, print->set->notable); + fl_print_format("%['.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_parameter_action_rule_with_unknown_ + +#ifndef _di_control_print_error_parameter_value_empty_ + f_status_t control_print_error_parameter_value_empty(fl_print_t * const print, const f_string_static_t parameter) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe value for the parameter '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%r%r%]", print->to, print->set->notable, f_console_symbol_long_normal_s, parameter, print->set->notable); + fl_print_format("%[' must not be an empty string.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_parameter_value_empty_ + +#ifndef _di_control_print_error_parameter_value_not_ + f_status_t control_print_error_parameter_value_not(fl_print_t * const print, const f_string_static_t parameter) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe parameter '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%r%r%]", print->to, print->set->notable, f_console_symbol_long_normal_s, parameter, print->set->notable); + fl_print_format("%[' is specified, but no value is given.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_parameter_value_not_ + +#ifndef _di_control_print_error_pipe_supported_not_ + f_status_t control_print_error_pipe_supported_not(fl_print_t * const print) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + fll_print_format("%[%QPipe input is not supported by this program.%]%r", print->to, print->set->error, print->prefix, print->set->error, f_string_eol_s); + + return F_none; + } +#endif // _di_control_print_error_pipe_supported_not_ + +#ifndef _di_control_print_error_response_packet_valid_not_ + f_status_t control_print_error_response_packet_valid_not(fl_print_t * const print) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + fll_print_format("%[%QThe received response is not a valid or supported packet.%]%r", print->to, print->set->error, print->prefix, print->set->error, f_string_eol_s); + + return F_none; + } +#endif // _di_control_print_error_response_packet_valid_not_ + +#ifndef _di_control_print_error_request_packet_too_large_ + f_status_t control_print_error_request_packet_too_large(fl_print_t * const print) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + fll_print_format("%[%QThe generated packet is too large, cannot send packet.%]%r", print->to, print->set->error, print->prefix, print->set->error, f_string_eol_s); + + return F_none; + } +#endif // _di_control_print_error_request_packet_too_large_ + +#ifndef _di_control_print_error_socket_file_failed_ + f_status_t control_print_error_socket_file_failed(fl_print_t * const print, const f_string_static_t path_socket) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QFailed to connect to the socket file '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, path_socket, print->set->notable); + fl_print_format("%['.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_socket_file_failed_ + +#ifndef _di_control_print_error_socket_file_missing_ + f_status_t control_print_error_socket_file_missing(fl_print_t * const print, const f_string_static_t path_socket) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe controller socket file '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, path_socket, print->set->notable); + fl_print_format("%[' could not be found and is required.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_socket_file_missing_ + +#ifndef _di_control_print_error_socket_file_not_ + f_status_t control_print_error_socket_file_not(fl_print_t * const print, const f_string_static_t path_socket) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe controller socket file '%]", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format("%[%Q%]", print->to, print->set->notable, path_socket, print->set->notable); + fl_print_format("%[' is not a socket file.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_error_socket_file_not_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/print/error.h b/level_3/control/c/main/print/error.h new file mode 100644 index 0000000..08ace68 --- /dev/null +++ b/level_3/control/c/main/print/error.h @@ -0,0 +1,492 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the print error functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_print_error_h +#define _control_print_error_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print generic error message regarding a function failing in some way. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * + * @return + * F_none 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_control_print_error_ + extern f_status_t control_print_error(fl_print_t * const print, const f_string_t function); +#endif // _di_control_print_error_ + +/** + * Print file related error or warning messages. + * + * @param print + * The output structure to print to. + * + * 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_none 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_file_print() + */ +#ifndef _di_control_print_error_file_ + extern f_status_t control_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_control_print_error_file_ + +/** + * Print an error from the packet response. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param header + * The control payload packet header data. + * @param status + * A string representing the name of the status code from header.status. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_packet_response_ + extern f_status_t control_print_error_packet_response(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t status); +#endif // _di_control_print_error_packet_response_ + +/** + * Print a error about a packet response failure. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param header + * The control payload packet header data. + * @param status + * A string representing the name of the status code from header.status. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_packet_response_failure_ + extern f_status_t control_print_error_packet_response_failure(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status); +#endif // _di_control_print_error_packet_response_failure_ +/** + * Print an error message about no actions being provided. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_actions_none_ + extern f_status_t control_print_error_parameter_actions_none(fl_print_t * const print); +#endif // _di_control_print_error_parameter_actions_none_ + +/** + * Print an error message about the given parameter not matching the known set of controller actions. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param action + * The parameter representing an action. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_action_not_ + extern f_status_t control_print_error_parameter_action_not(fl_print_t * const print, const f_string_static_t action); +#endif // _di_control_print_error_parameter_action_not_ + +/** + * Print an error message about the given parameter being a rule action having an empty rule basename. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param action + * The parameter representing an action. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_action_rule_basename_empty_ + extern f_status_t control_print_error_parameter_action_rule_basename_empty(fl_print_t * const print, const f_string_static_t action); +#endif // _di_control_print_error_parameter_action_rule_basename_empty_ + +/** + * Print an error message about the given parameter being a rule action having an empty rule directory path. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param action + * The parameter representing an action. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_action_rule_directory_empty_ + extern f_status_t control_print_error_parameter_action_rule_directory_empty(fl_print_t * const print, const f_string_static_t action); +#endif // _di_control_print_error_parameter_action_rule_directory_empty_ + +/** + * Print an error message about the given parameter being a rule action having an empty rule name. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param action + * The parameter representing an action. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_action_rule_empty_ + extern f_status_t control_print_error_parameter_action_rule_empty(fl_print_t * const print, const f_string_static_t action); +#endif // _di_control_print_error_parameter_action_rule_empty_ + +/** + * Print an error message about the given parameter being a rule action but no rule name is specified. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param action + * The parameter representing an action. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_action_rule_not_ + extern f_status_t control_print_error_parameter_action_rule_not(fl_print_t * const print, const f_string_static_t action); +#endif // _di_control_print_error_parameter_action_rule_not_ + +/** + * Print an error message about the given parameter being a rule action having too few arguments passed. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param action + * The parameter representing an action. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_action_rule_too_few_ + extern f_status_t control_print_error_parameter_action_rule_too_few(fl_print_t * const print, const f_string_static_t action); +#endif // _di_control_print_error_parameter_action_rule_too_few_ + +/** + * Print an error message about the given parameter being a rule action having few many arguments passed for a given "with". + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param action + * The parameter representing an action. + * @param with + * The additional parameter in which is requiring additional arguments that are not met. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_action_rule_too_few_with_ + extern f_status_t control_print_error_parameter_action_rule_too_few_with(fl_print_t * const print, const f_string_static_t action, const f_string_static_t with); +#endif // _di_control_print_error_parameter_action_rule_too_few_with_ + +/** + * Print an error message about the given parameter being a rule action having too many arguments passed. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param action + * The parameter representing an action. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_action_rule_too_many_ + extern f_status_t control_print_error_parameter_action_rule_too_many(fl_print_t * const print, const f_string_static_t action); +#endif // _di_control_print_error_parameter_action_rule_too_many_ + +/** + * Print an error message about the given parameter being a rule action having too many arguments passed for a given "with". + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param action + * The parameter representing an action. + * @param with + * The additional parameter in which is requiring additional arguments that are not met. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_action_rule_too_many_with_ + extern f_status_t control_print_error_parameter_action_rule_too_many_with(fl_print_t * const print, const f_string_static_t action, const f_string_static_t with); +#endif // _di_control_print_error_parameter_action_rule_too_many_with_ +/** + * Print an error message about the given parameter being unknown for the use with the given action. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param action + * The parameter representing an action. + * @param with + * The additional parameter in which is requiring additional arguments that are not met. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_action_rule_with_unknown_ + extern f_status_t control_print_error_parameter_action_rule_with_unknown(fl_print_t * const print, const f_string_static_t action, const f_string_static_t with); +#endif // _di_control_print_error_parameter_action_rule_with_unknown_ + +/** + * Print an error message about the parameter's associated value being an empty string. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param parameter + * The parameter name. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_value_empty_ + extern f_status_t control_print_error_parameter_value_empty(fl_print_t * const print, const f_string_static_t parameter); +#endif // _di_control_print_error_parameter_value_empty_ + +/** + * Print an error message about the parameter missings its associated value. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param parameter + * The parameter name. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_parameter_value_not_ + extern f_status_t control_print_error_parameter_value_not(fl_print_t * const print, const f_string_static_t parameter); +#endif // _di_control_print_error_parameter_value_not_ + +/** + * Print an error message about a pipe input being unsupported. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_pipe_supported_not_ + extern f_status_t control_print_error_pipe_supported_not(fl_print_t * const print); +#endif // _di_control_print_error_pipe_supported_not_ + +/** + * Print an error message about the response packet format either being invalid or not supported. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_response_packet_valid_not_ + extern f_status_t control_print_error_response_packet_valid_not(fl_print_t * const print); +#endif // _di_control_print_error_response_packet_valid_not_ + +/** + * Print an error message about the request packet being too large. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_request_packet_too_large_ + extern f_status_t control_print_error_request_packet_too_large(fl_print_t * const print); +#endif // _di_control_print_error_request_packet_too_large_ + +/** + * Print an error message about failure to connect to the socket file. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param path_socket + * The socket file path. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_socket_file_failed_ + extern f_status_t control_print_error_socket_file_failed(fl_print_t * const print, const f_string_static_t path_socket); +#endif // _di_control_print_error_socket_file_failed_ + +/** + * Print an error message about the socket file not being found. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param path_socket + * The socket file path. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_socket_file_missing_ + extern f_status_t control_print_error_socket_file_missing(fl_print_t * const print, const f_string_static_t path_socket); +#endif // _di_control_print_error_socket_file_missing_ + +/** + * Print an error message about the socket file not actually being a socket file. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param path_socket + * The socket file path. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_error_socket_file_not_ + extern f_status_t control_print_error_socket_file_not(fl_print_t * const print, const f_string_static_t path_socket); +#endif // _di_control_print_error_socket_file_not_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_print_error_h diff --git a/level_3/control/c/main/print/message.c b/level_3/control/c/main/print/message.c new file mode 100644 index 0000000..2cd0d9a --- /dev/null +++ b/level_3/control/c/main/print/message.c @@ -0,0 +1,82 @@ +#include "../control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_control_print_message_help_ + f_status_t control_print_message_help(fl_print_t * const print) { + + if (!print) return F_status_set_error(F_output_not); + + f_file_stream_lock(print->to); + + fll_program_print_help_header(print, control_program_name_long_s, control_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print->to); + + fll_program_print_help_option(print, control_short_name_s, control_long_name_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Specify the name of the controller socket file."); + fll_program_print_help_option(print, control_short_return_s, control_long_return_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Print a message about the response packet."); + fll_program_print_help_option(print, control_short_settings_s, control_long_settings_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "Specify a directory path or a full path to the control settings file."); + fll_program_print_help_option(print, control_short_socket_s, control_long_socket_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Specify a directory path or a full path to the controller socket file."); + + f_print_dynamic_raw(f_string_eol_s, print->to); + + fll_program_print_help_usage(print, control_program_name_s, control_action_s); + + fl_print_format("%r When the %[%r%r%] parameter represents a directory path then the file name is generated from either the", print->to, f_string_eol_s, print->set->notable, f_console_symbol_long_normal_s, control_long_socket_s, print->set->notable); + fl_print_format(" %[%r%r%] parameter or from the control settings file.%r%r", print->to, print->set->notable, f_console_symbol_long_normal_s, control_long_name_s, print->set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" A rule action allows for either the full rule path, such as '%[boot/root%]'", print->to, print->set->notable, print->set->notable); + fl_print_format(" as a single parameter or two parameters with the first representing the rule directory path '%[boot%]'", print->to, print->set->notable, print->set->notable); + fl_print_format(" and the second representing the rule base name '%[root%]'.%r%r", print->to, print->set->notable, print->set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%] parameter is intended to be used for scripting and is of the form \"response [type] [action] [status]\".%r", print->to, print->set->notable, f_console_symbol_long_normal_s, control_long_return_s, print->set->notable, f_string_eol_s); + fl_print_format(" Be sure to use the %[%r%r%] parameter to suppress output when using this in scripting.%r", print->to, print->set->notable, f_console_symbol_long_inverse_s, f_console_standard_long_quiet_s, print->set->notable, f_string_eol_s); + fl_print_format(" No response is returned on program errors, especially those errors that prevent communicating to the controller.%r", print->to, f_string_eol_s); + + f_file_stream_flush(print->to); + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_message_help_ + +#ifndef _di_control_print_message_packet_response_ + f_status_t control_print_message_packet_response(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status) { + + if (!print || !print->custom) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_normal_e) return F_output_not; + + control_main_t * const main = (control_main_t *) print->custom; + + f_file_stream_lock(print->to); + + fl_print_format("The action '", print->to); + fl_print_format("%[%q%]", print->to, print->set->notable, control_action_type_name(header.action), print->set->notable); + + if (header.status == F_done) { + fl_print_format("' is performed", print->to); + } + else { + fl_print_format("' is successfully performed", print->to); + } + + if (header.length) { + fl_print_format(": %/Q%r", print->to, main->cache.large, main->cache.packet_contents.array[main->cache.packet_contents.used - 1].array[0], f_string_eol_s); + } + else { + fl_print_format(".%r", print->to, f_string_eol_s); + } + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_message_packet_response_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/print/message.h b/level_3/control/c/main/print/message.h new file mode 100644 index 0000000..9cbf157 --- /dev/null +++ b/level_3/control/c/main/print/message.h @@ -0,0 +1,74 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the print functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_print_message_h +#define _control_print_message_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + * + * @see f_file_stream_flush() + * @see f_file_stream_lock() + * @see f_file_stream_unlock() + * @see f_print_dynamic_raw() + * @see fl_print_format() + * + * @see fll_program_print_help_header() + * @see fll_program_print_help_option() + * @see fll_program_print_help_option_standard() + * @see fll_program_print_help_usage() + */ +#ifndef _di_control_print_message_help_ + extern f_status_t control_print_message_help(fl_print_t * const print); +#endif // _di_control_print_message_help_ + +/** + * Print a message about a packet response. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param header + * The control payload packet header data. + * @param status + * A string representing the name of the status code from header.status. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_message_packet_response_ + extern f_status_t control_print_message_packet_response(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status); +#endif // _di_control_print_message_packet_response_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_print_message_h diff --git a/level_3/control/c/main/print/warning.c b/level_3/control/c/main/print/warning.c new file mode 100644 index 0000000..75eb4d7 --- /dev/null +++ b/level_3/control/c/main/print/warning.c @@ -0,0 +1,65 @@ +#include "../control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_control_print_warning_packet_header_duplicate_object_ + f_status_t control_print_warning_packet_header_duplicate_object(fl_print_t * const print, const f_string_static_t response_header) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_verbose_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe received response header '%]", print->to, print->set->warning, print->prefix, print->set->warning); + fl_print_format("%[%Q%]", print->to, print->set->notable, response_header, print->set->notable); + fl_print_format("%[' is repeated.%]%r", print->to, print->set->warning, print->set->warning, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_warning_packet_header_duplicate_object_ + +#ifndef _di_control_print_warning_packet_process_string_to_failed_ + f_status_t control_print_warning_packet_process_string_to_failed(fl_print_t * const print, const f_status_t status_of, const f_status_t status_error) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_verbose_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QFailed while calling f_status_string_to() for status%] ", print->to, print->set->warning, print->set->warning, print->set->warning); + fl_print_format("%[%ui%]", print->to, print->set->notable, status_of, print->set->notable); + fl_print_format("%[, failing with status code%] ", print->to, print->set->warning, status_error, print->set->warning); + fl_print_format("%[%ui%]", print->to, print->set->notable, status_error, print->set->notable); + fl_print_format("%[.%]%r", print->to, print->set->warning, print->set->warning, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_warning_packet_process_string_to_failed_ + +#ifndef _di_control_print_warning_packet_response_busy_ + f_status_t control_print_warning_packet_response_busy(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_verbose_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe action '%]", print->to, print->set->warning, print->prefix, print->set->warning); + fl_print_format("%[%q%]", print->to, print->set->notable, control_action_type_name(header.action), print->set->notable); + fl_print_format("%[' could not be performed because the service is busy.%]%r", print->to, print->set->warning, print->set->warning, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_none; + } +#endif // _di_control_print_warning_packet_response_busy_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/print/warning.h b/level_3/control/c/main/print/warning.h new file mode 100644 index 0000000..847632d --- /dev/null +++ b/level_3/control/c/main/print/warning.h @@ -0,0 +1,92 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the print functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_print_warning_h +#define _control_print_warning_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print a warning message about a response header being repeated (when debugging). + * + * This program currently does not support multiple headers for any given valid header Object. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param response_header + * The repeated response header. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_warning_packet_header_duplicate_object_ + extern f_status_t control_print_warning_packet_header_duplicate_object(fl_print_t * const print, const f_string_static_t response_header); +#endif // _di_control_print_warning_packet_header_duplicate_object_ + +/** + * Print a warning message about a failure when calling f_status_string_to(). + * + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param status_of + * The status code to be translating to a string. + * @param status_error + * The status code representing the failure status returned by f_status_string_to(). + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + * + * @see f_status_string_to() + */ +#ifndef _di_control_print_warning_packet_process_string_to_failed_ + extern f_status_t control_print_warning_packet_process_string_to_failed(fl_print_t * const print, const f_status_t status_of, const f_status_t status_error); +#endif // _di_control_print_warning_packet_process_string_to_failed_ + +/** + * Print a warning about a packet response returning as busy. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param header + * The control payload packet header data. + * @param status + * A string representing the name of the status code from header.status. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + */ +#ifndef _di_control_print_warning_packet_response_busy_ + extern f_status_t control_print_warning_packet_response_busy(fl_print_t * const print, const control_payload_header_t header, const f_string_static_t string_status); +#endif // _di_control_print_warning_packet_response_busy_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_print_warning_h diff --git a/level_3/control/c/main/process.c b/level_3/control/c/main/process.c new file mode 100644 index 0000000..0c95daf --- /dev/null +++ b/level_3/control/c/main/process.c @@ -0,0 +1,9 @@ +#include "control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/process.h b/level_3/control/c/main/process.h new file mode 100644 index 0000000..0eda87d --- /dev/null +++ b/level_3/control/c/main/process.h @@ -0,0 +1,23 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides the process functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_process_h +#define _control_process_h + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_process_h diff --git a/level_3/control/c/main/signal.c b/level_3/control/c/main/signal.c new file mode 100644 index 0000000..2354590 --- /dev/null +++ b/level_3/control/c/main/signal.c @@ -0,0 +1,111 @@ +#include "control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_di_control_signal_check_) && defined(_di_thread_support_) + f_status_t control_signal_check(control_main_t * const main) { + + if (!main || main->program.signal.id == -1) return F_false; + + if (!((++main->program.signal_check) % control_signal_check_d)) { + if (fll_program_standard_signal_received(&main->program)) { + fll_program_print_signal_received(&main->program.warning, main->program.signal_received); + + main->setting.state.status = F_status_set_error(F_interrupt); + + return F_true; + } + + main->program.signal_check = 0; + } + + return F_false; + } +#endif // !defined(_di_control_signal_check_) && defined(_di_thread_support_) + +#if !defined(_di_control_signal_check_) && !defined(_di_thread_support_) + f_status_t control_signal_check(control_main_t * const main) { + + if (!main || main->program.signal.id == -1) return F_false; + + if (main->program.signal_received) { + fll_program_print_signal_received(&main->program.warning, main->program.signal_received); + + main->setting.state.status = F_status_set_error(F_interrupt); + + return F_true; + } + + return F_false; + } +#endif // !defined(_di_control_signal_check_) && !defined(_di_thread_support_) + +#if !defined(_di_control_signal_handler_) && !defined(_di_thread_support_) + void control_signal_handler(control_main_t * const main) { + + if (!main) return; + + siginfo_t information; + f_number_unsigned_t failsafe = 0; + + memset(&information, 0, sizeof(siginfo_t)); + + main->program.signal_received = 0; + + f_signal_set_empty(&main->program.signal.set); + f_signal_set_add(F_signal_abort, &main->program.signal.set); + f_signal_set_add(F_signal_broken_pipe, &main->program.signal.set); + f_signal_set_add(F_signal_hangup, &main->program.signal.set); + f_signal_set_add(F_signal_interrupt, &main->program.signal.set); + f_signal_set_add(F_signal_quit, &main->program.signal.set); + f_signal_set_add(F_signal_termination, &main->program.signal.set); + + if (main->program.signal.id == -1) { + main->setting.status_signal = f_signal_open(&main->program.signal); + + if (F_status_is_error(main->setting.status_signal)) { + main->program.signal_received = F_signal_abort; + + return; + } + } + + do { + memset(&information, 0, sizeof(siginfo_t)); + + main->setting.status_signal = f_signal_wait(&main->program.signal.set, &information); + + if (F_status_is_error(main->setting.status_signal) && F_status_set_fine(main->setting.status_signal) != F_interrupt) { + if (++failsafe >= control_signal_check_failsafe_d) break; + } + + switch (information.si_signo) { + case F_signal_abort: + case F_signal_broken_pipe: + case F_signal_hangup: + case F_signal_interrupt: + case F_signal_quit: + case F_signal_termination: + main->program.signal_received = information.si_signo; + + break; + } + + failsafe = 0; + main->setting.status_signal = F_none; + + } while (!main->program.signal_received); + + f_signal_close(&main->program.signal); + + if (F_status_is_error(main->setting.status_signal)) { + main->program.signal_received = F_signal_abort; + } + } +#endif // !defined(_di_control_signal_handler_) && !defined(_di_thread_support_) + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/signal.h b/level_3/control/c/main/signal.h new file mode 100644 index 0000000..981706f --- /dev/null +++ b/level_3/control/c/main/signal.h @@ -0,0 +1,86 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides signal functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_signal_h +#define _control_signal_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Check to see if a signal is received. + * + * If main.signal is non-zero, then this handles the following signals: + * - F_signal_abort + * - F_signal_broken_pipe + * - F_signal_hangup + * - F_signal_interrupt + * - F_signal_quit + * - F_signal_termination + * + * There is a threaded and a non-threaded version of this. + * The non-threaded version checks periodically using control_signal_check_d and updates main->signal_check as needed. + * The threaded version checks the flag state which is set by a separate thread that is blocking until signal is received. + * + * @param main + * The main program and settings data. + * + * This does not alter main.setting.state.status. + * + * @return + * F_true on signal received. + * F_false otherwise. + * + * @see control_signal_handler() + * + * @see fll_program_standard_signal_received() + */ +#ifndef _di_control_signal_check_ + extern f_status_t control_signal_check(control_main_t * const main); +#endif // _di_control_signal_check_ + +/** + * Signal handler for signals/interrupts. + * + * This blocks until an expected signal is recieved. + * When an expected signal is received it then sets the + * + * If main.signal is non-zero, then this handles the following signals: + * - F_signal_abort + * - F_signal_broken_pipe + * - F_signal_hangup + * - F_signal_interrupt + * - F_signal_quit + * - F_signal_termination + * + * @param main + * The main program and settings data. + * + * This alters main.program.signal_received, setting it to a received signal. + * + * This alters main.setting.state.status: + * Errors (with error bit) from: f_signal_open() + * Errors (with error bit) from: f_signal_wait() + * + * @see f_signal_close() + * @see f_signal_open() + * @see f_signal_wait() + */ +#if !defined(_di_control_signal_handler_) && !defined(_di_thread_support_) + extern void control_signal_handler(control_main_t * const main); +#endif // !defined(_di_control_signal_handler_) && !defined(_di_thread_support_) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_signal_h diff --git a/level_3/control/c/main/thread.c b/level_3/control/c/main/thread.c new file mode 100644 index 0000000..b859f7a --- /dev/null +++ b/level_3/control/c/main/thread.c @@ -0,0 +1,26 @@ +#include "control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_di_control_thread_signal_) && !defined(_di_thread_support_) + void * control_thread_signal(void * const main) { + + f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0); + + if (main) { + control_signal_handler((control_main_t *) main); + } + + return 0; + } +#endif // !defined(_di_control_thread_signal_) && !defined(_di_thread_support_) + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/main/thread.h b/level_3/control/c/main/thread.h new file mode 100644 index 0000000..22212e7 --- /dev/null +++ b/level_3/control/c/main/thread.h @@ -0,0 +1,46 @@ +/** + * FLL - Level 3 + * + * Project: Control + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides thread functionality. + * + * This is auto-included and should not need to be explicitly included. + */ +#ifndef _control_thread_h +#define _control_thread_h + +/** + * Thread handler for signals/interrupts. + * + * If main.signal is non-zero, then this handles the following signals: + * - F_signal_abort + * - F_signal_broken_pipe + * - F_signal_hangup + * - F_signal_interrupt + * - F_signal_quit + * - F_signal_termination + * + * @param main + * The program and settings data. + * + * Must be of type control_main_t. + * + * @return + * 0, always. + * + * @see f_thread_cancel_state_set() + * + * @see control_signal_handler() + */ +#if !defined(_di_control_thread_signal_) && !defined(_di_thread_support_) + extern void * control_thread_signal(void * const main); +#endif // !defined(_di_control_thread_signal_) && !defined(_di_thread_support_) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_thread_h diff --git a/level_3/control/c/print.c b/level_3/control/c/print.c deleted file mode 100644 index 04031ad..0000000 --- a/level_3/control/c/print.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "control.h" -#include "private-common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _di_control_print_help_ - f_status_t control_print_help(control_setting_t * const setting, const fl_print_t print) { - - f_file_stream_lock(print.to); - - fll_program_print_help_header(print, control_program_name_long_s, control_program_version_s); - - fll_program_print_help_option_standard(main->output.to, context); - - f_print_dynamic_raw(f_string_eol_s, main->output.to); - - fll_program_print_help_option(print, control_short_name_s, control_long_name_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Specify the name of the controller socket file."); - fll_program_print_help_option(print, control_short_return_s, control_long_return_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Print a message about the response packet."); - fll_program_print_help_option(print, control_short_settings_s, control_long_settings_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "Specify a directory path or a full path to the control settings file."); - fll_program_print_help_option(print, control_short_socket_s, control_long_socket_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Specify a directory path or a full path to the controller socket file."); - - f_print_dynamic_raw(f_string_eol_s, print.to); - f_print_dynamic_raw(f_string_eol_s, print.to); - - fll_program_print_help_usage(print, control_program_name_s, control_action_s); - - fl_print_format("%r When the %[%r%r%] parameter represents a directory path then the file name is generated from either the", print.to, f_string_eol_s, print.set->notable, f_console_symbol_long_normal_s, control_long_socket_s, print.set->notable); - fl_print_format(" %[%r%r%] parameter or from the control settings file.%r%r", print.to, print.set->notable, f_console_symbol_long_normal_s, control_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" A rule action allows for either the full rule path, such as '%[boot/root%]'", print.to, print.set->notable, print.set->notable); - fl_print_format(" as a single parameter or two parameters with the first representing the rule directory path '%[boot%]'", print.to, print.set->notable, print.set->notable); - fl_print_format(" and the second representing the rule base name '%[root%]'.%r%r", print.to, print.set->notable, print.set->notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%] parameter is intended to be used for scripting and is of the form \"response [type] [action] [status]\".%r", print.to, print.set->notable, f_console_symbol_long_normal_s, control_long_return_s, print.set->notable, f_string_eol_s); - fl_print_format(" Be sure to use the %[%r%r%] parameter to suppress output when using this in scripting.%r", print.to, print.set->notable, f_console_symbol_long_inverse_s, f_console_standard_long_quiet_s, print.set->notable, f_string_eol_s); - fl_print_format(" No response is returned on program errors, especially those errors that prevent communicating to the controller.%r", print.to, f_string_eol_s); - - f_file_stream_flush(print.to); - f_file_stream_unlock(print.to); - - return F_none; - } -#endif // _di_control_print_help_ - -#ifdef __cplusplus -} // extern "C" -#endif diff --git a/level_3/control/c/print.h b/level_3/control/c/print.h deleted file mode 100644 index e46b5a4..0000000 --- a/level_3/control/c/print.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * FLL - Level 3 - * - * Project: Control - * API Version: 0.7 - * Licenses: lgpl-2.1-or-later - */ -#ifndef _control_print_h -#define _control_print_h - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Print help. - * - * @param setting - * The main program settings. - * - * This does not alter setting.state.status. - * @param print - * The output structure to print to. - * - * @return - * F_none on success. - * F_output_not on success, but no printing is performed. - */ -#ifndef _di_control_print_help_ - extern f_status_t control_print_help(control_setting_t * const setting, const fl_print_t print); -#endif // _di_control_print_help_control - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // _control_print_h diff --git a/level_3/control/c/private-control.c b/level_3/control/c/private-control.c deleted file mode 100644 index 43868e3..0000000 --- a/level_3/control/c/private-control.c +++ /dev/null @@ -1,874 +0,0 @@ -#include "control.h" -#include "private-common.h" -#include "private-control.h" -#include "private-print.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _di_control_action_verify_ - f_status_t control_action_verify(const fll_program_data_t * const main, control_data_t * const data) { - - switch (data->action) { - case control_action_type_freeze_e: - case control_action_type_kill_e: - case control_action_type_pause_e: - case control_action_type_reload_e: - case control_action_type_rerun_e: - case control_action_type_restart_e: - case control_action_type_resume_e: - case control_action_type_start_e: - case control_action_type_stop_e: - case control_action_type_thaw_e: - if (main->parameters.remaining.used < 3) { - control_print_error_parameter_action_rule_not(main, data->argv[main->parameters.remaining.array[0]]); - - return F_status_set_error(F_parameter); - } - - if (main->parameters.remaining.used > 3) { - if (f_compare_dynamic(control_at_s, data->argv[main->parameters.remaining.array[3]]) == F_equal_to) { - if (main->parameters.remaining.used < 5) { - control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s); - - return F_status_set_error(F_parameter); - } - - if (main->parameters.remaining.used > 5) { - control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s); - - return F_status_set_error(F_parameter); - } - } - else if (f_compare_dynamic(control_in_s, data->argv[main->parameters.remaining.array[3]]) == F_equal_to) { - if (main->parameters.remaining.used < 6) { - control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_in_s); - - return F_status_set_error(F_parameter); - } - } - else if (f_compare_dynamic(control_now_s, data->argv[main->parameters.remaining.array[3]]) == F_equal_to) { - if (main->parameters.remaining.used > 4) { - control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_now_s); - - return F_status_set_error(F_parameter); - } - } - else { - control_print_error_parameter_action_rule_with_unknown(main, data->argv[main->parameters.remaining.array[0]], data->argv[main->parameters.remaining.array[2]]); - - return F_status_set_error(F_parameter); - } - } - - if (!data->argv[main->parameters.remaining.array[1]].used) { - if (main->parameters.remaining.used == 3) { - control_print_error_parameter_action_rule_empty(main, data->argv[main->parameters.remaining.array[0]]); - } - else { - control_print_error_parameter_action_rule_directory_empty(main, data->argv[main->parameters.remaining.array[0]]); - } - - return F_status_set_error(F_parameter); - } - - if (main->parameters.remaining.used == 3) { - if (!data->argv[main->parameters.remaining.array[2]].used) { - control_print_error_parameter_action_rule_basename_empty(main, data->argv[main->parameters.remaining.array[0]]); - - return F_status_set_error(F_parameter); - } - } - - return F_none; - - case control_action_type_kexec_e: - case control_action_type_reboot_e: - case control_action_type_shutdown_e: - if (main->parameters.remaining.used < 2) { - control_print_error_parameter_action_rule_too_few(main, data->argv[main->parameters.remaining.array[0]]); - - return F_status_set_error(F_parameter); - } - - if (f_compare_dynamic(control_at_s, data->argv[main->parameters.remaining.array[1]]) == F_equal_to) { - if (main->parameters.remaining.used < 3) { - control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s); - - return F_status_set_error(F_parameter); - } - - if (main->parameters.remaining.used > 3) { - control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s); - - return F_status_set_error(F_parameter); - } - } - else if (f_compare_dynamic(control_in_s, data->argv[main->parameters.remaining.array[1]]) == F_equal_to) { - if (main->parameters.remaining.used < 4) { - control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_in_s); - - return F_status_set_error(F_parameter); - } - } - else if (f_compare_dynamic(control_now_s, data->argv[main->parameters.remaining.array[1]]) == F_equal_to) { - if (main->parameters.remaining.used > 2) { - control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_now_s); - - return F_status_set_error(F_parameter); - } - } - else { - control_print_error_parameter_action_rule_with_unknown(main, data->argv[main->parameters.remaining.array[0]], data->argv[main->parameters.remaining.array[1]]); - - return F_status_set_error(F_parameter); - } - } - - return F_none; - } -#endif // _di_control_action_verify_ - -#ifndef _di_control_packet_build_ - f_status_t control_packet_build(const fll_program_data_t * const main, control_data_t * const data) { - - data->cache.packet.used = 0; - data->cache.large.used = 0; - data->cache.small.used = 0; - - f_number_unsigned_t i = 0; - f_status_t status = F_none; - - { - f_number_unsigned_t length = 5 + f_fss_header_s.used + f_fss_payload_s.used; - length += control_action_s.used + control_length_s.used + control_type_s.used; - length += (f_fss_payload_list_open_s.used + f_fss_payload_list_close_s.used) * 2; - length += (f_fss_payload_header_open_s.used + f_fss_payload_header_close_s.used) * 3; - length += data->argv[main->parameters.remaining.array[0]].used + f_string_ascii_0_s.used; - - // @todo This should properly handle escaping the FSS-0001 (Extended) Content and then count that length. - for (i = 1; i < main->parameters.remaining.used; ++i) { - length += f_fss_payload_header_next_s.used + data->argv[main->parameters.remaining.array[i]].used; - } // for - - if (data->action == control_action_type_kexec_e || data->action == control_action_type_reboot_e || data->action == control_action_type_shutdown_e) { - length += control_init_s.used; - } - else { - length += control_controller_s.used; - } - - if (length > 0xffffffffu) { - return F_status_set_error(F_too_large); - } - - status = f_string_dynamic_resize(length, &data->cache.packet); - if (F_status_is_error(status)) return status; - } - - const f_state_t state = macro_f_state_t_initialize_1(control_allocation_large_d, control_allocation_small_d, F_none, 0, 0, 0, &fll_program_standard_signal_handle, 0, (void *) main, 0); - - f_string_static_t contents_array[main->parameters.remaining.used]; - f_string_statics_t contents = macro_f_string_statics_t_initialize_1(contents_array, 0, main->parameters.remaining.used); - - // The Packet Control Block. - { - f_char_t block_control = (f_char_t) control_packet_flag_binary_d; - - #ifdef _is_F_endian_big - block_control |= (f_char_t) control_packet_flag_endian_big_d; - #endif // _is_F_endian_big - - status = f_string_append(&block_control, 1, &data->cache.packet); - if (F_status_is_error(status)) return status; - } - - // Reserve the Packet Size Block to be calculated later. - data->cache.packet.used = 5; - - // Payload Header: type. - if (data->action == control_action_type_kexec_e || data->action == control_action_type_reboot_e || data->action == control_action_type_shutdown_e) { - contents_array[0] = control_init_s; - } - else { - contents_array[0] = control_controller_s; - } - - contents.used = 1; - - status = fll_fss_extended_write(control_type_s, contents, 0, state, &data->cache.large); - if (F_status_is_error(status)) return status; - - // Payload Header: action. - for (contents.used = 0; contents.used < main->parameters.remaining.used; ++contents.used) { - contents_array[contents.used] = data->argv[main->parameters.remaining.array[contents.used]]; - } // for - - status = fll_fss_extended_write(control_action_s, contents, 0, state, &data->cache.large); - if (F_status_is_error(status)) return status; - - // Payload Header: length. - contents_array[0] = f_string_ascii_0_s; - contents.used = 1; - - status = fll_fss_extended_write(control_length_s, contents, 0, state, &data->cache.large); - if (F_status_is_error(status)) return status; - - // Payload Packet: Header. - status = fll_fss_payload_write(f_fss_header_s, data->cache.large, F_false, 0, state, &data->cache.packet); - if (F_status_is_error(status)) return status; - - // Payload Packet: Payload. - data->cache.large.used = 0; - - status = fll_fss_payload_write(f_fss_payload_s, data->cache.large, F_false, 0, state, &data->cache.packet); - if (F_status_is_error(status)) return status; - - // Construct Packet Size Block. - #ifdef _is_F_endian_big - data->cache.packet.string[1] = data->cache.packet.used & 0xffu; - data->cache.packet.string[2] = data->cache.packet.used & 0xff00u; - data->cache.packet.string[3] = data->cache.packet.used & 0xff0000u; - data->cache.packet.string[4] = data->cache.packet.used & 0xff000000u; - #else - data->cache.packet.string[1] = data->cache.packet.used & 0xff000000u; - data->cache.packet.string[2] = data->cache.packet.used & 0xff0000u; - data->cache.packet.string[3] = data->cache.packet.used & 0xff00u; - data->cache.packet.string[4] = data->cache.packet.used & 0xffu; - #endif // _is_F_endian_big - - return F_none; - } -#endif // _di_control_packet_build_ - -#ifndef _di_control_packet_header_flag_ - uint8_t control_packet_header_flag(const uint8_t buffer[]) { - return (uint8_t) (((buffer[0] & 0x8u) ? control_packet_flag_binary_d : 0) | ((buffer[0] & 0x4u) ? control_packet_flag_endian_big_d : 0)); - } -#endif // _di_control_packet_header_flag_ - -#ifndef _di_control_packet_header_length_ - uint32_t control_packet_header_length(const bool is_big, const uint8_t buffer[]) { - - #ifdef _is_F_endian_big - if (is_big) { - return (buffer[1] << 24u) | (buffer[2] << 16u) | (buffer[3] << 8u) | buffer[4]; - } - #else - if (!is_big) { - return (buffer[1] << 24u) | (buffer[2] << 16u) | (buffer[3] << 8u) | buffer[4]; - } - #endif // _is_F_endian_big - - return (buffer[4] << 24u) | (buffer[3] << 16u) | (buffer[2] << 8u) | buffer[1]; - } -#endif // _di_control_packet_header_length_ - -#ifndef _di_control_packet_receive_ - f_status_t control_packet_receive(const fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) { - - data->cache.large.used = 0; - data->cache.small.used = 0; - data->cache.packet.used = 0; - data->cache.packet_objects.used = 0; - data->cache.packet_contents.used = 0; - data->cache.header_objects.used = 0; - data->cache.header_contents.used = 0; - data->cache.delimits.used = 0; - - header->action = 0; - header->type = 0; - header->status = F_none; - header->length = 0; - - f_status_t status = F_none; - f_number_unsigned_t i = 0; - f_string_range_t range_header = f_string_range_t_initialize; - f_string_range_t range_payload = f_string_range_t_initialize; - - { - f_number_unsigned_t length = 5; - uint8_t head[length]; - - memset(head, 0, sizeof(uint8_t) * length); - - status = f_socket_read(&data->socket, f_socket_flag_peek_e, (void *) head, &length); - if (F_status_is_error(status)) return status; - if (length < 5) return F_status_set_error(F_packet_not); - - // Only the first two bits of the 8 Control bits are allowed to be set to 1 for this Packet. - if (head[0] & (~(control_packet_flag_binary_d | control_packet_flag_endian_big_d))) { - return F_status_set_error(F_packet_not); - } - - length = control_packet_header_length(head[0] & control_packet_flag_endian_big_d, head); - - if (length > 0xffffffffu) { - return F_status_set_error(F_too_large); - } - - status = f_string_dynamic_increase_by(length, &data->cache.large); - if (F_status_is_error(status)) return status; - - status = f_socket_read(&data->socket, f_socket_flag_wait_all_e, (void *) head, &length); - if (F_status_is_error(status)) return status; - if (length < data->cache.large.used) return F_status_set_error(F_too_small); - if (length > data->cache.large.used) return F_status_set_error(F_too_large); - } - - { - f_state_t state = macro_f_state_t_initialize_1(control_allocation_large_d, control_allocation_small_d, F_none, 0, 0, 0, &fll_program_standard_signal_handle, 0, (void *) main, 0); - f_string_range_t range_packet = macro_f_string_range_t_initialize_2(data->cache.large.used); - - status = fll_fss_basic_list_read(data->cache.large, state, &range_packet, &data->cache.packet_objects, &data->cache.packet_contents, &data->cache.delimits, 0, 0); - - if (F_status_is_error(status)) { - control_print_debug_packet_message(main, "Failure while reading FSS Basic List in the response packet", 0, 0, &status); - - if (F_status_set_fine(status) == F_memory_not) { - return status; - } - - return F_status_set_error(F_header); - } - - status = f_fss_apply_delimit(state, data->cache.delimits, &data->cache.large); - - if (F_status_is_error(status)) { - control_print_debug_packet_message(main, "Failure while processing delimits for the FSS Basic List in the response packet", 0, 0, &status); - - return F_status_set_error(F_header); - } - - data->cache.delimits.used = 0; - - { - f_string_ranges_t *content_header = 0; - f_string_ranges_t *content_payload = 0; - - for (; i < data->cache.packet_objects.used; ++i) { - - if (f_compare_dynamic_partial_string(f_fss_header_s.string, data->cache.large, f_fss_header_s.used, data->cache.packet_objects.array[i]) == F_equal_to) { - - // The FSS-000E (Payload) standard does not prohibit multiple "header", but such cases are not supported by the controller and the control programs. - if (content_header) { - control_print_debug_packet_message(main, "Multiple %[" F_fss_header_s "%] found in response packet", 0, 0, 0); - - return F_status_set_error(F_payload_not); - } - - content_header = &data->cache.packet_contents.array[i]; - } - else if (f_compare_dynamic_partial_string(f_fss_payload_s.string, data->cache.large, f_fss_payload_s.used, data->cache.packet_objects.array[i]) == F_equal_to) { - - // Only a single "payload" is supported by the FSS-000E (Payload) standard. - if (content_payload) { - control_print_debug_packet_message(main, "Multiple %[" F_fss_payload_s "%] found in response packet", 0, 0, 0); - - return F_status_set_error(F_payload_not); - } - - if (i + 1 < data->cache.packet_contents.used) { - control_print_debug_packet_message(main, "Invalid FSS Payload format, the %[" F_fss_payload_s "%] is required to be the last FSS Basic List Object", 0, 0, 0); - - return F_status_set_error(F_payload_not); - } - - content_payload = &data->cache.packet_contents.array[i]; - } - } // for - - if (!content_header) { - control_print_debug_packet_message(main, "Did not find a %[" F_fss_header_s "%] in the response packet", 0, 0, 0); - - return F_status_set_error(F_payload_not); - } - - if (!content_payload) { - control_print_debug_packet_message(main, "Did not find a %[" F_fss_payload_s "%] in the response packet", 0, 0, 0); - - return F_status_set_error(F_payload_not); - } - - range_header = content_header->array[0]; - range_payload = content_payload->array[0]; - } - - { - // 0x1 = found action, 0x2 = found length, 0x4 = found status, 0x8 = found_type. - uint8_t found = 0; - f_number_unsigned_t number = 0; - f_string_range_t range = range_header; - - status = fll_fss_extended_read(data->cache.large, state, &range, &data->cache.header_objects, &data->cache.header_contents, 0, 0, &data->cache.delimits, 0); - - if (F_status_is_error(status)) { - control_print_debug_packet_message(main, "Failure while reading FSS Extended in the response packet", 0, 0, &status); - - if (F_status_set_fine(status) == F_memory_not) { - return status; - } - - return F_status_set_error(F_header_not); - } - - status = f_fss_apply_delimit(state, data->cache.delimits, &data->cache.large); - - if (F_status_is_error(status)) { - control_print_debug_packet_message(main, "Failure while processing delimits for the FSS Basic List in the response packet", 0, 0, &status); - - return F_status_set_error(F_header_not); - } - - if (!data->cache.header_contents.used) { - control_print_debug_packet_message(main, "Did not find any Content within the %[" F_fss_header_s "%]", 0, 0, 0); - - return F_status_set_error(F_header_not); - } - - for (i = 0; i < data->cache.header_objects.used; ++i) { - - if (f_compare_dynamic_partial_string(control_action_s.string, data->cache.large, control_action_s.used, data->cache.header_objects.array[i]) == F_equal_to) { - if (!(found & 0x1)) { - const f_number_unsigned_t action_length = (data->cache.header_contents.array[i].array[0].stop - data->cache.header_contents.array[i].array[0].start) + 1; - char action_string[action_length + 1]; - const f_string_static_t action = macro_f_string_static_t_initialize_1(action_string, 0, action_length); - - memcpy(action_string, data->cache.large.string + data->cache.header_contents.array[i].array[0].start, action_length); - action_string[action_length] = 0; - - found |= 0x1; - - control_print_debug_packet_header_object_and_content(main, control_action_s, data->cache.large, data->cache.header_contents.array[i].array[0]); - - header->action = control_action_type_identify(action); - - if (!header->action) { - control_print_debug_packet_message(main, "Failed to identify %[" CONTROL_action_s "%] from: ", &data->cache.large, &data->cache.header_contents.array[i].array[0], 0); - - return F_status_set_error(F_header_not); - } - } - else { - control_print_warning_packet_header_duplicate_object(main, control_action_s); - } - } - else if (f_compare_dynamic_partial_string(control_length_s.string, data->cache.large, control_length_s.used, data->cache.header_objects.array[i]) == F_equal_to) { - if (!(found & 0x2)) { - found |= 0x2; - number = 0; - - control_print_debug_packet_header_object_and_content(main, control_length_s, data->cache.large, data->cache.header_contents.array[i].array[0]); - - status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, data->cache.large, data->cache.header_contents.array[i].array[0], &number); - - if (F_status_is_error(status)) { - control_print_debug_packet_message(main, "Failed to process number for %[" CONTROL_length_s "%] in the response packet, number is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], &status); - - return F_status_set_error(F_header_not); - } - - if (number > F_type_size_max_32_unsigned_d) { - control_print_debug_packet_message(main, "Processed number for %[" CONTROL_length_s "%] exceeds allowed size in the response packet, number is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], &status); - - return F_status_set_error(F_header_not); - } - - header->length = (uint16_t) number; - } - else { - control_print_warning_packet_header_duplicate_object(main, control_length_s); - } - } - else if (f_compare_dynamic_partial_string(control_status_s.string, data->cache.large, control_status_s.used, data->cache.header_objects.array[i]) == F_equal_to) { - if (!(found & 0x4)) { - found |= 0x4; - number = 0; - - control_print_debug_packet_header_object_and_content(main, control_status_s, data->cache.large, data->cache.header_contents.array[i].array[0]); - - // Attempt to get status as a number. - status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, data->cache.large, data->cache.header_contents.array[i].array[0], &number); - - if (F_status_set_fine(status) == F_number) { - - // Not a number, so attempt get by status string name. - const f_number_unsigned_t name_length = (data->cache.header_contents.array[i].array[0].stop - data->cache.header_contents.array[i].array[0].start) + 1; - char name_string[name_length + 1]; - const f_string_static_t name = macro_f_string_static_t_initialize_1(name_string, 0, name_length); - - memcpy(name_string, data->cache.large.string + data->cache.header_contents.array[i].array[0].start, name_length); - name_string[name_length] = 0; - - status = fl_status_string_from(name, &header->status); - - if (F_status_is_error(status)) { - control_print_debug_packet_message(main, "Failed to process %[" CONTROL_status_s "%] in the response packet, Content is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], &status); - - return F_status_set_error(F_header_not); - } - } - else if (F_status_is_error(status)) { - control_print_debug_packet_message(main, "Failed to process number for %[" CONTROL_status_s "%] in the response packet, number is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], &status); - - if (F_status_set_fine(status) == F_memory_not) { - return status; - } - - return F_status_set_error(F_header_not); - } - else { - if (number > F_status_size_max_with_bits_d) { - control_print_debug_packet_message(main, "Processed number for %[" CONTROL_status_s "%] exceeds allowed size in the response packet, number is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], 0); - - return F_status_set_error(F_header_not); - } - } - } - else { - control_print_warning_packet_header_duplicate_object(main, control_length_s); - } - } - else if (f_compare_dynamic_partial_string(control_type_s.string, data->cache.large, control_type_s.used, data->cache.header_objects.array[i]) == F_equal_to) { - if (!(found & 0x8)) { - found |= 0x8; - - control_print_debug_packet_header_object_and_content(main, control_type_s, data->cache.large, data->cache.header_contents.array[i].array[0]); - - if (f_compare_dynamic_partial_string(control_controller_s.string, data->cache.large, control_controller_s.used, data->cache.header_contents.array[i].array[0]) == F_equal_to) { - header->type = control_payload_type_controller_e; - } - else if (f_compare_dynamic_partial_string(control_error_s.string, data->cache.large, control_error_s.used, data->cache.header_contents.array[i].array[0]) == F_equal_to) { - header->type = control_payload_type_error_e; - } - else { - control_print_debug_packet_message(main, "Unknown %[" CONTROL_type_s "%] in response packet, Content is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], 0); - - return F_status_set_error(F_header_not); - } - } - else { - control_print_warning_packet_header_duplicate_object(main, control_type_s); - } - } - } - } - } - - return F_none; - } -#endif // _di_control_packet_receive_ - -#ifndef _di_control_packet_process_ - f_status_t control_packet_process(const fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) { - - f_string_static_t string_status = f_string_static_t_initialize; - - { - const f_status_t status = f_status_string_to(header->status, &string_status); - - if (F_status_is_error(status)) { - control_print_warning_packet_process_string_to_failed(main, header->status, status); - } - } - - if (main->parameters.array[control_parameter_return_e].result & f_console_result_found_e) { - fll_print_format("%rresponse %q %q %q%r", main->output.to, f_string_eol_s, control_payload_type_name(header->type), control_action_type_name(header->action), string_status, f_string_eol_s); - } - else if (header->type == control_payload_type_error_e) { - control_print_error_packet_response(main, data, *header, string_status); - } - else if (header->status == F_failure || header->status == F_busy || header->status == F_done || header->status == F_success) { - control_print_controller_packet_response(main, data, *header, string_status); - } - else { - - // Set type to 0 to inform the caller to handle this error. - header->type = 0; - - return F_status_set_error(F_known_not); - } - - if (header->type == control_payload_type_error_e || header->status == F_failure || header->status == F_busy) { - return F_status_set_error(header->status); - } - - return header->status; - } -#endif // _di_control_packet_process_ - -#ifndef _di_control_packet_send_ - f_status_t control_packet_send(const fll_program_data_t * const main, control_data_t * const data) { - - data->socket.size_write = data->cache.packet.used; - - return f_socket_write(&data->socket, 0, (void *) &data->cache.packet, 0); - } -#endif // _di_control_packet_send_ - -#ifndef _di_control_settings_load_ - f_status_t control_settings_load(const fll_program_data_t * const main, control_data_t * const data) { - - f_status_t status = F_none; - - data->cache.small.used = 0; - - if (main->parameters.array[control_parameter_settings_e].result & f_console_result_value_e) { - const f_number_unsigned_t index = main->parameters.array[control_parameter_settings_e].values.array[main->parameters.array[control_parameter_settings_e].values.used - 1]; - - status = f_string_dynamic_append(data->argv[index], &data->cache.small); - } - else { - status = f_string_dynamic_append(control_path_settings_s, &data->cache.small); - } - - if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_append", fll_error_file_flag_fallback_e); - - return status; - } - - { - f_file_t file = f_file_t_initialize; - - status = f_file_stream_open(data->cache.small, f_file_open_mode_read_s, &file); - - if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", fll_error_file_flag_fallback_e, data->cache.small, f_file_operation_open_s, fll_error_file_type_file_e); - - return status; - } - - status = f_file_stream_read(file, &data->cache.large); - - f_file_stream_flush(file); - f_file_stream_close(&file); - - if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_read", fll_error_file_flag_fallback_e, data->cache.small, f_file_operation_read_s, fll_error_file_type_file_e); - - return status; - } - } - - f_state_t state = f_state_t_initialize; - f_string_range_t range = f_string_range_t_initialize; - f_string_ranges_t objects = f_string_ranges_t_initialize; - f_string_rangess_t contents = f_string_rangess_t_initialize; - f_number_unsigneds_t delimits = f_number_unsigneds_t_initialize; - - status = fll_fss_extended_read(data->cache.large, state, &range, &objects, &contents, 0, 0, &delimits, 0); - - if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "fll_fss_extended_read", fll_error_file_flag_fallback_e, data->cache.small, f_file_operation_process_s, fll_error_file_type_file_e); - } - else { - status = f_fss_apply_delimit(state, delimits, &data->cache.large); - - if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_fss_apply_delimit", fll_error_file_flag_fallback_e, data->cache.small, f_file_operation_process_s, fll_error_file_type_file_e); - } - } - - if (F_status_is_error_not(status)) { - uint8_t parameter_hass[] = { 0, 0, 0, 0 }; - - f_number_unsigned_t parameter_ats[] = { 0, 0, 0, 0 }; - - { - const f_string_static_t parameter_names[] = { - control_name_socket_s, - control_path_socket_s, - control_path_socket_prefix_s, - control_path_socket_suffix_s, - }; - - f_number_unsigned_t i = 0; - uint8_t j = 0; - f_string_range_t range = f_string_range_t_initialize; - - for (; i < objects.used; ++i) { - - for (j = 0; j < 4; ++j) { - - range.stop = parameter_names[j].used - 1; - - if (f_compare_dynamic_partial(parameter_names[j], data->cache.large, range, objects.array[i]) == F_equal_to) { - parameter_hass[j] = F_true; - parameter_ats[j] = i; - - break; - } - } // for - } // for - } - - data->cache.small.used = 0; - - if (main->parameters.array[control_parameter_socket_e].result & f_console_result_value_e) { - const f_number_unsigned_t index = main->parameters.array[control_parameter_socket_e].values.array[main->parameters.array[control_parameter_socket_e].values.used - 1]; - - status = f_string_dynamic_append(data->argv[index], &data->cache.small); - } - else if (parameter_hass[1]) { - status = f_string_dynamic_partial_append_nulless(data->cache.large, objects.array[parameter_ats[1]], &data->cache.small); - } - else { - status = f_string_dynamic_append(controller_path_socket_s, &data->cache.small); - } - - if (F_status_is_error(status)) { - if (main->parameters.array[control_parameter_socket_e].result & f_console_result_value_e || !parameter_hass[1]) { - fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_append", fll_error_file_flag_fallback_e); - } - else { - fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", fll_error_file_flag_fallback_e); - } - } - - status = f_file_exists(data->cache.small, F_true); - - if (F_status_is_error(status) || status == F_false) { - if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_exists", fll_error_file_flag_fallback_e, data->cache.small, f_file_operation_find_s, fll_error_file_type_directory_e); - - if (main->error.verbosity > f_console_verbosity_quiet_e) { - fll_print_dynamic_raw(f_string_eol_s, main->error.to); - } - } - - control_print_error_socket_file_missing(main, data->cache.small); - - status = F_status_set_error(F_socket_not); - } - - // Construct the file name when the socket path is a directory. - else if (f_file_is(data->cache.small, F_file_type_directory_d, F_true) == F_true) { - status = f_string_dynamic_append_assure(f_path_separator_s, &data->cache.small); - - if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_append_assure", fll_error_file_flag_fallback_e); - } - else { - uint8_t append_ids[] = { - 0, - control_parameter_name_e, - 0, - }; - - uint8_t append_hass[] = { - parameter_hass[2], - parameter_hass[0], - parameter_hass[3], - }; - - const f_string_static_t append_defaults[] = { - controller_path_socket_prefix_s, - controller_name_socket_s, - controller_path_socket_suffix_s, - }; - - for (uint8_t i = 0; i < 3; ++i) { - - if (append_ids[i] && main->parameters.array[append_ids[i]].result & f_console_result_value_e) { - const f_number_unsigned_t index = main->parameters.array[append_ids[i]].values.array[main->parameters.array[append_ids[i]].values.used - 1]; - - status = f_string_dynamic_append(data->argv[index], &data->cache.small); - } - else if (append_hass[i]) { - status = f_string_dynamic_partial_append_nulless(data->cache.large, objects.array[append_hass[i]], &data->cache.small); - } - else { - status = f_string_dynamic_append_nulless(append_defaults[i], &data->cache.small); - } - - if (F_status_is_error(status)) { - if ((append_ids[i] && main->parameters.array[append_ids[i]].result & f_console_result_value_e) || !append_hass[i]) { - fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_append", fll_error_file_flag_fallback_e); - } - else { - fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", fll_error_file_flag_fallback_e); - } - - break; - } - } // for - - if (F_status_is_error_not(status)) { - status = f_file_exists(data->cache.small, F_true); - - if (F_status_is_error(status) || status == F_false) { - if (F_status_is_error(status)) { - fll_error_file_print(main->error, F_status_set_fine(status), "f_file_exists", fll_error_file_flag_fallback_e, data->cache.small, f_file_operation_find_s, fll_error_file_type_directory_e); - - if (main->error.verbosity > f_console_verbosity_quiet_e) { - fll_print_dynamic_raw(f_string_eol_s, main->error.to); - } - } - - control_print_error_socket_file_missing(main, data->cache.small); - - status = F_status_set_error(F_socket_not); - } - } - } - } - - if (F_status_is_error_not(status)) { - if (f_file_is(data->cache.small, F_file_type_socket_d, F_true) == F_false) { - control_print_error_socket_file_not(main, data->cache.small); - - status = F_status_set_error(F_socket_not); - } - } - - if (F_status_is_error_not(status)) { - status = f_socket_create(&data->socket); - - if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "f_socket_create", fll_error_file_flag_fallback_e); - - control_print_error_socket_file_failed(main, data->cache.small); - } - } - - if (F_status_is_error_not(status)) { - status = f_socket_connect(data->socket); - - if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "f_socket_connect", fll_error_file_flag_fallback_e); - - control_print_error_socket_file_failed(main, data->cache.small); - } - } - } - - f_string_ranges_resize(0, &objects); - f_string_rangess_resize(0, &contents); - f_number_unsigneds_resize(0, &delimits); - - data->cache.large.used = 0; - data->cache.small.used = 0; - - if (F_status_is_error_not(status)) { - if (data->cache.large.size > control_default_buffer_limit_soft_large_d) { - status = f_string_dynamic_resize(control_default_buffer_limit_soft_large_d, &data->cache.large); - } - - if (F_status_is_error_not(status)) { - if (data->cache.small.size > control_default_buffer_limit_soft_small_d) { - status = f_string_dynamic_resize(control_default_buffer_limit_soft_small_d, &data->cache.small); - } - } - } - - if (F_status_is_error(status)) return status; - - return F_none; - } -#endif // _di_control_settings_load_ - -#ifdef __cplusplus -} // extern "C" -#endif diff --git a/level_3/control/c/private-control.h b/level_3/control/c/private-control.h deleted file mode 100644 index b663dc9..0000000 --- a/level_3/control/c/private-control.h +++ /dev/null @@ -1,222 +0,0 @@ -/** - * FLL - Level 3 - * - * Project: Control - * API Version: 0.7 - * Licenses: lgpl-2.1-or-later - */ -#ifndef _PRIVATE_control_h -#define _PRIVATE_control_h - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Verify that the additional parameters are reasonably correct for the identified action. - * - * @param main - * The main program data. - * @param data - * The control data. - * - * @return - * F_none on success. - * - * F_parameter (with error bit) on parameter validation/verification failure. - */ -#ifndef _di_control_action_verify_ - extern f_status_t control_action_verify(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_control_action_verify_ - -/** - * Build the payload, storing it in the large cache. - * - * @param main - * The main program data. - * @param data - * The control data. - * - * @return - * F_none on success. - * - * F_too_large (with error bit) If the message is too large for the packet format to transmit. - * - * Errors (with error bit) from: f_string_append(). - * Errors (with error bit) from: f_string_dynamic_append(). - * Errors (with error bit) from: f_string_dynamic_resize(). - * Errors (with error bit) from: fll_fss_extended_write(). - * Errors (with error bit) from: fll_fss_payload_write(). - * - * @see f_string_append() - * @see f_string_dynamic_append() - * @see f_string_dynamic_resize() - */ -#ifndef _di_control_packet_build_ - extern f_status_t control_packet_build(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_control_packet_build_ - -/** - * Given the header buffer, get the flag bits. - * - * @param buffer - * The buffer to read the length of and get the - * - * @return - * The 8-bit number representing the flags. - */ -#ifndef _di_control_packet_header_flag_ - extern uint8_t control_packet_header_flag(const uint8_t buffer[]) F_attribute_visibility_internal_d; -#endif // _di_control_packet_header_flag_ - -/** - * Given the header buffer, get the length bits. - * - * The endianness is automatically detected and swapped by this function to guarantee host order bytes. - * - * @param is_big - * If TRUE, then the length in the buffer is in big endian format. - * If FALSE, then the length in the buffer is in little endian format. - * @param buffer - * The buffer to read the length of and get the - * - * @return - * The 32-bit number representing the length. - */ -#ifndef _di_control_packet_header_length_ - extern uint32_t control_packet_header_length(const bool is_big, const uint8_t buffer[]) F_attribute_visibility_internal_d; -#endif // _di_control_packet_header_length_ - -/** - * Receive the response from the remote socket, storing it in the large cache. - * - * @todo consider returning F_header (with error bit) fo most header processing errors rather than individual status codes. - * - * @param main - * The main program data. - * @param data - * The control data. - * @param header - * The control payload packet header data. - * - * @return - * F_none on success. - * - * F_header_not (with error bit) If there is a problem processing the packet header. - * F_memory_not (with error bit) On out of memory issues (this is passed through from called functions). - * F_packet_not (with error bit) If the received packet is not a valid packet or not a supported packet structure. - * F_payload_not (with error bit) If there is a problem processing the packet payload. - * F_too_large (with error bit) If the received packet specifies a size that is too large or the actual size is larger than the specified size. - * F_too_small (with error bit) If the received packet actual size is smaller than the specified size. - * - * Errors (with error bit) from: f_socket_read(). - * Errors (with error bit) from: f_string_dynamic_increase_by(). - * Errors (with error bit) from: fl_conversion_dynamic_partial_to_unsigned_detect(). - * Errors (with error bit) from: fll_fss_extended_read(). - * Errors (with error bit) from: fll_fss_basic_list_read(). - * - * @see f_socket_read() - * @see f_string_dynamic_increase_by() - * @see fl_conversion_dynamic_partial_to_unsigned_detect() - * @see f_fss_apply_delimit() - * @see fl_status_string_from() - * @see fll_fss_extended_read() - * @see fll_fss_basic_list_read() - */ -#ifndef _di_control_packet_receive_ - extern f_status_t control_packet_receive(const fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) F_attribute_visibility_internal_d; -#endif // _di_control_packet_receive_ - -/** - * Process the received and loaded packet. - * - * @param main - * The main program data. - * @param data - * The control data. - * @param header - * The control payload packet header data. - * - * @return - * F_done on success but action has no success or failure states. - * F_success on success. - * - * F_busy (with error bit) - * F_failure (with error bit) on success but controller returned failure for action. - * F_known_not (with error bit) if the Payload type is unknown. - * Any error (with error bit) on failure where the error is defined by the controller service. - */ -#ifndef _di_control_packet_process_ - extern f_status_t control_packet_process(const fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) F_attribute_visibility_internal_d; -#endif // _di_control_packet_process_ - -/** - * Send the payload to the remote socket, getting the payload from the large cache. - * - * @param main - * The main program data. - * @param data - * The control data. - * - * @return - * F_none on success. - * - * Errors (with error bit) from: f_socket_write(). - * - * @see f_socket_write() - */ -#ifndef _di_control_packet_send_ - extern f_status_t control_packet_send(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_control_packet_send_ - -/** - * Load and process the control settings file. - * - * This identifies and attempts to connect to the socket. - * - * @param main - * The main program data. - * @param data - * The control data. - * - * @return - * F_none on success. - * - * F_interrupt (with error bit) on interrupt signal received. - * F_socket_not (with error bit) on socket related error preventing the socket from being created or connected to. - * - * Errors (with error bit) from: f_file_exists(). - * Errors (with error bit) from: f_file_open(). - * Errors (with error bit) from: f_file_stream_read(). - * Errors (with error bit) from: f_socket_connect(). - * Errors (with error bit) from: f_socket_create(). - * Errors (with error bit) from: f_string_append(). - * Errors (with error bit) from: f_string_append_assure(). - * Errors (with error bit) from: f_string_dynamic_append_nulless(). - * Errors (with error bit) from: f_string_dynamic_partial_append_nulless(). - * Errors (with error bit) from: f_string_dynamics_resize(). - * Errors (with error bit) from: f_fss_apply_delimit(). - * Errors (with error bit) from: fll_fss_extended_read(). - * - * @see f_file_exists() - * @see f_file_open() - * @see f_file_stream_read() - * @see f_socket_connect() - * @see f_socket_create() - * @see f_string_append() - * @see f_string_append_assure() - * @see f_string_dynamic_append_nulless() - * @see f_string_dynamic_partial_append_nulless() - * @see f_string_dynamics_resize() - * @see f_fss_apply_delimit() - * @see fll_fss_extended_read() - */ -#ifndef _di_control_settings_load_ - extern f_status_t control_settings_load(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_control_settings_load_ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // _PRIVATE_control_h diff --git a/level_3/control/c/private-print.c b/level_3/control/c/private-print.c deleted file mode 100644 index 474944c..0000000 --- a/level_3/control/c/private-print.c +++ /dev/null @@ -1,444 +0,0 @@ -#include "control.h" -#include "private-common.h" -#include "private-control.h" -#include "private-print.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _di_control_print_controller_packet_response_ - void control_print_controller_packet_response(const fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t string_status) { - - if (header.status == F_failure) { - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe action '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, control_action_type_name(header.action), main->context.set.notable); - fl_print_format("%[' failed with status '%]", main->error.to, main->context.set.error, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, string_status, main->context.set.notable); - fl_print_format("%[' (%]", main->error.to, main->context.set.error, main->context.set.error); - fl_print_format("%[%ui%]", main->error.to, main->context.set.notable, header.status, main->context.set.notable); - - if (header.length) { - fl_print_format("%[): %/Q%]%r", main->error.to, main->context.set.error, main->context.set.error, data->cache.large, data->cache.packet_contents.array[data->cache.packet_contents.used - 1].array[0], f_string_eol_s); - } - else { - fl_print_format("%[).%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - } - - f_file_stream_unlock(main->error.to); - - return; - } - - if (header.status == F_busy) { - if (main->warning.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->warning.to); - - fl_print_format("%r%[%QThe action '%]", main->warning.to, f_string_eol_s, main->context.set.warning, main->warning.prefix, main->context.set.warning); - fl_print_format("%[%q%]", main->warning.to, main->context.set.notable, control_action_type_name(header.action), main->context.set.notable); - fl_print_format("%[' could not be performed because the service is busy.%]%r", main->warning.to, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - f_file_stream_unlock(main->warning.to); - - return; - } - - if (main->output.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->output.to); - - fl_print_format("%rThe action '", main->output.to, f_string_eol_s); - fl_print_format("%[%q%]", main->output.to, main->context.set.notable, control_action_type_name(header.action), main->context.set.notable); - - if (header.status == F_done) { - fl_print_format("' is performed", main->output.to); - } - else { - fl_print_format("' is successfully performed", main->output.to); - } - - if (header.length) { - fl_print_format(": %/Q%r", main->output.to, data->cache.large, data->cache.packet_contents.array[data->cache.packet_contents.used - 1].array[0], f_string_eol_s); - } - else { - fl_print_format(".%r", main->output.to, f_string_eol_s); - } - - f_file_stream_unlock(main->output.to); - } -#endif // _di_control_print_controller_packet_response_ - -#ifndef _di_control_print_debug_packet_header_object_and_content_ - void control_print_debug_packet_header_object_and_content(const fll_program_data_t * const main, const f_string_static_t object, const f_string_static_t content, const f_string_range_t content_range) { - - if (main->output.verbosity == f_console_verbosity_debug_e) return; - - f_file_stream_lock(main->output.to); - - fl_print_format("%rPacket header Object '%[%Q%]", main->output.to, f_string_eol_s, main->context.set.notable, object, main->context.set.notable); - fl_print_format("' has value '%[%/Q%]'.%r", main->output.to, main->context.set.notable, content, content_range, main->context.set.notable, f_string_eol_s); - - f_file_stream_unlock(main->output.to); - } -#endif // _di_control_print_debug_packet_header_object_and_content_ - -#ifndef _di_control_print_debug_packet_message_ - void control_print_debug_packet_message(const fll_program_data_t * const main, const f_string_t message, const f_string_static_t *buffer, const f_string_range_t *range, const f_status_t *status) { - - if (main->output.verbosity == f_console_verbosity_debug_e) return; - - f_file_stream_lock(main->output.to); - - fl_print_format("%r%s", main->output.to, f_string_eol_s, message, main->context.set.notable, main->context.set.notable); - - if (buffer) { - if (range) { - fl_print_format("'%[%/Q%]'", main->output.to, main->context.set.notable, *buffer, *range, main->context.set.notable); - } - else { - fl_print_format("'%[%/Q%]'", main->output.to, main->context.set.notable, *buffer, main->context.set.notable); - } - } - - if (status) { - fl_print_format(", with status code %[%ui%]'", main->output.to, main->context.set.notable, *status, main->context.set.notable); - } - - fl_print_format(".%r", main->output.to, f_string_eol_s); - - f_file_stream_unlock(main->output.to); - } -#endif // _di_control_print_debug_packet_message_ - -#ifndef _di_control_print_error_packet_response_ - void control_print_error_packet_response(const fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t string_status) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QReceived error response for " CONTROL_action_s " '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%q%]", main->error.to, main->context.set.notable, control_action_type_name(header.action), main->context.set.notable); - fl_print_format("%[' with status '%]", main->error.to, main->context.set.error, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, string_status, main->context.set.notable); - fl_print_format("%[' (%]", main->error.to, main->context.set.error, main->context.set.error); - fl_print_format("%[%ui%]", main->error.to, main->context.set.notable, header.status, main->context.set.notable); - - if (header.length) { - fl_print_format("%[): %/Q%]%r", main->error.to, main->context.set.error, main->context.set.error, data->cache.large, data->cache.packet_contents.array[data->cache.packet_contents.used - 1].array[0], f_string_eol_s); - } - else { - fl_print_format("%[).%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - } - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_packet_response_ - -#ifndef _di_control_print_error_parameter_actions_none_ - void control_print_error_parameter_actions_none(const fll_program_data_t * const main) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - fll_print_format("%r%[%QNo actions provided.%]%r", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s); - } -#endif // _di_control_print_error_parameter_actions_none_ - -#ifndef _di_control_print_error_parameter_action_not_ - void control_print_error_parameter_action_not(const fll_program_data_t * const main, const f_string_static_t action) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable); - fl_print_format("%[' is not a known controller action.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_parameter_action_not_ - -#ifndef _di_control_print_error_parameter_action_rule_basename_empty_ - void control_print_error_parameter_action_rule_basename_empty(const fll_program_data_t * const main, const f_string_static_t action) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable); - fl_print_format("%[' a rule base name cannot be an empty string.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_parameter_action_rule_basename_empty_ - -#ifndef _di_control_print_error_parameter_action_rule_directory_empty_ - void control_print_error_parameter_action_rule_directory_empty(const fll_program_data_t * const main, const f_string_static_t action) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable); - fl_print_format("%[' a rule directory path cannot be an empty string.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_parameter_action_rule_directory_empty_ - -#ifndef _di_control_print_error_parameter_action_rule_empty_ - void control_print_error_parameter_action_rule_empty(const fll_program_data_t * const main, const f_string_static_t action) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable); - fl_print_format("%[' a rule name cannot be an empty string.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_parameter_action_rule_empty_ - -#ifndef _di_control_print_error_parameter_action_rule_not_ - void control_print_error_parameter_action_rule_not(const fll_program_data_t * const main, const f_string_static_t action) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable); - fl_print_format("%[' requires either a full rule name or a rule directory path along with the rule base name.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_parameter_action_rule_not_ - -#ifndef _di_control_print_error_parameter_action_rule_too_few_ - void control_print_error_parameter_action_rule_too_few(const fll_program_data_t * const main, const f_string_static_t action) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable); - fl_print_format("%[' has too few arguments.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_parameter_action_rule_too_few_ - -#ifndef _di_control_print_error_parameter_action_rule_too_few_with_ - void control_print_error_parameter_action_rule_too_few_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable); - fl_print_format("%[' when used with '%]", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, with, main->context.set.notable); - fl_print_format("%[' has too few arguments.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_parameter_action_rule_too_few_with_ - -#ifndef _di_control_print_error_parameter_action_rule_too_many_ - void control_print_error_parameter_action_rule_too_many(const fll_program_data_t * const main, const f_string_static_t action) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable); - fl_print_format("%[' has too many arguments.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_parameter_action_rule_too_many_ - -#ifndef _di_control_print_error_parameter_action_rule_too_many_with_ - void control_print_error_parameter_action_rule_too_many_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable); - fl_print_format("%[' when used with '%]", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, with, main->context.set.notable); - fl_print_format("%[' has too many arguments.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_parameter_action_rule_too_many_with_ - -#ifndef _di_control_print_error_parameter_action_rule_with_unknown_ - void control_print_error_parameter_action_rule_with_unknown(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe action parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, action, main->context.set.notable); - fl_print_format("%[' does not know the argument '%]", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, with, main->context.set.notable); - fl_print_format("%['.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_parameter_action_rule_with_unknown_ - -#ifndef _di_control_print_error_parameter_value_empty_ - void control_print_error_parameter_value_empty(const fll_program_data_t * const main, const f_string_static_t parameter) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe value for the parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%r%r%]", main->error.to, main->context.set.notable, f_console_symbol_long_normal_s, parameter, main->context.set.notable); - fl_print_format("%[' must not be an empty string.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_parameter_value_empty_ - -#ifndef _di_control_print_error_parameter_value_not_ - void control_print_error_parameter_value_not(const fll_program_data_t * const main, const f_string_static_t parameter) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe parameter '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%r%r%]", main->error.to, main->context.set.notable, f_console_symbol_long_normal_s, parameter, main->context.set.notable); - fl_print_format("%[' is specified, but no value is given.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_parameter_value_not_ - -#ifndef _di_control_print_error_pipe_supported_not_ - void control_print_error_pipe_supported_not(const fll_program_data_t * const main) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - fll_print_format("%r%[%QPipe input is not supported by this program.%]%r", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s); - } -#endif // _di_control_print_error_pipe_supported_not_ - -#ifndef _di_control_print_error_response_packet_valid_not_ - void control_print_error_response_packet_valid_not(const fll_program_data_t * const main) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - fll_print_format("%r%[%QThe received response is not a valid or supported packet.%]%r", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s); - } -#endif // _di_control_print_error_response_packet_valid_not_ - -#ifndef _di_control_print_error_request_packet_too_large_ - void control_print_error_request_packet_too_large(const fll_program_data_t * const main) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - fll_print_format("%r%[%QThe generated packet is too large, cannot send packet.%]%r", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s); - } -#endif // _di_control_print_error_request_packet_too_large_ - -#ifndef _di_control_print_error_socket_file_failed_ - void control_print_error_socket_file_failed(const fll_program_data_t * const main, const f_string_static_t path_socket) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QFailed to connect to the socket file '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, path_socket, main->context.set.notable); - fl_print_format("%['.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_socket_file_failed_ - -#ifndef _di_control_print_error_socket_file_missing_ - void control_print_error_socket_file_missing(const fll_program_data_t * const main, const f_string_static_t path_socket) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe controller socket file '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, path_socket, main->context.set.notable); - fl_print_format("%[' could not be found and is required.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_socket_file_missing_ - -#ifndef _di_control_print_error_socket_file_not_ - void control_print_error_socket_file_not(const fll_program_data_t * const main, const f_string_static_t path_socket) { - - if (main->error.verbosity == f_console_verbosity_quiet_e) return; - - f_file_stream_lock(main->error.to); - - fl_print_format("%r%[%QThe controller socket file '%]", main->error.to, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to, main->context.set.notable, path_socket, main->context.set.notable); - fl_print_format("%[' is not a socket file.%]%r", main->error.to, main->context.set.error, main->context.set.error, f_string_eol_s); - - f_file_stream_unlock(main->error.to); - } -#endif // _di_control_print_error_socket_file_not_ - -#ifndef _di_control_print_warning_packet_header_duplicate_object_ - void control_print_warning_packet_header_duplicate_object(const fll_program_data_t * const main, const f_string_static_t response_header) { - - if (main->warning.verbosity == f_console_verbosity_debug_e) return; - - f_file_stream_lock(main->warning.to); - - fl_print_format("%r%[%QThe received response header '%]", main->warning.to, f_string_eol_s, main->context.set.warning, main->warning.prefix, main->context.set.warning); - fl_print_format("%[%Q%]", main->warning.to, main->context.set.notable, response_header, main->context.set.notable); - fl_print_format("%[' is repeated.%]%r", main->warning.to, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - f_file_stream_unlock(main->warning.to); - } -#endif // _di_control_print_warning_packet_header_duplicate_object_ - -#ifndef _di_control_print_warning_packet_process_string_to_failed_ - void control_print_warning_packet_process_string_to_failed(const fll_program_data_t * const main, const f_status_t status_of, const f_status_t status_error) { - - if (main->warning.verbosity == f_console_verbosity_debug_e) return; - - f_file_stream_lock(main->warning.to); - - fl_print_format("%r%[%QFailed while calling f_status_string_to() for status%] ", main->output.to, f_string_eol_s, main->context.set.warning, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%ui%]", main->output.to, main->context.set.notable, status_of, main->context.set.notable); - fl_print_format("%[, failing with status code%] ", main->output.to, main->context.set.warning, status_error, main->context.set.warning); - fl_print_format("%[%ui%]", main->output.to, main->context.set.notable, status_error, main->context.set.notable); - fl_print_format("%[.%]%r", main->output.to, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - f_file_stream_unlock(main->warning.to); - } -#endif // _di_control_print_warning_packet_process_string_to_failed_ - -#ifdef __cplusplus -} // extern "C" -#endif diff --git a/level_3/control/c/private-print.h b/level_3/control/c/private-print.h deleted file mode 100644 index d136ec1..0000000 --- a/level_3/control/c/private-print.h +++ /dev/null @@ -1,345 +0,0 @@ -/** - * FLL - Level 3 - * - * Project: Control - * API Version: 0.7 - * Licenses: lgpl-2.1-or-later - */ -#ifndef _PRIVATE_control_print_h -#define _PRIVATE_control_print_h - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Print a message about a packet response. - * - * @param main - * The main program data. - * @param data - * The control data. - * @param header - * The control payload packet header data. - * @param status - * A string representing the name of the status code from header.status. - */ -#ifndef _di_control_print_controller_packet_response_ - extern void control_print_controller_packet_response(const fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t string_status) F_attribute_visibility_internal_d; -#endif // _di_control_print_controller_packet_response_ - -/** - * Print a message displaying the object and content for some packet header. - * - * @param main - * The main program data. - * @param object - * The object string. - * @param content - * The content string. - * @param content_range - * The range representing the content where the content is found within the content string. - */ -#ifndef _di_control_print_debug_packet_header_object_and_content_ - extern void control_print_debug_packet_header_object_and_content(const fll_program_data_t * const main, const f_string_static_t object, const f_string_static_t content, const f_string_range_t content_range) F_attribute_visibility_internal_d; -#endif // _di_control_print_debug_packet_header_object_and_content_ - -/** - * Print a debug message regarding some packet. - * - * @param main - * The main program data. - * @param message - * The message to print. - * - * A single "%[" followed by a single "%]" is supported in the message and is replaced with "notable" context. - * @param buffer - * (optional) An additonal message to print (this is syntax highlighted). - * Set to NULL to not use. - * @param range - * (optional) The range within the buffer to print rather than printing the entire buffer. - * Set to NULL to not use. - * This is ignored when buffer is NULL. - * @param status - * (optional) A status code that triggered the failure (this is syntax highlighted). - * Set to NULL to not use. - */ -#ifndef _di_control_print_debug_packet_message_ - extern void control_print_debug_packet_message(const fll_program_data_t * const main, const f_string_t message, const f_string_static_t *buffer, const f_string_range_t *range, const f_status_t *status) F_attribute_visibility_internal_d; -#endif // _di_control_print_debug_packet_message_ - -/** - * Print an error from the packet response. - * - * @param main - * The main program data. - * @param data - * The control data. - * @param header - * The control payload packet header data. - * @param status - * A string representing the name of the status code from header.status. - */ -#ifndef _di_control_print_error_packet_response_ - extern void control_print_error_packet_response(const fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t status) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_packet_response_ -/** - * Print an error message about no actions being provided. - * - * @param main - * The main program data. - */ -#ifndef _di_control_print_error_parameter_actions_none_ - extern void control_print_error_parameter_actions_none(const fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_actions_none_ - -/** - * Print an error message about the given parameter not matching the known set of controller actions. - * - * @param main - * The main program data. - * @param action - * The parameter representing an action. - */ -#ifndef _di_control_print_error_parameter_action_not_ - extern void control_print_error_parameter_action_not(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_action_not_ - -/** - * Print an error message about the given parameter being a rule action having an empty rule basename. - * - * @param main - * The main program data. - * @param action - * The parameter representing an action. - */ -#ifndef _di_control_print_error_parameter_action_rule_basename_empty_ - extern void control_print_error_parameter_action_rule_basename_empty(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_action_rule_basename_empty_ - -/** - * Print an error message about the given parameter being a rule action having an empty rule directory path. - * - * @param main - * The main program data. - * @param action - * The parameter representing an action. - */ -#ifndef _di_control_print_error_parameter_action_rule_directory_empty_ - extern void control_print_error_parameter_action_rule_directory_empty(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_action_rule_directory_empty_ - -/** - * Print an error message about the given parameter being a rule action having an empty rule name. - * - * @param main - * The main program data. - * @param action - * The parameter representing an action. - */ -#ifndef _di_control_print_error_parameter_action_rule_empty_ - extern void control_print_error_parameter_action_rule_empty(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_action_rule_empty_ - -/** - * Print an error message about the given parameter being a rule action but no rule name is specified. - * - * @param main - * The main program data. - * @param action - * The parameter representing an action. - */ -#ifndef _di_control_print_error_parameter_action_rule_not_ - extern void control_print_error_parameter_action_rule_not(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_action_rule_not_ - -/** - * Print an error message about the given parameter being a rule action having too few arguments passed. - * - * @param main - * The main program data. - * @param action - * The parameter representing an action. - */ -#ifndef _di_control_print_error_parameter_action_rule_too_few_ - extern void control_print_error_parameter_action_rule_too_few(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_action_rule_too_few_ - -/** - * Print an error message about the given parameter being a rule action having few many arguments passed for a given "with". - * - * @param main - * The main program data. - * @param action - * The parameter representing an action. - * @param with - * The additional parameter in which is requiring additional arguments that are not met. - */ -#ifndef _di_control_print_error_parameter_action_rule_too_few_with_ - extern void control_print_error_parameter_action_rule_too_few_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_action_rule_too_few_with_ - -/** - * Print an error message about the given parameter being a rule action having too many arguments passed. - * - * @param main - * The main program data. - * @param action - * The parameter representing an action. - */ -#ifndef _di_control_print_error_parameter_action_rule_too_many_ - extern void control_print_error_parameter_action_rule_too_many(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_action_rule_too_many_ - -/** - * Print an error message about the given parameter being a rule action having too many arguments passed for a given "with". - * - * @param main - * The main program data. - * @param action - * The parameter representing an action. - * @param with - * The additional parameter in which is requiring additional arguments that are not met. - */ -#ifndef _di_control_print_error_parameter_action_rule_too_many_with_ - extern void control_print_error_parameter_action_rule_too_many_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_action_rule_too_many_with_ -/** - * Print an error message about the given parameter being unknown for the use with the given action. - * - * @param main - * The main program data. - * @param action - * The parameter representing an action. - * @param with - * The additional parameter in which is requiring additional arguments that are not met. - */ -#ifndef _di_control_print_error_parameter_action_rule_with_unknown_ - extern void control_print_error_parameter_action_rule_with_unknown(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_action_rule_with_unknown_ - -/** - * Print an error message about the parameter's associated value being an empty string. - * - * @param main - * The main program data. - * @param parameter - * The parameter name. - */ -#ifndef _di_control_print_error_parameter_value_empty_ - extern void control_print_error_parameter_value_empty(const fll_program_data_t * const main, const f_string_static_t parameter) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_value_empty_ - -/** - * Print an error message about the parameter missings its associated value. - * - * @param main - * The main program data. - * @param parameter - * The parameter name. - */ -#ifndef _di_control_print_error_parameter_value_not_ - extern void control_print_error_parameter_value_not(const fll_program_data_t * const main, const f_string_static_t parameter) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_value_not_ - -/** - * Print an error message about a pipe input being unsupported. - * - * @param main - * The main program data. - */ -#ifndef _di_control_print_error_pipe_supported_not_ - extern void control_print_error_pipe_supported_not(const fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_pipe_supported_not_ - -/** - * Print an error message about the response packet format either being invalid or not supported. - * - * @param main - * The main program data. - */ -#ifndef _di_control_print_error_response_packet_valid_not_ - extern void control_print_error_response_packet_valid_not(const fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_response_packet_valid_not_ - -/** - * Print an error message about the request packet being too large. - * - * @param main - * The main program data. - */ -#ifndef _di_control_print_error_request_packet_too_large_ - void extern control_print_error_request_packet_too_large(const fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_request_packet_too_large_ - -/** - * Print an error message about failure to connect to the socket file. - * - * @param main - * The main program data. - * @param path_socket - * The socket file path. - */ -#ifndef _di_control_print_error_socket_file_failed_ - extern void control_print_error_socket_file_failed(const fll_program_data_t * const main, const f_string_static_t path_socket) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_socket_file_failed_ - -/** - * Print an error message about the socket file not being found. - * - * @param main - * The main program data. - * @param path_socket - * The socket file path. - */ -#ifndef _di_control_print_error_socket_file_missing_ - extern void control_print_error_socket_file_missing(const fll_program_data_t * const main, const f_string_static_t path_socket) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_socket_file_missing_ - -/** - * Print an error message about the socket file not actually being a socket file. - * - * @param main - * The main program data. - * @param path_socket - * The socket file path. - */ -#ifndef _di_control_print_error_socket_file_not_ - extern void control_print_error_socket_file_not(const fll_program_data_t * const main, const f_string_static_t path_socket) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_socket_file_not_ - -/** - * Print a warning message about a response header being repeated (when debugging). - * - * This program currently does not support multiple headers for any given valid header Object. - * - * @param main - * The main program data. - * @param response_header - * The repeated response header. - */ -#ifndef _di_control_print_warning_packet_header_duplicate_object_ - extern void control_print_warning_packet_header_duplicate_object(const fll_program_data_t * const main, const f_string_static_t response_header) F_attribute_visibility_internal_d; -#endif // _di_control_print_warning_packet_header_duplicate_object_ - -/** - * Print a warning message about a failure when calling f_status_string_to(). - * - * @param main - * The main program data. - * @param status_of - * The status code to be translating to a string. - * @param status_error - * The status code representing the failure status returned by f_status_string_to(). - * - * @see f_status_string_to() - */ -#ifndef _di_control_print_warning_packet_process_string_to_failed_ - extern void control_print_warning_packet_process_string_to_failed(const fll_program_data_t * const main, const f_status_t status_of, const f_status_t status_error) F_attribute_visibility_internal_d; -#endif // _di_control_print_warning_packet_process_string_to_failed_ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // _PRIVATE_control_print_h diff --git a/level_3/control/data/build/settings b/level_3/control/data/build/settings index fbad463..f60f7d2 100644 --- a/level_3/control/data/build/settings +++ b/level_3/control/data/build/settings @@ -35,11 +35,11 @@ build_libraries-individual_thread -lf_thread build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library control.c common.c print.c private-common.c private-control.c private-print.c +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 main/print/data.c main/print/debug.c main/print/error.c main/print/message.c main/print/warning.c main/action.c main/control.c main/packet.c main/payload.c main/signal.c main/thread.c -build_sources_program main.c +build_sources_program main/main.c -build_sources_headers control.h common.h print.h +build_sources_headers main/common.h main/common/define.h main/common/enumeration.h main/common/print.h main/common/string.h main/common/type.h main/print.h main/print/data.h main/print/debug.h main/print/error.h main/print/message.h main/print/warning.h main/action.h main/control.h main/packet.h main/payload.h main/signal.h main/thread.h build_sources_documentation man