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.
+++ /dev/null
-#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
+++ /dev/null
-/**
- * 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
+++ /dev/null
-#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
+++ /dev/null
-#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;
-}
--- /dev/null
+#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
--- /dev/null
+/**
+ * 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
--- /dev/null
+#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
--- /dev/null
+/**
+ * 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
--- /dev/null
+#include "../control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * 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
--- /dev/null
+#include "../control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * 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
--- /dev/null
+#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
--- /dev/null
+/**
+ * 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
-#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);
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"
* 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.
#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
--- /dev/null
+#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
--- /dev/null
+/**
+ * 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
--- /dev/null
+#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
* 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
#include <fll/level_0/rip.h>
#include <fll/level_0/signal.h>
#include <fll/level_0/socket.h>
+#include <fll/level_0/thread.h>
#include <fll/level_0/status_string.h>
// FLL-1 includes.
#include <fll/level_2/program.h>
// Control includes.
-#include <program/control/common.h>
-#include <program/control/print.h>
+#include <program/control/main/common/define.h>
+#include <program/control/main/common/enumeration.h>
+#include <program/control/main/common/print.h>
+#include <program/control/main/common/string.h>
+#include <program/control/main/common/type.h>
+#include <program/control/main/common.h>
+#include <program/control/main/print/data.h>
+#include <program/control/main/print/debug.h>
+#include <program/control/main/print/error.h>
+#include <program/control/main/print/message.h>
+#include <program/control/main/print/warning.h>
+#include <program/control/main/action.h>
+#include <program/control/main/packet.h>
+#include <program/control/main/payload.h>
+#include <program/control/main/signal.h>
+#include <program/control/main/thread.h>
#ifdef __cplusplus
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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+/**
+ * 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
--- /dev/null
+#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
--- /dev/null
+/**
+ * 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
--- /dev/null
+#include "../control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * 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
--- /dev/null
+#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
--- /dev/null
+/**
+ * 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
--- /dev/null
+#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
--- /dev/null
+/**
+ * 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
--- /dev/null
+#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
--- /dev/null
+/**
+ * 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
--- /dev/null
+#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
--- /dev/null
+/**
+ * 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
--- /dev/null
+#include "control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * 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
--- /dev/null
+#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
--- /dev/null
+/**
+ * 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
--- /dev/null
+#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
--- /dev/null
+/**
+ * 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
+++ /dev/null
-#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
+++ /dev/null
-/**
- * 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
+++ /dev/null
-#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
+++ /dev/null
-/**
- * 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
+++ /dev/null
-#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
+++ /dev/null
-/**
- * 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
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