Maybe there is some way to fix this during compile or link time without having to fix GLIBC or use a different libc for static linking.
Valgrind Debugging:
- The tool code:"helgrind" in valgrind allows for debugging threads (such as code:"valgrind --tool=helgrind" controller).
+ The tool code:"helgrind" in valgrind allows for debugging threads (such as code:"valgrind --tool=helgrind" fake).
The way in which the code:"active" lock is used will result in out of order locks.
This causes code:"helgrind" to produce a lot of warnings about locks being out of order.
+++ /dev/null
-#include "controller.h"
-#include "common/private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_program_version_s_
- const f_string_static_t controller_program_version_s = macro_f_string_static_t_initialize_1(CONTROLLER_program_version_s, 0, CONTROLLER_program_version_s_length);
-#endif // _di_controller_program_version_s_
-
-#ifndef _di_controller_parameter_d_
- const f_string_static_t controller_short_cgroup_s = macro_f_string_static_t_initialize_1(CONTROLLER_short_cgroup_s, 0, CONTROLLER_short_cgroup_s_length);
- const f_string_static_t controller_short_daemon_s = macro_f_string_static_t_initialize_1(CONTROLLER_short_daemon_s, 0, CONTROLLER_short_daemon_s_length);
- const f_string_static_t controller_short_init_s = macro_f_string_static_t_initialize_1(CONTROLLER_short_init_s, 0, CONTROLLER_short_init_s_length);
- const f_string_static_t controller_short_interruptible_s = macro_f_string_static_t_initialize_1(CONTROLLER_short_interruptible_s, 0, CONTROLLER_short_interruptible_s_length);
- const f_string_static_t controller_short_pid_s = macro_f_string_static_t_initialize_1(CONTROLLER_short_pid_s, 0, CONTROLLER_short_pid_s_length);
- const f_string_static_t controller_short_settings_s = macro_f_string_static_t_initialize_1(CONTROLLER_short_settings_s, 0, CONTROLLER_short_settings_s_length);
- const f_string_static_t controller_short_simulate_s = macro_f_string_static_t_initialize_1(CONTROLLER_short_simulate_s, 0, CONTROLLER_short_simulate_s_length);
- const f_string_static_t controller_short_socket_s = macro_f_string_static_t_initialize_1(CONTROLLER_short_socket_s, 0, CONTROLLER_short_socket_s_length);
- const f_string_static_t controller_short_uninterruptible_s = macro_f_string_static_t_initialize_1(CONTROLLER_short_uninterruptible_s, 0, CONTROLLER_short_uninterruptible_s_length);
- const f_string_static_t controller_short_validate_s = macro_f_string_static_t_initialize_1(CONTROLLER_short_validate_s, 0, CONTROLLER_short_validate_s_length);
-
- const f_string_static_t controller_long_cgroup_s = macro_f_string_static_t_initialize_1(CONTROLLER_long_cgroup_s, 0, CONTROLLER_long_cgroup_s_length);
- const f_string_static_t controller_long_daemon_s = macro_f_string_static_t_initialize_1(CONTROLLER_long_daemon_s, 0, CONTROLLER_long_daemon_s_length);
- const f_string_static_t controller_long_init_s = macro_f_string_static_t_initialize_1(CONTROLLER_long_init_s, 0, CONTROLLER_long_init_s_length);
- const f_string_static_t controller_long_interruptible_s = macro_f_string_static_t_initialize_1(CONTROLLER_long_interruptible_s, 0, CONTROLLER_long_interruptible_s_length);
- const f_string_static_t controller_long_pid_s = macro_f_string_static_t_initialize_1(CONTROLLER_long_pid_s, 0, CONTROLLER_long_pid_s_length);
- const f_string_static_t controller_long_settings_s = macro_f_string_static_t_initialize_1(CONTROLLER_long_settings_s, 0, CONTROLLER_long_settings_s_length);
- const f_string_static_t controller_long_simulate_s = macro_f_string_static_t_initialize_1(CONTROLLER_long_simulate_s, 0, CONTROLLER_long_simulate_s_length);
- const f_string_static_t controller_long_socket_s = macro_f_string_static_t_initialize_1(CONTROLLER_long_socket_s, 0, CONTROLLER_long_socket_s_length);
- const f_string_static_t controller_long_uninterruptible_s = macro_f_string_static_t_initialize_1(CONTROLLER_long_uninterruptible_s, 0, CONTROLLER_long_uninterruptible_s_length);
- const f_string_static_t controller_long_validate_s = macro_f_string_static_t_initialize_1(CONTROLLER_long_validate_s, 0, CONTROLLER_long_validate_s_length);
-#endif // _di_controller_parameter_d_
-
-#ifndef _di_controller_main_delete_
- f_status_t controller_main_delete(controller_main_t * const main) {
-
- if (!main) return F_status_set_error(F_parameter);
-
- fll_program_data_delete(&main->program);
- controller_setting_delete(&main->setting);
-
- if (main->process) {
- controller_process_delete(main->process);
- }
-
- return F_okay;
- }
-#endif // _di_controller_main_delete_
-
-#ifndef _di_controller_control_delete_
- f_status_t controller_control_delete(controller_control_t * const control) {
-
- if (!control) return F_status_set_error(F_parameter);
-
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &control->cache_1.string, &control->cache_1.used, &control->cache_1.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &control->cache_2.string, &control->cache_2.used, &control->cache_2.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &control->cache_3.string, &control->cache_3.used, &control->cache_3.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &control->input.string, &control->input.used, &control->input.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &control->output.string, &control->output.used, &control->output.size);
-
- return F_okay;
- }
-#endif // _di_controller_control_delete_
-
-#ifndef _di_controller_control_payload_type_identify_
- uint8_t controller_control_payload_type_identify(const f_string_static_t payload) {
-
- if (f_compare_dynamic(payload, controller_controller_s) == F_equal_to) return controller_control_payload_type_controller_e;
- if (f_compare_dynamic(payload, controller_error_s) == F_equal_to) return controller_control_payload_type_error_e;
- if (f_compare_dynamic(payload, controller_init_s) == F_equal_to) return controller_control_payload_type_init_e;
-
- return 0;
- }
-#endif // _di_controller_control_payload_type_identify_
-
-#ifndef _di_controller_control_payload_type_name_
- f_string_static_t controller_control_payload_type_name(const uint8_t type) {
-
- switch (type) {
- case controller_control_payload_type_controller_e:
- return controller_controller_s;
-
- case controller_control_payload_type_error_e:
- return controller_error_s;
-
- case controller_control_payload_type_init_e:
- return controller_init_s;
- }
-
- return f_string_empty_s;
- }
-#endif // _di_controller_control_payload_type_name_
-
-#ifndef _di_controller_entry_action_type_identify_
- uint8_t controller_entry_action_type_identify(const f_string_static_t action) {
-
- if (f_compare_dynamic(action, controller_consider_s) == F_equal_to) return controller_entry_action_type_consider_e;
- if (f_compare_dynamic(action, controller_execute_s) == F_equal_to) return controller_entry_action_type_execute_e;
- if (f_compare_dynamic(action, controller_failsafe_s) == F_equal_to) return controller_entry_action_type_failsafe_e;
- if (f_compare_dynamic(action, controller_freeze_s) == F_equal_to) return controller_entry_action_type_freeze_e;
- if (f_compare_dynamic(action, controller_item_s) == F_equal_to) return controller_entry_action_type_item_e;
- if (f_compare_dynamic(action, controller_kexec_s) == F_equal_to) return controller_entry_action_type_kexec_e;
- if (f_compare_dynamic(action, controller_kill_s) == F_equal_to) return controller_entry_action_type_kill_e;
- if (f_compare_dynamic(action, controller_pause_s) == F_equal_to) return controller_entry_action_type_pause_e;
- if (f_compare_dynamic(action, controller_ready_s) == F_equal_to) return controller_entry_action_type_ready_e;
- if (f_compare_dynamic(action, controller_reboot_s) == F_equal_to) return controller_entry_action_type_reboot_e;
- if (f_compare_dynamic(action, controller_reload_s) == F_equal_to) return controller_entry_action_type_reload_e;
- if (f_compare_dynamic(action, controller_restart_s) == F_equal_to) return controller_entry_action_type_restart_e;
- if (f_compare_dynamic(action, controller_resume_s) == F_equal_to) return controller_entry_action_type_resume_e;
- if (f_compare_dynamic(action, controller_shutdown_s) == F_equal_to) return controller_entry_action_type_shutdown_e;
- if (f_compare_dynamic(action, controller_start_s) == F_equal_to) return controller_entry_action_type_start_e;
- if (f_compare_dynamic(action, controller_stop_s) == F_equal_to) return controller_entry_action_type_stop_e;
- if (f_compare_dynamic(action, controller_thaw_s) == F_equal_to) return controller_entry_action_type_thaw_e;
- if (f_compare_dynamic(action, controller_timeout_s) == F_equal_to) return controller_entry_action_type_timeout_e;
-
- return 0;
- }
-#endif // _di_controller_entry_action_type_identify_
-
-#ifndef _di_controller_entry_action_type_name_
- f_string_static_t controller_entry_action_type_name(const uint8_t type) {
-
- switch (type) {
- case controller_entry_action_type_consider_e:
- return controller_consider_s;
-
- case controller_entry_action_type_execute_e:
- return controller_execute_s;
-
- case controller_entry_action_type_failsafe_e:
- return controller_failsafe_s;
-
- case controller_entry_action_type_freeze_e:
- return controller_freeze_s;
-
- case controller_entry_action_type_item_e:
- return controller_item_s;
-
- case controller_entry_action_type_kexec_e:
- return controller_kexec_s;
-
- case controller_entry_action_type_kill_e:
- return controller_kill_s;
-
- case controller_entry_action_type_pause_e:
- return controller_pause_s;
-
- case controller_entry_action_type_ready_e:
- return controller_ready_s;
-
- case controller_entry_action_type_reboot_e:
- return controller_reboot_s;
-
- case controller_entry_action_type_reload_e:
- return controller_reload_s;
-
- case controller_entry_action_type_restart_e:
- return controller_restart_s;
-
- case controller_entry_action_type_resume_e:
- return controller_resume_s;
-
- case controller_entry_action_type_shutdown_e:
- return controller_shutdown_s;
-
- case controller_entry_action_type_start_e:
- return controller_start_s;
-
- case controller_entry_action_type_stop_e:
- return controller_stop_s;
-
- case controller_entry_action_type_thaw_e:
- return controller_thaw_s;
-
- case controller_entry_action_type_timeout_e:
- return controller_timeout_s;
- }
-
- return f_string_empty_s;
- }
-#endif // _di_controller_entry_action_type_name_
-
-#ifndef _di_controller_process_delete_
- f_status_t controller_process_delete(controller_process_t * const process) {
-
- if (!process) return F_status_set_error(F_parameter);
-
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &process->name_entry.string, &process->name_entry.used, &process->name_entry.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &process->path_cgroup.string, &process->path_cgroup.used, &process->path_cgroup.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &process->path_control.string, &process->path_control.used, &process->path_control.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &process->path_current.string, &process->path_current.used, &process->path_current.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &process->path_pid.string, &process->path_pid.used, &process->path_pid.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &process->path_setting.string, &process->path_setting.used, &process->path_setting.size);
-
- controller_control_delete(&process->control);
-
- f_memory_arrays_resize(0, sizeof(f_string_map_t), (void **) &process->entry.define.array, &process->entry.define.used, &process->entry.define.size, &f_string_maps_delete_callback);
- f_memory_arrays_resize(0, sizeof(f_string_map_t), (void **) &process->entry.parameter.array, &process->entry.parameter.used, &process->entry.parameter.size, &f_string_maps_delete_callback);
- f_memory_arrays_resize(0, sizeof(f_string_map_t), (void **) &process->exit.define.array, &process->exit.define.used, &process->exit.define.size, &f_string_maps_delete_callback);
- f_memory_arrays_resize(0, sizeof(f_string_map_t), (void **) &process->exit.parameter.array, &process->exit.parameter.used, &process->exit.parameter.size, &f_string_maps_delete_callback);
-
- controller_entry_items_delete(&process->entry.items);
- controller_entry_items_delete(&process->exit.items);
-
- controller_rules_delete(&process->rules);
-
- return F_okay;
- }
-#endif // _di_controller_process_delete_
-
-#ifndef _di_controller_rule_action_type_identify_
- uint8_t controller_rule_action_type_identify(const f_string_static_t action) {
-
- if (f_compare_dynamic(action, controller_freeze_s) == F_equal_to) {
- return controller_rule_action_type_freeze_e;
- }
-
- if (f_compare_dynamic(action, controller_group_s) == F_equal_to) {
- return controller_rule_action_type_group_e;
- }
-
- if (f_compare_dynamic(action, controller_kill_s) == F_equal_to) {
- return controller_rule_action_type_kill_e;
- }
-
- if (f_compare_dynamic(action, controller_pause_s) == F_equal_to) {
- return controller_rule_action_type_pause_e;
- }
-
- if (f_compare_dynamic(action, controller_pid_file_s) == F_equal_to) {
- return controller_rule_action_type_pid_file_e;
- }
-
- if (f_compare_dynamic(action, controller_reload_s) == F_equal_to) {
- return controller_rule_action_type_reload_e;
- }
-
- if (f_compare_dynamic(action, controller_rerun_s) == F_equal_to) {
- return controller_rule_action_type_rerun_e;
- }
-
- if (f_compare_dynamic(action, controller_restart_s) == F_equal_to) {
- return controller_rule_action_type_restart_e;
- }
-
- if (f_compare_dynamic(action, controller_resume_s) == F_equal_to) {
- return controller_rule_action_type_resume_e;
- }
-
- if (f_compare_dynamic(action, controller_start_s) == F_equal_to) {
- return controller_rule_action_type_start_e;
- }
-
- if (f_compare_dynamic(action, controller_stop_s) == F_equal_to) {
- return controller_rule_action_type_stop_e;
- }
-
- if (f_compare_dynamic(action, controller_start_s) == F_equal_to) {
- return controller_rule_action_type_start_e;
- }
-
- if (f_compare_dynamic(action, controller_thaw_s) == F_equal_to) {
- return controller_rule_action_type_thaw_e;
- }
-
- if (f_compare_dynamic(action, controller_user_s) == F_equal_to) {
- return controller_rule_action_type_user_e;
- }
-
- if (f_compare_dynamic(action, controller_with_s) == F_equal_to) {
- return controller_rule_action_type_with_e;
- }
-
- return 0;
- }
-#endif // _di_controller_rule_action_type_identify_
-
-#ifndef _di_controller_rule_action_type_name_
- f_string_static_t controller_rule_action_type_name(const uint8_t type) {
-
- switch (type) {
- case controller_rule_action_type_freeze_e:
- return controller_freeze_s;
-
- case controller_rule_action_type_group_e:
- return controller_group_s;
-
- case controller_rule_action_type_kill_e:
- return controller_kill_s;
-
- case controller_rule_action_type_pause_e:
- return controller_pause_s;
-
- case controller_rule_action_type_pid_file_e:
- return controller_pid_file_s;
-
- case controller_rule_action_type_reload_e:
- return controller_reload_s;
-
- case controller_rule_action_type_rerun_e:
- return controller_rerun_s;
-
- case controller_rule_action_type_restart_e:
- return controller_restart_s;
-
- case controller_rule_action_type_resume_e:
- return controller_resume_s;
-
- case controller_rule_action_type_start_e:
- return controller_start_s;
-
- case controller_rule_action_type_stop_e:
- return controller_stop_s;
-
- case controller_rule_action_type_thaw_e:
- return controller_thaw_s;
-
- case controller_rule_action_type_user_e:
- return controller_user_s;
-
- case controller_rule_action_type_with_e:
- return controller_with_s;
- }
-
- return f_string_empty_s;
- }
-#endif // _di_controller_rule_action_type_name_
-
-#ifndef _di_controller_rule_action_execute_type_identify_
- uint8_t controller_rule_action_execute_type_identify(const f_string_static_t action) {
-
- if (f_compare_dynamic(action, controller_freeze_s) == F_equal_to) {
- return controller_rule_action_execute_type_freeze_e;
- }
-
- if (f_compare_dynamic(action, controller_kill_s) == F_equal_to) {
- return controller_rule_action_execute_type_kill_e;
- }
-
- if (f_compare_dynamic(action, controller_pause_s) == F_equal_to) {
- return controller_rule_action_execute_type_pause_e;
- }
-
- if (f_compare_dynamic(action, controller_reload_s) == F_equal_to) {
- return controller_rule_action_execute_type_reload_e;
- }
-
- if (f_compare_dynamic(action, controller_restart_s) == F_equal_to) {
- return controller_rule_action_execute_type_restart_e;
- }
-
- if (f_compare_dynamic(action, controller_resume_s) == F_equal_to) {
- return controller_rule_action_execute_type_resume_e;
- }
-
- if (f_compare_dynamic(action, controller_start_s) == F_equal_to) {
- return controller_rule_action_execute_type_start_e;
- }
-
- if (f_compare_dynamic(action, controller_stop_s) == F_equal_to) {
- return controller_rule_action_execute_type_stop_e;
- }
-
- if (f_compare_dynamic(action, controller_thaw_s) == F_equal_to) {
- return controller_rule_action_execute_type_thaw_e;
- }
-
- return controller_rule_action_execute_type__enum_size_e;
- }
-#endif // _di_controller_rule_action_execute_type_identify_
-
-#ifndef _di_controller_rule_action_execute_type_name_
- f_string_static_t controller_rule_action_execute_type_name(const uint8_t type) {
-
- switch (type) {
- case controller_rule_action_execute_type_freeze_e:
- return controller_freeze_s;
-
- case controller_rule_action_execute_type_kill_e:
- return controller_kill_s;
-
- case controller_rule_action_execute_type_pause_e:
- return controller_pause_s;
-
- case controller_rule_action_execute_type_reload_e:
- return controller_reload_s;
-
- case controller_rule_action_execute_type_restart_e:
- return controller_restart_s;
-
- case controller_rule_action_execute_type_resume_e:
- return controller_resume_s;
-
- case controller_rule_action_execute_type_start_e:
- return controller_start_s;
-
- case controller_rule_action_execute_type_stop_e:
- return controller_stop_s;
-
- case controller_rule_action_execute_type_thaw_e:
- return controller_thaw_s;
- }
-
- return f_string_empty_s;
- }
-#endif // _di_controller_rule_action_execute_type_name_
-
-#ifndef _di_controller_rule_item_type_identify_
- uint8_t controller_rule_item_type_identify(const f_string_static_t item) {
-
- if (f_compare_dynamic(item, controller_command_s) == F_equal_to) {
- return controller_rule_item_type_command_e;
- }
-
- if (f_compare_dynamic(item, controller_script_s) == F_equal_to) {
- return controller_rule_item_type_script_e;
- }
-
- if (f_compare_dynamic(item, controller_service_s) == F_equal_to) {
- return controller_rule_item_type_service_e;
- }
-
- if (f_compare_dynamic(item, controller_settings_s) == F_equal_to) {
- return controller_rule_item_type_settings_e;
- }
-
- if (f_compare_dynamic(item, controller_utility_s) == F_equal_to) {
- return controller_rule_item_type_utility_e;
- }
-
- return 0;
- }
-#endif // _di_controller_rule_item_type_identify_
-
-#ifndef _di_controller_rule_item_type_name_
- f_string_static_t controller_rule_item_type_name(const uint8_t type) {
-
- switch (type) {
- case controller_rule_item_type_command_e:
- return controller_command_s;
-
- case controller_rule_item_type_script_e:
- return controller_script_s;
-
- case controller_rule_item_type_service_e:
- return controller_service_s;
-
- case controller_rule_item_type_settings_e:
- return controller_settings_s;
-
- case controller_rule_item_type_utility_e:
- return controller_utility_s;
- }
-
- return f_string_empty_s;
- }
-#endif // _di_controller_rule_item_type_name_
-
-#ifndef _di_controller_rule_setting_limit_type_identify_
- uint8_t controller_rule_setting_limit_type_identify(const f_string_static_t limit) {
-
- if (f_compare_dynamic(limit, controller_as_s) == F_equal_to) {
- return controller_resource_limit_type_as_e;
- }
-
- if (f_compare_dynamic(limit, controller_core_s) == F_equal_to) {
- return controller_resource_limit_type_core_e;
- }
-
- if (f_compare_dynamic(limit, controller_cpu_s) == F_equal_to) {
- return controller_resource_limit_type_cpu_e;
- }
-
- if (f_compare_dynamic(limit, controller_data_s) == F_equal_to) {
- return controller_resource_limit_type_data_e;
- }
-
- if (f_compare_dynamic(limit, controller_fsize_s) == F_equal_to) {
- return controller_resource_limit_type_fsize_e;
- }
-
- if (f_compare_dynamic(limit, controller_locks_s) == F_equal_to) {
- return controller_resource_limit_type_locks_e;
- }
-
- if (f_compare_dynamic(limit, controller_memlock_s) == F_equal_to) {
- return controller_resource_limit_type_memlock_e;
- }
-
- if (f_compare_dynamic(limit, controller_msgqueue_s) == F_equal_to) {
- return controller_resource_limit_type_msgqueue_e;
- }
-
- if (f_compare_dynamic(limit, controller_nice_s) == F_equal_to) {
- return controller_resource_limit_type_nice_e;
- }
-
- if (f_compare_dynamic(limit, controller_nofile_s) == F_equal_to) {
- return controller_resource_limit_type_nofile_e;
- }
-
- if (f_compare_dynamic(limit, controller_nproc_s) == F_equal_to) {
- return controller_resource_limit_type_nproc_e;
- }
-
- if (f_compare_dynamic(limit, controller_rss_s) == F_equal_to) {
- return controller_resource_limit_type_rss_e;
- }
-
- if (f_compare_dynamic(limit, controller_rtprio_s) == F_equal_to) {
- return controller_resource_limit_type_rtprio_e;
- }
-
- if (f_compare_dynamic(limit, controller_rttime_s) == F_equal_to) {
- return controller_resource_limit_type_rttime_e;
- }
-
- if (f_compare_dynamic(limit, controller_sigpending_s) == F_equal_to) {
- return controller_resource_limit_type_sigpending_e;
- }
-
- if (f_compare_dynamic(limit, controller_stack_s) == F_equal_to) {
- return controller_resource_limit_type_stack_e;
- }
-
- return 0;
- }
-#endif // _di_controller_rule_setting_limit_type_identify_
-
-#ifndef _di_controller_rule_setting_limit_type_name_
- f_string_static_t controller_rule_setting_limit_type_name(const uint8_t type) {
-
- switch (type) {
- case controller_resource_limit_type_as_e:
- return controller_as_s;
-
- case controller_resource_limit_type_core_e:
- return controller_core_s;
-
- case controller_resource_limit_type_cpu_e:
- return controller_cpu_s;
-
- case controller_resource_limit_type_data_e:
- return controller_data_s;
-
- case controller_resource_limit_type_fsize_e:
- return controller_fsize_s;
-
- case controller_resource_limit_type_locks_e:
- return controller_locks_s;
-
- case controller_resource_limit_type_memlock_e:
- return controller_memlock_s;
-
- case controller_resource_limit_type_msgqueue_e:
- return controller_msgqueue_s;
-
- case controller_resource_limit_type_nice_e:
- return controller_nice_s;
-
- case controller_resource_limit_type_nofile_e:
- return controller_nofile_s;
-
- case controller_resource_limit_type_nproc_e:
- return controller_nproc_s;
-
- case controller_resource_limit_type_rss_e:
- return controller_rss_s;
-
- case controller_resource_limit_type_rtprio_e:
- return controller_rtprio_s;
-
- case controller_resource_limit_type_rttime_e:
- return controller_rttime_s;
-
- case controller_resource_limit_type_sigpending_e:
- return controller_sigpending_s;
-
- case controller_resource_limit_type_stack_e:
- return controller_stack_s;
- }
-
- return f_string_empty_s;
- }
-#endif // _di_controller_rule_setting_limit_type_name_
-
-#ifndef _di_controller_setting_delete_
- f_status_t controller_setting_delete(controller_setting_t * const setting) {
-
- if (!setting) return F_status_set_error(F_parameter);
-
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &setting->path_pid.string, &setting->path_pid.used, &setting->path_pid.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &setting->path_setting.string, &setting->path_setting.used, &setting->path_setting.size);
-
- return F_okay;
- }
-#endif // _di_controller_setting_delete_
-
-#ifndef _di_controller_setting_load_
- void controller_setting_load(const f_console_arguments_t arguments, controller_main_t * const main) {
-
- if (!main) return;
-
- main->setting.state.step_small = controller_allocation_console_d;
-
- f_console_parameter_process(arguments, &main->program.parameters, &main->setting.state, 0);
-
- main->setting.state.step_small = controller_allocation_small_d;
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "f_console_parameter_process", fll_error_file_flag_fallback_e);
-
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- fll_print_dynamic_raw(f_string_eol_s, main->program.error.to);
- }
-
- return;
- }
-
- main->setting.state.status = fll_program_parameter_process_context_standard(F_true, &main->program);
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "fll_program_parameter_process_context_standard", fll_error_file_flag_fallback_e);
-
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- fll_print_dynamic_raw(f_string_eol_s, main->program.error.to);
- }
-
- return;
- }
-
- main->setting.state.status = fll_program_parameter_process_verbosity_standard(F_true, &main->program);
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "fll_program_parameter_process_verbosity_standard", fll_error_file_flag_fallback_e);
-
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- fll_print_dynamic_raw(f_string_eol_s, main->program.error.to);
- }
-
- return;
- }
-
- main->program.output.to.id = F_type_descriptor_output_d;
- main->program.output.to.stream = F_type_output_d;
- main->program.output.to.flag = F_file_flag_create_d | F_file_flag_write_only_d | F_file_flag_append_d;
-
- if (main->program.parameters.array[f_console_standard_parameter_help_e].result & f_console_result_found_e) {
- main->setting.flag |= controller_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 |= controller_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 |= controller_main_flag_copyright_e;
-
- return;
- }
-
- f_string_static_t * const args = main->program.parameters.arguments.array;
-
- if (main->process) {
- //main->process->control.server.address = main->process->control.address; // @fixme is this actually f_socket_address_t?
- main->process->control.server.domain = f_socket_protocol_family_local_e;
- main->process->control.server.type = f_socket_type_stream_e;
- main->process->control.server.length = sizeof(struct sockaddr_un);
-
- //memset(&main->process->control.server.address, 0, main->process->control.server.length);
-
- if (main->program.parameters.remaining.used) {
- main->setting.state.status = f_string_dynamic_append(args[main->program.parameters.remaining.array[0]], &main->process->name_entry);
- }
- else {
- main->setting.state.status = f_string_dynamic_append(controller_default_s, &main->process->name_entry);
- }
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "f_string_dynamic_append", fll_error_file_flag_fallback_e);
-
- return;
- }
-
- if (main->program.parameters.array[controller_parameter_init_e].result & f_console_result_found_e) {
- main->setting.flag |= controller_main_flag_init_e;
- }
-
- if (main->setting.flag & controller_main_flag_init_e) {
- main->process->mode = controller_setting_mode_service_e;
- }
- }
-
- main->setting.state.status = F_okay;
- }
-#endif // _di_controller_setting_load_
-
-#ifndef _di_controller_entry_action_delete_
- f_status_t controller_entry_action_delete(controller_entry_action_t * const action) {
-
- if (!action) return F_status_set_error(F_parameter);
-
- f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &action->parameters.array, &action->parameters.used, &action->parameters.size, &f_string_dynamics_delete_callback);
-
- return F_okay;
- }
-#endif // _di_controller_entry_action_delete_
-
-#ifndef _di_controller_entry_actions_delete_
- f_status_t controller_entry_actions_delete(controller_entry_actions_t * const actions) {
-
- if (!actions) return F_status_set_error(F_parameter);
-
- // @todo Determine if this should be replaced with a resize callback strategy.
- actions->used = actions->size;
-
- while (actions->used) {
- controller_entry_action_delete(&actions->array[--actions->used]);
- } // while
-
- f_memory_array_resize(0, sizeof(controller_entry_action_t), (void **) &actions->array, &actions->used, &actions->size);
-
- return F_okay;
- }
-#endif // _di_controller_entry_actions_delete_
-
-#ifndef _di_controller_entry_actions_increase_by_
- f_status_t controller_entry_actions_increase_by(const f_number_unsigned_t amount, controller_entry_actions_t * const actions) {
-
- if (!actions) return F_status_set_error(F_parameter);
-
- if (amount) {
- if (actions->used >= F_number_t_size_unsigned_d) return F_status_set_error(F_array_too_large);
-
- const f_number_unsigned_t length = actions->used + amount;
-
- if (length > actions->size) {
- const f_status_t status = f_memory_resize(actions->size, length, sizeof(controller_entry_action_t), (void **) & actions->array);
-
- if (F_status_is_error_not(status)) {
- actions->size = actions->used + amount;
- }
-
- return status;
- }
- }
-
- return F_data_not;
- }
-#endif // _di_controller_entry_actions_increase_by_
-
-#ifndef _di_controller_entry_item_delete_
- f_status_t controller_entry_item_delete(controller_entry_item_t * const item) {
-
- if (!item) return F_status_set_error(F_parameter);
-
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &item->name.string, &item->name.used, &item->name.size);
-
- controller_entry_actions_delete(&item->actions);
-
- return F_okay;
- }
-#endif // _di_controller_entry_item_delete_
-
-#ifndef _di_controller_entry_items_delete_
- f_status_t controller_entry_items_delete(controller_entry_items_t * const items) {
-
- if (!items) return F_status_set_error(F_parameter);
-
- // @todo Determine if this should be replaced with a resize callback strategy.
- items->used = items->size;
-
- while (items->used) {
- controller_entry_item_delete(&items->array[--items->used]);
- } // while
-
- f_memory_array_resize(0, sizeof(controller_entry_item_t), (void **) &items->array, &items->used, &items->size);
-
- return F_okay;
- }
-#endif // _di_controller_entry_items_delete_
-
-#ifndef _di_controller_entry_items_increase_by_
- f_status_t controller_entry_items_increase_by(const f_number_unsigned_t amount, controller_entry_items_t * const items) {
-
- if (!items) return F_status_set_error(F_parameter);
-
- if (amount) {
- if (items->used >= F_number_t_size_unsigned_d) return F_status_set_error(F_array_too_large);
-
- const f_number_unsigned_t length = items->used + amount;
-
- if (length > items->size) {
- const f_status_t status = f_memory_resize(items->size, length, sizeof(controller_entry_item_t), (void **) & items->array);
-
- if (F_status_is_error_not(status)) {
- items->size = items->used + amount;
- }
-
- return status;
- }
- }
-
- return F_data_not;
- }
-#endif // _di_controller_entry_items_increase_by_
-
-#ifndef _di_controller_rule_action_t_
- const f_string_static_t controller_rule_action_method_string_extended_s = macro_f_string_static_t_initialize_1(CONTROLLER_rule_action_method_string_extended_s, 0, CONTROLLER_rule_action_method_string_extended_s_length);
- const f_string_static_t controller_rule_action_method_string_extended_list_s = macro_f_string_static_t_initialize_1(CONTROLLER_rule_action_method_string_extended_list_s, 0, CONTROLLER_rule_action_method_string_extended_list_s_length);
-#endif // _di_controller_rule_action_t_
-
-#ifndef _di_controller_rule_action_delete_
- void controller_rule_action_delete(controller_rule_action_t * const action) {
-
- if (!action) return;
-
- f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &action->parameters.array, &action->parameters.used, &action->parameters.size, &f_string_dynamics_delete_callback);
-
- f_memory_array_resize(0, sizeof(f_iki_data_t), (void **) &action->ikis.array, &action->ikis.used, &action->ikis.size);
- }
-#endif // _di_controller_rule_action_delete_
-
-#ifndef _di_controller_rule_actions_delete_
- void controller_rule_actions_delete(controller_rule_actions_t * const actions) {
-
- if (!actions) return;
-
- actions->used = actions->size;
-
- while (actions->used) {
- controller_rule_action_delete(&actions->array[--actions->used]);
- } // while
-
- f_memory_delete(actions->size, sizeof(controller_rule_action_t), (void **) & actions->array);
- actions->size = 0;
- }
-#endif // _di_controller_rule_actions_delete_
-
-#ifndef _di_controller_rule_actions_increase_by_
- f_status_t controller_rule_actions_increase_by(const f_number_unsigned_t amount, controller_rule_actions_t * const actions) {
-
- if (!actions) return F_status_set_error(F_parameter);
-
- if (amount) {
- if (actions->used >= F_number_t_size_unsigned_d) return F_status_set_error(F_array_too_large);
-
- const f_number_unsigned_t length = actions->used + amount;
-
- if (length > actions->size) {
- const f_status_t status = f_memory_resize(actions->size, length, sizeof(controller_rule_action_t), (void **) & actions->array);
-
- if (F_status_is_error_not(status)) {
- actions->size = actions->used + amount;
- }
-
- return status;
- }
- }
-
- return F_data_not;
- }
-#endif // _di_controller_rule_actions_increase_by_
-
-#ifndef _di_controller_rule_delete_
- void controller_rule_delete(controller_rule_t * const rule) {
-
- if (!rule) return;
-
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &rule->engine.string, &rule->engine.used, &rule->engine.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &rule->name.string, &rule->name.used, &rule->name.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &rule->path.string, &rule->path.used, &rule->path.size);
-
- f_memory_arrays_resize(0, sizeof(f_string_map_t), (void **) &rule->define.array, &rule->define.used, &rule->define.size, &f_string_maps_delete_callback);
- f_memory_arrays_resize(0, sizeof(f_string_map_t), (void **) &rule->parameter.array, &rule->parameter.used, &rule->parameter.size, &f_string_maps_delete_callback);
-
- f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &rule->engine_arguments.array, &rule->engine_arguments.used, &rule->engine_arguments.size, &f_string_dynamics_delete_callback);
- f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &rule->environment.array, &rule->environment.used, &rule->environment.size, &f_string_dynamics_delete_callback);
-
- f_memory_array_resize(0, sizeof(int32_t), (void **) &rule->affinity.array, &rule->affinity.used, &rule->affinity.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &rule->cgroup.path.string, &rule->cgroup.path.used, &rule->cgroup.path.size);
- f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &rule->cgroup.groups.array, &rule->cgroup.groups.used, &rule->cgroup.groups.size, &f_string_dynamics_delete_callback);
- f_memory_array_resize(0, sizeof(int32_t), (void **) &rule->groups.array, &rule->groups.used, &rule->groups.size);
- f_memory_array_resize(0, sizeof(f_limit_set_t), (void **) &rule->limits.array, &rule->limits.used, &rule->limits.size);
-
- if (rule->capability) {
- f_capability_delete(&rule->capability);
- }
-
- controller_rule_ons_delete(&rule->ons);
- controller_rule_items_delete(&rule->items);
- }
-#endif // _di_controller_rule_delete_
-
-#ifndef _di_controller_rule_item_delete_
- void controller_rule_item_delete(controller_rule_item_t * const item) {
-
- if (!item) return;
-
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &item->pid_file.string, &item->pid_file.used, &item->pid_file.size);
-
- controller_rule_actions_delete(&item->actions);
- }
-#endif // _di_controller_rule_item_delete_
-
-#ifndef _di_controller_rule_items_delete_
- void controller_rule_items_delete(controller_rule_items_t * const items) {
-
- if (!items) return;
-
- items->used = items->size;
-
- while (items->used) {
- controller_rule_item_delete(&items->array[--items->used]);
- } // while
-
- f_memory_delete(items->size, sizeof(controller_rule_item_t), (void **) & items->array);
- items->size = 0;
- }
-#endif // _di_controller_rule_items_delete_
-
-#ifndef _di_controller_rule_on_delete_
- void controller_rule_on_delete(controller_rule_on_t * const on) {
-
- if (!on) return;
-
- f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &on->need.array, &on->need.used, &on->need.size, &f_string_dynamics_delete_callback);
- f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &on->want.array, &on->want.used, &on->want.size, &f_string_dynamics_delete_callback);
- f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &on->wish.array, &on->wish.used, &on->wish.size, &f_string_dynamics_delete_callback);
- }
-#endif // _di_controller_rule_on_delete_
-
-#ifndef _di_controller_rule_ons_delete_
- void controller_rule_ons_delete(controller_rule_ons_t * const ons) {
-
- if (!ons) return;
-
- ons->used = ons->size;
-
- while (ons->used) {
- controller_rule_on_delete(&ons->array[--ons->used]);
- } // while
-
- f_memory_delete(ons->size, sizeof(controller_rule_on_t), (void **) & ons->array);
- ons->size = 0;
- }
-#endif // _di_controller_rule_ons_delete_
-
-#ifndef _di_controller_rule_ons_increase_
- f_status_t controller_rule_ons_increase(controller_rule_ons_t * const ons) {
-
- if (!ons) return F_status_set_error(F_parameter);
-
- if (ons->used + 1 > ons->size) {
- f_number_unsigned_t length = ons->used + controller_common_allocation_small_d;
-
- if (length > F_number_t_size_unsigned_d) {
- if (ons->used + 1 > F_number_t_size_unsigned_d) {
- return F_status_set_error(F_array_too_large);
- }
-
- length = F_number_t_size_unsigned_d;
- }
-
- return controller_rule_ons_resize(length, ons);
- }
-
- return F_data_not;
- }
-#endif // _di_controller_rule_ons_increase_
-
-#ifndef _di_controller_rule_ons_resize_
- f_status_t controller_rule_ons_resize(const f_number_unsigned_t length, controller_rule_ons_t * const ons) {
-
- if (!ons) return F_status_set_error(F_parameter);
-
- for (f_number_unsigned_t i = length; i < ons->size; ++i) {
- controller_rule_on_delete(&ons->array[i]);
- } // for
-
- const f_status_t status = f_memory_resize(ons->size, length, sizeof(controller_rule_on_t), (void **) & ons->array);
- if (F_status_is_error(status)) return status;
-
- ons->size = length;
-
- if (ons->used > ons->size) {
- ons->used = length;
- }
-
- return F_okay;
- }
-#endif // _di_controller_rule_ons_resize_
-
-#ifndef _di_controller_rules_delete_
- void controller_rules_delete(controller_rules_t * const rules) {
-
- if (!rules) return;
-
- controller_rules_resize(0, rules);
- }
-#endif // _di_controller_rules_delete_
-
-#ifndef _di_controller_rules_increase_
- f_status_t controller_rules_increase(controller_rules_t * const rules) {
-
- if (!rules) return F_status_set_error(F_parameter);
-
- if (rules->used + 1 > rules->size) {
- f_number_unsigned_t length = rules->used + controller_common_allocation_small_d;
-
- if (length > F_number_t_size_unsigned_d) {
- if (rules->used + 1 > F_number_t_size_unsigned_d) {
- return F_status_set_error(F_array_too_large);
- }
-
- length = F_number_t_size_unsigned_d;
- }
-
- return controller_rules_resize(length, rules);
- }
-
- return F_data_not;
- }
-#endif // _di_controller_rules_increase_
-
-#ifndef _di_controller_rules_resize_
- f_status_t controller_rules_resize(const f_number_unsigned_t length, controller_rules_t * const rules) {
-
- if (!rules) return F_status_set_error(F_parameter);
-
- for (f_number_unsigned_t i = length; i < rules->size; ++i) {
- controller_rule_delete(&rules->array[i]);
- } // for
-
- const f_status_t status = f_memory_resize(rules->size, length, sizeof(controller_rule_t), (void **) & rules->array);
- if (F_status_is_error(status)) return status;
-
- rules->size = length;
-
- if (rules->used > rules->size) {
- rules->used = length;
- }
-
- return F_okay;
- }
-#endif // _di_controller_rules_resize_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * 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 _controller_common_h
-#define _controller_common_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * The program version.
- */
-#ifndef _di_controller_program_version_s_
- #define CONTROLLER_program_version_major_s F_string_ascii_0_s
- #define CONTROLLER_program_version_minor_s F_string_ascii_7_s
- #define CONTROLLER_program_version_micro_s F_string_ascii_0_s
-
- #define CONTROLLER_program_version_major_s_length F_string_ascii_0_s_length
- #define CONTROLLER_program_version_minor_s_length F_string_ascii_7_s_length
- #define CONTROLLER_program_version_micro_s_length F_string_ascii_0_s_length
-
- #if !(defined(CONTROLLER_program_version_nano_prefix_s) && defined(CONTROLLER_program_version_nano_prefix_s_length))
- #define CONTROLLER_program_version_nano_prefix_s
- #define CONTROLLER_program_version_nano_prefix_s_length 0
- #endif // !(defined(CONTROLLER_program_version_nano_prefix_s) && defined(CONTROLLER_program_version_nano_prefix_s_length))
-
- #if !(defined(CONTROLLER_program_version_nano_s) && defined(CONTROLLER_program_version_nano_s_length))
- #define CONTROLLER_program_version_nano_s
- #define CONTROLLER_program_version_nano_s_length 0
- #endif // !(defined(CONTROLLER_program_version_nano_s) && defined(CONTROLLER_program_version_nano_s_length))
-
- #define CONTROLLER_program_version_s CONTROLLER_program_version_major_s F_string_ascii_period_s CONTROLLER_program_version_minor_s F_string_ascii_period_s CONTROLLER_program_version_micro_s CONTROLLER_program_version_nano_prefix_s CONTROLLER_program_version_nano_s
-
- #define CONTROLLER_program_version_s_length CONTROLLER_program_version_major_s_length + F_string_ascii_period_s_length + CONTROLLER_program_version_minor_s_length + F_string_ascii_period_s_length + CONTROLLER_program_version_micro_s_length + CONTROLLER_program_version_nano_prefix_s_length + CONTROLLER_program_version_nano_s_length
-
- extern const f_string_static_t controller_program_version_s;
-#endif // _di_controller_program_version_s_
-
-/**
- * The program defines.
- *
- * controller_*_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_controller_d_
- #define controller_allocation_console_d 4
- #define controller_allocation_large_d 256
- #define controller_allocation_small_d 16
- #define controller_signal_check_d 20000
-#endif // _di_controller_d_
-
-/**
- * The main program parameters.
- */
-#ifndef _di_controller_parameter_d_
- #define CONTROLLER_short_cgroup_s "c"
- #define CONTROLLER_short_daemon_s "d"
- #define CONTROLLER_short_init_s "I"
- #define CONTROLLER_short_interruptible_s "i"
- #define CONTROLLER_short_pid_s "p"
- #define CONTROLLER_short_settings_s "s"
- #define CONTROLLER_short_simulate_s "S"
- #define CONTROLLER_short_socket_s "k"
- #define CONTROLLER_short_uninterruptible_s "U"
- #define CONTROLLER_short_validate_s "v"
-
- #define CONTROLLER_long_cgroup_s "cgroup"
- #define CONTROLLER_long_daemon_s "daemon"
- #define CONTROLLER_long_init_s "init"
- #define CONTROLLER_long_interruptible_s "interruptible"
- #define CONTROLLER_long_pid_s "pid"
- #define CONTROLLER_long_settings_s "settings"
- #define CONTROLLER_long_simulate_s "simulate"
- #define CONTROLLER_long_socket_s "socket"
- #define CONTROLLER_long_uninterruptible_s "uninterruptible"
- #define CONTROLLER_long_validate_s "validate"
-
- #define CONTROLLER_short_cgroup_s_length 1
- #define CONTROLLER_short_daemon_s_length 1
- #define CONTROLLER_short_init_s_length 1
- #define CONTROLLER_short_interruptible_s_length 1
- #define CONTROLLER_short_pid_s_length 1
- #define CONTROLLER_short_settings_s_length 1
- #define CONTROLLER_short_simulate_s_length 1
- #define CONTROLLER_short_socket_s_length 1
- #define CONTROLLER_short_uninterruptible_s_length 1
- #define CONTROLLER_short_validate_s_length 1
-
- #define CONTROLLER_long_cgroup_s_length 6
- #define CONTROLLER_long_daemon_s_length 6
- #define CONTROLLER_long_init_s_length 4
- #define CONTROLLER_long_interruptible_s_length 13
- #define CONTROLLER_long_pid_s_length 3
- #define CONTROLLER_long_settings_s_length 8
- #define CONTROLLER_long_simulate_s_length 8
- #define CONTROLLER_long_socket_s_length 6
- #define CONTROLLER_long_uninterruptible_s_length 15
- #define CONTROLLER_long_validate_s_length 8
-
- extern const f_string_static_t controller_short_cgroup_s;
- extern const f_string_static_t controller_short_daemon_s;
- extern const f_string_static_t controller_short_init_s;
- extern const f_string_static_t controller_short_interruptible_s;
- extern const f_string_static_t controller_short_pid_s;
- extern const f_string_static_t controller_short_settings_s;
- extern const f_string_static_t controller_short_simulate_s;
- extern const f_string_static_t controller_short_socket_s;
- extern const f_string_static_t controller_short_uninterruptible_s;
- extern const f_string_static_t controller_short_validate_s;
-
- extern const f_string_static_t controller_long_cgroup_s;
- extern const f_string_static_t controller_long_daemon_s;
- extern const f_string_static_t controller_long_init_s;
- extern const f_string_static_t controller_long_interruptible_s;
- extern const f_string_static_t controller_long_pid_s;
- extern const f_string_static_t controller_long_settings_s;
- extern const f_string_static_t controller_long_simulate_s;
- extern const f_string_static_t controller_long_socket_s;
- extern const f_string_static_t controller_long_uninterruptible_s;
- extern const f_string_static_t controller_long_validate_s;
-
- enum {
- controller_parameter_cgroup_e = f_console_standard_parameter_last_e,
- controller_parameter_daemon_e,
- controller_parameter_init_e,
- controller_parameter_interruptible_e,
- controller_parameter_pid_e,
- controller_parameter_settings_e,
- controller_parameter_simulate_e,
- controller_parameter_socket_e,
- controller_parameter_uninterruptible_e,
- controller_parameter_validate_e,
- }; // enum
-
- #define controller_console_parameter_t_initialize \
- { \
- macro_fll_program_console_parameter_standard_initialize, \
- \
- macro_f_console_parameter_t_initialize_3(controller_short_cgroup_s, controller_long_cgroup_s, 1, f_console_flag_normal_e), \
- macro_f_console_parameter_t_initialize_3(controller_short_daemon_s, controller_long_daemon_s, 0, f_console_flag_normal_e), \
- macro_f_console_parameter_t_initialize_3(controller_short_init_s, controller_long_init_s, 0, f_console_flag_normal_e), \
- macro_f_console_parameter_t_initialize_3(controller_short_interruptible_s, controller_long_interruptible_s, 0, f_console_flag_normal_e), \
- macro_f_console_parameter_t_initialize_3(controller_short_pid_s, controller_long_pid_s, 1, f_console_flag_normal_e), \
- macro_f_console_parameter_t_initialize_3(controller_short_settings_s, controller_long_settings_s, 1, f_console_flag_normal_e), \
- macro_f_console_parameter_t_initialize_3(controller_short_simulate_s, controller_long_simulate_s, 0, f_console_flag_normal_e), \
- macro_f_console_parameter_t_initialize_3(controller_short_socket_s, controller_long_socket_s, 1, f_console_flag_normal_e), \
- macro_f_console_parameter_t_initialize_3(controller_short_uninterruptible_s, controller_long_uninterruptible_s, 0, f_console_flag_normal_e), \
- macro_f_console_parameter_t_initialize_3(controller_short_validate_s, controller_long_validate_s, 0, f_console_flag_normal_e), \
- }
-
- #define controller_parameter_total_d (f_console_parameter_state_type_total_d + 10)
-#endif // _di_controller_parameter_d_
-
-/**
- * Codes representing control payload types.
- *
- * controller_control_payload_type_*:
- * - controller: The item type represents a command operation.
- * - error: The item type represents a script operation.
- * - init: The item type represents an init operation (Only fo init mode).
- */
-#ifndef _di_controller_control_payload_type_e_
- enum {
- controller_control_payload_type_controller_e = 1,
- controller_control_payload_type_error_e,
- controller_control_payload_type_init_e,
- }; // enum
-#endif // _di_controller_control_payload_type_e_
-
-/**
- * Codes representing supported actions.
- *
- * controller_entry_action_type_*:
- * - consider: Perform the consider controller operation.
- * - execute: Perform the execute controller operation.
- * - freeze: Perform the freeze controller operation..
- * - item: Perform the item controller operation.
- * - kexec: Perform the kexec controller operation (only for init mode).
- * - kill: Perform the kill controller operation.
- * - pause: Perform the pause controller operation.
- * - ready: Perform the ready controller operation.
- * - reboot: Perform the reboot controller operation (only for init mode).
- * - reload: Perform the reload 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.
- * - timeout: Perform the timeout controller operation.
- * - thaw: Perform the thaw controller operation.
- */
-#ifndef _di_controller_entry_action_type_e_
- enum {
- controller_entry_action_type_consider_e = 1,
- controller_entry_action_type_execute_e,
- controller_entry_action_type_failsafe_e,
- controller_entry_action_type_freeze_e,
- controller_entry_action_type_item_e,
- controller_entry_action_type_kexec_e,
- controller_entry_action_type_kill_e,
- controller_entry_action_type_pause_e,
- controller_entry_action_type_ready_e,
- controller_entry_action_type_reboot_e,
- controller_entry_action_type_reload_e,
- controller_entry_action_type_restart_e,
- controller_entry_action_type_resume_e,
- controller_entry_action_type_shutdown_e,
- controller_entry_action_type_start_e,
- controller_entry_action_type_stop_e,
- controller_entry_action_type_timeout_e,
- controller_entry_action_type_thaw_e,
- }; // enum
-#endif // _di_controller_entry_action_type_e_
-
-/**
- * Codes representing rule actions.
- *
- * controller_rule_action_type_*:
- * - freeze: The Freeze execution instructions.
- * - group: The Group setting.
- * - kill: The Kill execution instructions.
- * - pause: The Pause execution instructions.
- * - pid_file: The PID file setting.
- * - rerun: The Re-run execution after success or failure.
- * - reload: The Reload execution instructions.
- * - restart: The Restart execution instructions.
- * - resume: The Resume execution instructions.
- * - start: The Start execution instructions.
- * - stop: The Stop execution instructions.
- * - thaw: The Thaw execution instructions.
- * - user: The User setting.
- * - with: The With flags.
- */
-#ifndef _di_controller_rule_action_type_e_
- enum {
- controller_rule_action_type_freeze_e = 1,
- controller_rule_action_type_group_e,
- controller_rule_action_type_kill_e,
- controller_rule_action_type_pause_e,
- controller_rule_action_type_pid_file_e,
- controller_rule_action_type_reload_e,
- controller_rule_action_type_rerun_e,
- controller_rule_action_type_restart_e,
- controller_rule_action_type_resume_e,
- controller_rule_action_type_start_e,
- controller_rule_action_type_stop_e,
- controller_rule_action_type_thaw_e,
- controller_rule_action_type_user_e,
- controller_rule_action_type_with_e,
-
- // Designate the largest value in the enum, the '__' is intended.
- controller_rule_action_type__enum_size_e,
- }; // enum
-#endif // _di_controller_rule_action_type_e_
-
-/**
- * Codes representing rule action executes.
- *
- * Execute type starts at 0 because it is intended to be used as an index within a static array.
- *
- * controller_rule_action_execute_type_*:
- * - freeze: The Freeze execution instructions.
- * - kill: The Kill execution instructions.
- * - pause: The Pause execution instructions.
- * - reload: The Reload execution instructions.
- * - restart: The Restart execution instructions.
- * - resume: The Resume execution instructions.
- * - start: The Start execution instructions.
- * - stop: The Stop execution instructions.
- * - thaw: The Thaw execution instructions.
- */
-#ifndef _di_controller_rule_action_execute_type_e_
- enum {
- controller_rule_action_execute_type_freeze_e = 0,
- controller_rule_action_execute_type_kill_e,
- controller_rule_action_execute_type_pause_e,
- controller_rule_action_execute_type_reload_e,
- controller_rule_action_execute_type_restart_e,
- controller_rule_action_execute_type_resume_e,
- controller_rule_action_execute_type_start_e,
- controller_rule_action_execute_type_stop_e,
- controller_rule_action_execute_type_thaw_e,
-
- // Designate the largest value in the enum, the '__' is intended.
- controller_rule_action_execute_type__enum_size_e,
- }; // enum
-#endif // _di_controller_rule_action_execute_type_e_
-
-/**
- * Codes representing rule items.
- *
- * controller_rule_item_type_*:
- * - command: The item type represents a command operation.
- * - script: The item type represents a script operation.
- * - service: The item type represents a service operation.
- * - settings: The item type represents a setting operation.
- * - utility: The item type represents a utility operation.
- */
-#ifndef _di_controller_rule_item_type_e_
- enum {
- controller_rule_item_type_command_e = 1,
- controller_rule_item_type_script_e,
- controller_rule_item_type_service_e,
- controller_rule_item_type_settings_e,
- controller_rule_item_type_utility_e,
- }; // enum
-#endif // _di_controller_rule_item_type_e_
-
-/**
- * A set of codes for resource limitations.
- *
- * This essentally converts the POSIX standard names into a more verbose format.
- */
-#ifndef _di_controller_resource_limit_type_d_
- enum {
- controller_resource_limit_type_as_e = RLIMIT_AS,
- controller_resource_limit_type_core_e = RLIMIT_CORE,
- controller_resource_limit_type_cpu_e = RLIMIT_CPU,
- controller_resource_limit_type_data_e = RLIMIT_DATA,
- controller_resource_limit_type_fsize_e = RLIMIT_FSIZE,
- controller_resource_limit_type_locks_e = RLIMIT_LOCKS,
- controller_resource_limit_type_memlock_e = RLIMIT_MEMLOCK,
- controller_resource_limit_type_msgqueue_e = RLIMIT_MSGQUEUE,
- controller_resource_limit_type_nice_e = RLIMIT_NICE,
- controller_resource_limit_type_nofile_e = RLIMIT_NOFILE,
- controller_resource_limit_type_nproc_e = RLIMIT_NPROC,
- controller_resource_limit_type_rss_e = RLIMIT_RSS,
- controller_resource_limit_type_rtprio_e = RLIMIT_RTPRIO,
- controller_resource_limit_type_rttime_e = RLIMIT_RTTIME,
- controller_resource_limit_type_sigpending_e = RLIMIT_SIGPENDING,
- controller_resource_limit_type_stack_e = RLIMIT_STACK,
- }; // enum
-#endif // _di_controller_resource_limit_type_d_
-
-/**
- * Flags passed to the main function or program.
- *
- * controller_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.
- * - init: Operate as an "init" program.
- * - separate: Enable printing of separators.
- * - strip_invalid: Using strip invalid character mode.
- * - verify: Using verify mode.
- * - version: Print version.
- * - version_copyright_help: A helper flag representing version, copyright, and help flag bits being set.
- */
-#ifndef _di_controller_main_flag_e_
- enum {
- controller_main_flag_none_e = 0x0,
- controller_main_flag_copyright_e = 0x1,
- controller_main_flag_file_from_e = 0x2,
- controller_main_flag_file_to_e = 0x4,
- controller_main_flag_header_e = 0x8,
- controller_main_flag_help_e = 0x10,
- controller_main_flag_init_e = 0x20,
- controller_main_flag_separate_e = 0x40,
- controller_main_flag_strip_invalid_e = 0x80,
- controller_main_flag_verify_e = 0x100,
- controller_main_flag_version_e = 0x200,
- controller_main_flag_version_copyright_help_e = 0x211,
- }; // enum
-#endif // _di_controller_main_flag_e_
-
-/**
- * Flags for fine-tuned print control.
- *
- * controller_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_controller_print_flag_e_
- enum {
- controller_print_flag_none_e = 0x0,
- controller_print_flag_debug_e = 0x1,
- controller_print_flag_error_e = 0x2,
- controller_print_flag_file_e = 0x4,
- controller_print_flag_in_e = 0x8,
- controller_print_flag_out_e = 0x10,
- controller_print_flag_message_e = 0x20,
- controller_print_flag_warning_e = 0x40,
- }; // enum
-#endif // _di_controller_print_flag_e_
-
-/**
- * The controller 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.
- * as_init: Designate whether or not this is running as an init program.
- *
- * state: The state information.
- *
- * default_engine: The default scripting engine.
- * default_path_pid: The default PID file path.
- * default_path_pid_init: The default PID file path, when run as init.
- * default_path_pid_prefix: The default PID file path prefix.
- * default_path_pid_suffix: The default PID file path suffix.
- * default_path_setting: The default setting path.
- * default_path_setting_init: The default setting path, when run as init.
- * default_path_socket: The default socket file path.
- * default_path_socket_init: The default socket file path, when run as init.
- * default_path_socket_prefix: The default socket file path prefix.
- * default_path_socket_suffix: The default socket file path suffix.
- *
- * program_name: The short program name.
- * program_name_long: The long program name.
- *
- * path_pid: The name of the program.
- * path_setting: The long name of the program.
- */
-#ifndef _di_controller_setting_t_
- typedef struct {
- uint16_t flag;
-
- f_state_t state;
-
- const f_string_static_t *default_engine;
- const f_string_static_t *default_path_pid;
- const f_string_static_t *default_path_pid_init;
- const f_string_static_t *default_path_pid_prefix;
- const f_string_static_t *default_path_pid_suffix;
- const f_string_static_t *default_path_setting;
- const f_string_static_t *default_path_setting_init;
- const f_string_static_t *default_path_socket;
- const f_string_static_t *default_path_socket_init;
- const f_string_static_t *default_path_socket_prefix;
- const f_string_static_t *default_path_socket_suffix;
-
- f_string_static_t program_name;
- f_string_static_t program_name_long;
-
- f_string_dynamic_t path_pid;
- f_string_dynamic_t path_setting;
- } controller_setting_t;
-
- #define controller_setting_t_initialize \
- { \
- controller_main_flag_none_e, \
- f_state_t_initialize, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- f_string_static_t_initialize, \
- f_string_static_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- }
-#endif // _di_controller_setting_t_
-
-/**
- * Provide default control settings.
- *
- * controller_control_default:
- * - socket_backlog: The amount of waiting client connections to support while handling a socket connection.
- * - socket_buffer: The preferred max size of the buffer such that if the buffer exceeds this then it is reallocated to this size at the end of processing.
- * - socket_buffer_max: The max size allowed in the buffer (this value must not be set smaller than the packet headers).
- * - socket_cache: The preferred max size of the control cache such that if the cache exceeds this then it is reallocated to this size at the end of processing.
- * - socket_header: The minimum size in bytes of the packet header to read to be able to process the size information.
- * - socket_linger: The number of seconds to linger the connection before closing.
- * - socket_timeout: The number of microseconds to wait.
- * - socket_payload_max: The max size allowed for the "payload" part of a packet and must be smaller than socket_buffer_max (this is smaller than socket_buffer_max to allow for enough room to afford a header).
- */
-#ifndef _di_controller_control_defaults_
- #define controller_control_default_socket_backlog_d 64
- #define controller_control_default_socket_buffer_d 2048
- #define controller_control_default_socket_buffer_max_d 4294967296
- #define controller_control_default_socket_cache_d 128
- #define controller_control_default_socket_header_d 5
- #define controller_control_default_socket_linger_d 2
- #define controller_control_default_socket_timeout_d 10000 // 0.01 seconds.
- #define controller_control_default_socket_payload_max_d 4294965248
-#endif // _di_controller_defaults_
-
-/**
- * The control data.
- *
- * controller_control_flag_*:
- * - readonly: Control is set to read-only mode.
- * - has_user: A user is manually specified.
- * - has_group: A group is manually specified.
- * - has_mode: A file mode is manually specified.
- *
- * flag: Flags from controller_control_flag_*.
- * user: The user ID, if specified.
- * group: The group ID, if specified.
- * mode: The file mode, if specified.
- * server: The server socket connection.
- * client: The client socket connection.
- * cache_1: A generic buffer used for caching control related data.
- * cache_2: A generic buffer used for caching control related data.
- * cache_3: A generic buffer used for caching control related data.
- * input: A buffer used for receiving data from the client.
- * output: A buffer used for transmitting data to the client.
- * address: The socket address structure.
- */
-#ifndef _di_controller_control_t_
- enum {
- controller_control_flag_readonly_e = 0x1,
- controller_control_flag_has_user_e = 0x2,
- controller_control_flag_has_group_e = 0x4,
- controller_control_flag_has_mode_e = 0x8,
- };
-
- typedef struct {
- uint8_t flag;
-
- uid_t user;
- gid_t group;
- mode_t mode;
-
- f_socket_t server;
- f_socket_t client;
-
- f_string_dynamic_t cache_1;
- f_string_dynamic_t cache_2;
- f_string_dynamic_t cache_3;
-
- f_string_dynamic_t input;
- f_string_dynamic_t output;
-
- struct sockaddr_un address;
- } controller_control_t;
-
- #define controller_control_t_initialize { \
- 0, \
- -1, \
- -1, \
- 0, \
- f_socket_t_initialize, \
- f_socket_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- { }, \
- }
-#endif // _di_controller_control_t_
-
-/**
- * A codes repesent different flags associated with a packet.
- *
- * controller_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_controller_control_packet_flag_
- #define controller_control_packet_flag_binary_d 0x10000000
- #define controller_control_packet_flag_endian_big_d 0x01000000
-#endif // _di_controller_control_packet_flag_
-
-/**
- * An Entry Item Action.
- *
- * controller_entry_action_flag_*:
- * - undefined: The given type and code are designated as undefined.
- *
- * controller_entry_action_type_*:
- * - consider: Designate a rule to be pre-loaded.
- * - execute: Execute into another program.
- * - failsafe: Designate a failsafe "item".
- * - freeze: A Rule Action for freezing.
- * - item: A named set of Rules.
- * - kill: A Rule Action for killing.
- * - pause: A Rule Action for pausing.
- * - ready: Designate readiness for special processing for Entry or Exit.
- * - reload: A Rule Action for reloading.
- * - restart: A Rule Action for restarting.
- * - resume: A Rule Action for resuming.
- * - start: A Rule Action for starting.
- * - stop: A Rule Action for stopping.
- * - timeout: Inline timeout settings.
- * - thaw: A Rule Action for unfreezing.
- *
- * controller_entry_rule_code_*:
- * - asynchronous: Process Rule asynchronously.
- * - require: Require Rule operations to succeed or the Entry/Exit will fail.
- * - wait: Wait for all existing asynchronous processes to finish before operating Rule.
- *
- * controller_entry_timeout_code_*:
- * - exit: The timeout Action represents an exit timeout.
- * - kill: The timeout Action represents a kill timeout.
- * - start: The timeout Action represents a start timeout.
- * - stop: The timeout Action represents a stop timeout.
- *
- * type: The type of Action.
- * code: A single code or sub-type associated with the Action.
- * flag: A set of flags to describe special behavior for the given type and code (flags may be different per type and code).
- * line: The line number where the Entry Item begins.
- * number: The unsigned number that some types use instead of the "parameters".
- * status: The overall status.
- * parameters: The values associated with the Action.
- */
-#ifndef _di_controller_entry_action_t_
- #define controller_entry_rule_code_asynchronous_d 0x1
- #define controller_entry_rule_code_require_d 0x2
- #define controller_entry_rule_code_wait_d 0x4
-
- #define controller_entry_timeout_code_exit_d 0x1
- #define controller_entry_timeout_code_kill_d 0x2
- #define controller_entry_timeout_code_start_d 0x4
- #define controller_entry_timeout_code_stop_d 0x8
-
- enum {
- controller_entry_action_flag_none_e = 0x0,
- controller_entry_action_flag_undefined_e = 0x1,
- };
-
- typedef struct {
- uint8_t type;
- uint8_t code;
- uint8_t flag;
-
- f_number_unsigned_t line;
- f_number_unsigned_t number;
-
- f_status_t status;
-
- f_string_dynamics_t parameters;
- } controller_entry_action_t;
-
- #define controller_entry_action_t_initialize { \
- 0, \
- 0, \
- 0, \
- controller_entry_action_flag_none_e, \
- 0, \
- F_known_not, \
- f_string_dynamics_t_initialize, \
- }
-#endif // _di_controller_entry_action_t_
-
-/**
- * The Entry Item Actions.
- *
- * array: An array of Entry Item Actions.
- * size: Total amount of allocated space.
- * used: Total number of allocated spaces used.
- */
-#ifndef _di_controller_entry_actions_t_
- typedef struct {
- controller_entry_action_t *array;
-
- f_number_unsigned_t size;
- f_number_unsigned_t used;
- } controller_entry_actions_t;
-
- #define controller_entry_actions_t_initialize { \
- 0, \
- 0, \
- 0, \
- }
-#endif // _di_controller_entry_actions_t_
-
-/**
- * An Entry Item.
- *
- * line: The line number where the Entry Item begins.
- * name: The name of the Entry Item.
- * actions: The Actions associated with the Entry Item.
- */
-#ifndef _di_controller_entry_item_t_
- typedef struct {
- f_number_unsigned_t line;
- f_string_dynamic_t name;
-
- controller_entry_actions_t actions;
- } controller_entry_item_t;
-
- #define controller_entry_item_t_initialize \
- { \
- 0, \
- f_string_dynamic_t_initialize, \
- controller_entry_actions_t_initialize, \
- }
-#endif // _di_controller_entry_item_t_
-
-/**
- * An Entry Items.
- *
- * array: An array of Entry Items.
- * size: Total amount of allocated space.
- * used: Total number of allocated spaces used.
- */
-#ifndef _di_controller_entry_items_t_
- typedef struct {
- controller_entry_item_t *array;
-
- f_number_unsigned_t size;
- f_number_unsigned_t used;
- } controller_entry_items_t;
-
- #define controller_entry_items_t_initialize { \
- 0, \
- 0, \
- 0, \
- }
-
- #define macro_controller_entry_items_t_clear(items) \
- items.array = 0; \
- items.size = 0; \
- items.used = 0;
-#endif // _di_controller_entry_items_t_
-
-/**
- * The Entry or Exit.
- *
- * Entry and Exit files are essentially the same structure with minor differences in settings and behavior.
- * The structure is identical and due to lacking any particularly good name to represent both "entry" or "exit", the name "entry" is being used for both.
- *
- * controller_entry_flag_*:
- * - none_e: No flags are set.
- * - timeout_exit_no_e: The exit timeout is disabled.
- * - timeout_kill_no_e: The kill timeout is disabled for Rules by default.
- * - timeout_start_no_e: The start timeout is disabled for Rules by default.
- * - timeout_stop_no_e: The stop timeout is disabled for Rules by default.
- *
- * controller_entry_session_*:
- * - none: No special session configuration specified, use built in defaults.
- * - new: Designate the default to use a new session, ignoring built in defaults (passing FL_execute_parameter_option_session_d to the execute functions).
- * - same: Designate the default to use a same session, ignoring built in defaults.
- *
- * controller_entry_pid_*:
- * - disable: Do not check for or create a PID file to represent the entry execution.
- * - require: Check to see if the PID file exists for an entry at startup and then when "ready" create a pid file, display error on pid file already exists or on failure and then fail.
- * - ready: When "ready" create a pid file, display error on failure and then fail (does not check if PID file exists).
- *
- * controller_entry_show_*:
- * - normal: Do not print anything other than warnings and errors, but allow executed programs and scripts to output however they like.
- * - init: Print like an init program, printing status of entry and rules as they are being started, stopped, etc...
- *
- * define: Any defines (environment variables) made available to all Rules in this entry for IKI substitution or just as environment variables.
- * flag: A set of flags, primarily used to designate that timeouts are disabled.
- * items: The array of entry items.
- * parameter: Any parameters made available to all Rules in this entry for IKI substitution.
- * pid: The PID file generation setting.
- * session: The default session settings (when NULL, no default is specified).
- * show: The show setting for controlling what to show when executing entry items and rules.
- * status: The overall status.
- * timeout_exit: The timeout to wait when exiting the Controller program after sending the terminate signal to send the kill signal.
- * timeout_kill: The timeout to wait relating to using a kill signal.
- * timeout_start: The timeout to wait relating to starting a process.
- * timeout_stop: The timeout to wait relating to stopping a process.
- */
-#ifndef _di_controller_entry_t_
- enum {
- controller_entry_pid_disable_e = 0,
- controller_entry_pid_require_e,
- controller_entry_pid_ready_e,
- };
-
- enum {
- controller_entry_show_normal_e = 0,
- controller_entry_show_init_e,
- };
-
- enum {
- controller_entry_session_none_e = 0,
- controller_entry_session_new_e,
- controller_entry_session_same_e,
- };
-
- enum {
- controller_entry_flag_none_e = 0x0,
- controller_entry_flag_timeout_exit_no_e = 0x1,
- controller_entry_flag_timeout_kill_no_e = 0x2,
- controller_entry_flag_timeout_start_no_e = 0x4,
- controller_entry_flag_timeout_stop_no_e = 0x8,
- };
-
- typedef struct {
- f_status_t status;
-
- uint8_t pid;
- uint8_t session;
- uint8_t show;
- uint8_t flag;
-
- f_number_unsigned_t timeout_exit;
- f_number_unsigned_t timeout_kill;
- f_number_unsigned_t timeout_start;
- f_number_unsigned_t timeout_stop;
-
- f_string_maps_t define;
- f_string_maps_t parameter;
-
- controller_entry_items_t items;
- } controller_entry_t;
-
- #define controller_entry_t_initialize { \
- F_known_not, \
- controller_entry_pid_require_e, \
- controller_entry_session_none_e, \
- controller_entry_show_normal_e, \
- 0, \
- controller_thread_exit_timeout_d, \
- 0, \
- 0, \
- 0, \
- f_string_maps_t_initialize, \
- f_string_maps_t_initialize, \
- controller_entry_items_t_initialize, \
- }
-#endif // _di_controller_entry_t_
-
-/**
- * The Rule "rerun" item for controlling re-execution.
- *
- * count: A count of the number of executions.
- * delay: The time to wait before attempting to re-run.
- * max: The maximum number of times to re-run (with 0 representing re-run infinitely) for executions.
- */
-#ifndef _di_controller_rule_rerun_item_t_
- typedef struct {
- bool reset;
-
- f_number_unsigned_t count;
- f_number_unsigned_t delay;
- f_number_unsigned_t max;
- } controller_rule_rerun_item_t;
-
- #define controller_rule_rerun_item_initialize { \
- F_false, \
- 0, \
- 5000, \
- 0, \
-
- #define macro_controller_rule_rerun_item_initialize(item) { \
- item.reset = F_false; \
- item.count = 0; \
- item.delay = 5000; \
- item.max = 0; \
- }
-#endif // _di_controller_rule_rerun_item_t_
-
-/**
- * The Rule "rerun" values for controlling re-execution.
- *
- * controller_rule_rerun_is_*:
- * - failure: The success re-run is enabled.
- * - failure_reset: Reset success counter when failure is returned.
- * - success: The success re-run is enabled.
- * - success_reset: Reset failure counter when success is returned.
- *
- * is: A bitwise set of options to designate whether rerun is enabled or not and other options.
- * count_failure: A count of the number of failed executions.
- * count_success: A count of the number of successful executions.
- * delay_failure: The time to wait before attempting to "rerun" for failed executions.
- * delay_success: The time to wait before attempting to "rerun" for successful executions.
- * max_failure: The maximum number of times to "rerun" (with 0 representing "rerun" infinitely) for failed executions.
- * max_success: The maximum number of times to "rerun" (with 0 representing "rerun" infinitely) for successful executions.
- */
-#ifndef _di_controller_rule_rerun_t_
- #define controller_rule_rerun_is_failure_d 0x1
- #define controller_rule_rerun_is_failure_reset_d 0x2
- #define controller_rule_rerun_is_success_d 0x4
- #define controller_rule_rerun_is_success_reset_d 0x8
-
- typedef struct {
- uint8_t is;
-
- controller_rule_rerun_item_t failure;
- controller_rule_rerun_item_t success;
- } controller_rule_rerun_t;
-
- #define controller_rule_rerun_initialize { \
- 0, \
- controller_rule_rerun_item_initialize, \
- controller_rule_rerun_item_initialize, \
- }
-#endif // _di_controller_rule_rerun_t_
-
-/**
- * A Rule Action.
- *
- * controller_rule_action_method_*:
- * - extended: Designate that this Action is represented using FSS Extended.
- * - extended_list: Designate that this Action is represented using FSS Extended List.
- *
- * type: The Rule Action type.
- * line: The line number where the Rule Action begins.
- * status: The last execution status of the Rule Action.
- * parameters: All parameters associated with the Rule Action.
- */
-#ifndef _di_controller_rule_action_t_
- #define CONTROLLER_rule_action_method_string_extended_s "FSS-0001 (Extended)"
- #define CONTROLLER_rule_action_method_string_extended_list_s "FSS-0003 (Extended List)"
-
- #define CONTROLLER_rule_action_method_string_extended_s_length 19
- #define CONTROLLER_rule_action_method_string_extended_list_s_length 24
-
- extern const f_string_static_t controller_rule_action_method_string_extended_s;
- extern const f_string_static_t controller_rule_action_method_string_extended_list_s;
-
- enum {
- controller_rule_action_method_extended_e = 1,
- controller_rule_action_method_extended_list_e,
- };
-
- typedef struct {
- uint8_t type;
- f_number_unsigned_t line;
- f_status_t status;
-
- f_string_dynamics_t parameters;
- f_iki_datas_t ikis;
- } controller_rule_action_t;
-
- #define controller_rule_action_t_initialize { \
- 0, \
- 0, \
- F_known_not, \
- f_string_dynamics_t_initialize, \
- f_iki_datas_t_initialize, \
- }
-#endif // _di_controller_rule_action_t_
-
-/**
- * The Rule Actions.
- *
- * array: An array of Rule Actions.
- * size: Total amount of allocated space.
- * used: Total number of allocated spaces used.
- */
-#ifndef _di_controller_rule_actions_t_
- typedef struct {
- controller_rule_action_t *array;
-
- f_number_unsigned_t size;
- f_number_unsigned_t used;
- } controller_rule_actions_t;
-
- #define controller_rule_actions_t_initialize { \
- 0, \
- 0, \
- 0, \
- }
-#endif // _di_controller_rule_actions_t_
-
-/**
- * A Rule Item.
- *
- * controller_rule_item_type_*:
- * - command: A Command to execute.
- * - script: A Script to execute.
- * - service: A Service to execute.
- * - setting: Settings associated with the Rule Item.
- * - utility: A Utility to execute.
- *
- * type: The type of the Rule Item.
- * with: A bitwise number representing execute "with" options.
- * line: The line number where the Rule Item begins.
- * reruns: An array designating rerun settings for each execution type available.
- * actions: The actions associated with the Rule Item.
- */
-#ifndef _di_controller_rule_item_t_
- typedef struct {
- uint8_t type;
- uint8_t with;
- f_number_unsigned_t line;
-
- f_string_dynamic_t pid_file;
- controller_rule_rerun_t reruns[controller_rule_action_execute_type__enum_size_e];
- controller_rule_actions_t actions;
- } controller_rule_item_t;
-
- #define controller_rule_item_t_initialize \
- { \
- 0, \
- 0, \
- 0, \
- f_string_dynamic_t_initialize, \
- { \
- controller_rule_rerun_t_initialize, \
- controller_rule_rerun_t_initialize, \
- controller_rule_rerun_t_initialize, \
- controller_rule_rerun_t_initialize, \
- controller_rule_rerun_t_initialize, \
- controller_rule_rerun_t_initialize, \
- controller_rule_rerun_t_initialize, \
- controller_rule_rerun_t_initialize, \
- controller_rule_rerun_t_initialize, \
- }, \
- controller_rule_actions_t_initialize, \
- }
-#endif // _di_controller_rule_item_t_
-
-/**
- * The Rule Items.
- *
- * array: An array of Rule Items.
- * size: Total amount of allocated space.
- * used: Total number of allocated spaces used.
- */
-#ifndef _di_controller_rule_items_t_
- typedef struct {
- controller_rule_item_t *array;
-
- f_number_unsigned_t size;
- f_number_unsigned_t used;
- } controller_rule_items_t;
-
- #define controller_rule_items_initialize { \
- 0, \
- 0, \
- 0, \
- }
-#endif // _di_controller_rule_items_t_
-
-/**
- * The Rule "on" values for designating dependencies.
- *
- * action: The Rule Action type this "on" dependencies are associated with.
- * need: The Rule Alias for a required Rule.
- * want: The Rule Alias for an optional Rule that is required to succeed if found.
- * wish: The Rule Alias for an optional Rule that is not required.
- */
-#ifndef _di_controller_rule_on_t_
- typedef struct {
- uint8_t action;
-
- f_string_dynamics_t need;
- f_string_dynamics_t want;
- f_string_dynamics_t wish;
- } controller_rule_on_t;
-
- #define controller_rule_on_initialize { \
- 0, \
- f_string_dynamics_t_initialize, \
- f_string_dynamics_t_initialize, \
- f_string_dynamics_t_initialize, \
- }
-#endif // _di_controller_rule_on_t_
-
-/**
- * The Rule "on" array.
- *
- * array: An array of Rule "on" values.
- * size: Total amount of allocated space.
- * used: Total number of allocated spaces used.
- */
-#ifndef _di_controller_rule_ons_t_
- typedef struct {
- controller_rule_on_t *array;
-
- f_number_unsigned_t size;
- f_number_unsigned_t used;
- } controller_rule_ons_t;
-
- #define controller_rule_ons_t_initialize { \
- 0, \
- 0, \
- 0, \
- }
-#endif // _di_controller_rule_ons_t_
-
-/**
- * A Rule.
- *
- * controller_rule_setting_type_*:
- * - affinity: Setting type representing a affinity.
- * - capability: Setting type representing a capability.
- * - cgroup: Setting type representing a control group.
- * - define: Setting type representing a define.
- * - engine: Setting type representing a engine.
- * - engine_arguments: Setting type representing a engine.
- * - environment: Setting type representing a environment.
- * - group: Setting type representing a group.
- * - limit: Setting type representing a limit.
- * - name: Setting type representing a name.
- * - nice: Setting type representing a nice.
- * - on: Setting type representing a on.
- * - parameter: Setting type representing a parameter.
- * - path: Setting type representing a path.
- * - scheduler: Setting type representing a scheduler.
- * - user: Setting type representing a user.
- *
- * controller_rule_has_*:
- * - cgroup: Has type representing a control group.
- * - group: Has type representing a group.
- * - nice: Has type representing a nice.
- * - scheduler: Has type representing a scheduler.
- * - user: Has type representing a user.
- *
- * affinity: The cpu affinity to be used when executing the Rule.
- * alias: The distinct ID (machine name) of the Rule, such as "service/ssh".
- * capability: The capability setting if the Rule "has" a capability.
- * cgroup: The control group setting if the Rule "has" a control group.
- * define: Any defines (environment variables) made available to the Rule for IKI substitution or just as environment variables.
- * engine: The program or path to the program of the scripting engine to use when processing scripts in this Rule.
- * engine_arguments: Any arguments to pass to the engine program.
- * environment: All environment variables allowed to be exposed to the Rule when processing.
- * group: The group ID if the Rule "has" a group.
- * groups: A set of group IDs to run the process with (first specified group is the primary group).
- * has: Bitwise set of "has" codes representing what the Rule has.
- * items: All items associated with the Rule.
- * limits: The cpu/resource limits to use when executing the Rule.
- * name: A human name for the Rule (does not have to be distinct), such as "Bash Script".
- * nice: The niceness value if the Rule "has" nice.
- * on: A set of parameters for defining dependencies and how they are needed, wanted, or wished for.
- * parameter: Any parameters made available to the Rule for IKI substitution.
- * path: The path to the Rule file.
- * scheduler: The scheduler setting if the Rule "has" a scheduler.
- * status: A set of action-specific success/failure status of the Rule. Each index represents a controller_rule_action_type_* enum value. Index 0 represents a global status.
- * timeout_exit: The timeout to wait when exiting the Controller program after sending the terminate signal to send the kill signal.
- * timeout_kill: The timeout to wait relating to using a kill signal.
- * timeout_start: The timeout to wait relating to starting a process.
- * timeout_stop: The timeout to wait relating to stopping a process.
- * timestamp: The timestamp when the Rule was loaded.
- * user: The User ID if the Rule "has" a user.
- */
-#ifndef _di_controller_rule_t_
- enum {
- controller_rule_setting_type_affinity_e = 1,
- controller_rule_setting_type_capability_e,
- controller_rule_setting_type_cgroup_e,
- controller_rule_setting_type_define_e,
- controller_rule_setting_type_engine_e,
- controller_rule_setting_type_environment_e,
- controller_rule_setting_type_group_e,
- controller_rule_setting_type_limit_e,
- controller_rule_setting_type_name_e,
- controller_rule_setting_type_nice_e,
- controller_rule_setting_type_on_e,
- controller_rule_setting_type_parameter_e,
- controller_rule_setting_type_path_e,
- controller_rule_setting_type_scheduler_e,
- controller_rule_setting_type_timeout_e,
- controller_rule_setting_type_user_e,
- };
-
- // bitwise codes representing properties on controller_rule_t that have been found in the Rule file.
- #define controller_rule_has_cgroup_d 0x1
- #define controller_rule_has_environment_d 0x2
- #define controller_rule_has_group_d 0x4
- #define controller_rule_has_nice_d 0x8
- #define controller_rule_has_scheduler_d 0x10
- #define controller_rule_has_user_d 0x20
-
- // Designate codes for timeout settings to be used during the loading of the Rule timeout settings.
- #define controller_rule_timeout_code_kill_d 1
- #define controller_rule_timeout_code_start_d 2
- #define controller_rule_timeout_code_stop_d 3
-
- typedef struct {
- f_status_t status[controller_rule_action_type__enum_size_e];
-
- f_number_unsigned_t timeout_kill;
- f_number_unsigned_t timeout_start;
- f_number_unsigned_t timeout_stop;
-
- uint8_t has;
- int nice;
- uid_t user;
- gid_t group;
-
- f_time_simple_t timestamp;
-
- f_string_dynamic_t alias;
- f_string_dynamic_t engine;
- f_string_dynamic_t name;
- f_string_dynamic_t path;
-
- f_string_maps_t define;
- f_string_maps_t parameter;
-
- f_string_dynamics_t engine_arguments;
- f_string_dynamics_t environment;
-
- f_int32s_t affinity;
- f_capability_t capability;
- f_control_group_t cgroup;
- f_int32s_t groups;
- f_limit_sets_t limits;
- f_execute_scheduler_t scheduler;
-
- controller_rule_ons_t ons;
- controller_rule_items_t items;
- } controller_rule_t;
-
- #define controller_rule_t_initialize { \
- { \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- F_known_not, \
- }, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- f_time_simple_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_maps_t_initialize, \
- f_string_maps_t_initialize, \
- f_string_dynamics_t_initialize, \
- f_string_dynamics_t_initialize, \
- f_int32s_t_initialize, \
- f_capability_t_initialize, \
- f_control_group_t_initialize, \
- f_int32s_t_initialize, \
- f_limit_sets_t_initialize, \
- f_execute_scheduler_t_initialize, \
- controller_rule_ons_initialize, \
- controller_rule_items_initialize, \
- }
-#endif // _di_controller_rule_t_
-
-/**
- * The Rules.
- *
- * array: An array of Rules.
- * size: Total amount of allocated space.
- * used: Total number of allocated spaces used.
- */
-#ifndef _di_controller_rules_t_
- typedef struct {
- controller_rule_t *array;
-
- f_number_unsigned_t size;
- f_number_unsigned_t used;
- } controller_rules_t;
-
- #define controller_rules_t_initialize { \
- 0, \
- 0, \
- 0, \
- }
-#endif // _di_controller_rules_t_
-
-/**
- * The process specific settings.
- *
- * controller_setting_ready_*:
- * - no: Entry/Exit is not ready.
- * - wait: Entry/Exit has "ready" somewhere in the file but is not yet ready.
- * - yes: Entry/Exit is now ready (Entry/Exit is still being processed).
- * - done: Entry/Exit is ready and processing is complete.
- * - fail: Entry/Exit processing failed.
- * - abort: Abort received before finished processing Entry/Exit.
- *
- * controller_setting_mode_*:
- * - helper: Run as a helper, exiting when finished prrocess entry (and any respective exit).
- * - program: Run as a program, exiting when finished prrocess entry (and any respective exit).
- * - service: Run as a service, listening for requests after processing entry.
- *
- * controller_setting_flag_*:
- * - interruptible: When specified, program responds to interrupt signals, otherwise block/ignore interrupt signals.
- * - pid_created: When specified, the program responds to interrupt signals, otherwise block/ignore interrupt signals.
- * - failsafe: When specified, failsafe mode is enabled, otherwise failsafe mode is disabled.
- *
- * flag: Flags from controller_setting_flag_*.
- * ready: State representing if the settings are all loaded and is ready to run program operations.
- * mode: Controller setting mode based on the setting mode enumerator.
- * control: The control socket data.
- * failsafe_item_id: The Entry Item ID to execute when failsafe execution is enabled.
- * path_cgroup: Directory path to the cgroup directory.
- * path_control: File path to the control socket (used for printing the path).
- * path_pid: File path to the PID file.
- * path_setting: File path to the setting directory.
- * entry: The Entry settings.
- * rules: All rules and their respective settings.
- */
-#ifndef _di_controller_process_t_
- enum {
- controller_setting_ready_no_e = 0,
- controller_setting_ready_wait_e,
- controller_setting_ready_yes_e,
- controller_setting_ready_done_e,
- controller_setting_ready_fail_e,
- controller_setting_ready_abort_e,
- }; // enum
-
- enum {
- controller_setting_mode_service_e = 0,
- controller_setting_mode_helper_e,
- controller_setting_mode_program_e,
- }; // enum
-
- enum {
- controller_setting_flag_interruptible_e = 0x1,
- controller_setting_flag_pid_created_e = 0x2,
- controller_setting_flag_failsafe_e = 0x4,
- }; // enum
-
- typedef struct {
- uint8_t flag;
- uint8_t ready;
- uint8_t mode;
-
- f_number_unsigned_t failsafe_item_id;
-
- controller_control_t control;
-
- f_string_dynamic_t path_cgroup;
- f_string_dynamic_t path_control;
- f_string_dynamic_t path_current;
- f_string_dynamic_t path_pid;
- f_string_dynamic_t path_setting;
-
- f_string_dynamic_t name_entry;
-
- controller_entry_t entry;
- controller_entry_t exit;
- controller_rules_t rules;
- } controller_process_t;
-
- #define controller_process_t_initialize { \
- 0, \
- 0, \
- 0, \
- 0, \
- controller_control_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- controller_entry_t_initialize, \
- controller_entry_t_initialize, \
- controller_rules_t_initialize, \
- }
-#endif // _di_controller_process_t_
-
-/**
- * The main program data as a single structure.
- *
- * program: The main program data.
- * setting: The settings data.
- *
- * process: The active process information.
- */
-#ifndef _di_controller_main_t_
- typedef struct {
- fll_program_data_t program;
- controller_setting_t setting;
-
- controller_process_t *process;
- } controller_main_t;
-
- #define controller_main_t_initialize \
- { \
- fll_program_data_t_initialize, \
- controller_setting_t_initialize, \
- 0, \
- }
-#endif // _di_controller_main_t_
-
-/**
- * De-allocate main program data.
- *
- * @param main
- * The main program data.
- *
- * This does not alter main.setting.state.status.
- *
- * @return
- * F_okay on success.
- *
- * F_parameter (with error bit) if a parameter is invalid.
- */
-#ifndef _di_controller_main_delete_
- extern f_status_t controller_main_delete(controller_main_t * const main);
-#endif // _di_controller_main_delete_
-
-/**
- * Delete the controller control data.
- *
- * @param control
- * The controller control data.
- *
- * @return
- * F_okay on success.
- *
- * F_parameter (with error bit) if a parameter is invalid.
- */
-#ifndef _di_controller_control_delete_
- extern f_status_t controller_control_delete(controller_control_t * const control);
-#endif // _di_controller_control_delete_
-
-/**
- * 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_controller_control_payload_type_identify_
- extern uint8_t controller_control_payload_type_identify(const f_string_static_t payload);
-#endif // _di_controller_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_controller_control_payload_type_name_
- extern f_string_static_t controller_control_payload_type_name(const uint8_t type);
-#endif // _di_controller_control_payload_type_name_
-
-/**
- * Identify the entry action code the given name represents.
- *
- * @param action
- * The string representing an entry action.
- *
- * @return
- * The entry action type code on success.
- * 0 if name is unknown.
- */
-#ifndef _di_controller_entry_action_type_identify_
- extern uint8_t controller_entry_action_type_identify(const f_string_static_t action);
-#endif // _di_controller_entry_action_type_identify_
-
-/**
- * Get a string representing the entry action type.
- *
- * @param type
- * The entry action type code.
- *
- * @return
- * The string with used > 0 on success.
- * The string with used == 0 if no match was found.
- */
-#ifndef _di_controller_entry_action_type_name_
- extern f_string_static_t controller_entry_action_type_name(const uint8_t type);
-#endif // _di_controller_entry_action_type_name_
-
-/**
- * Delete the controller process data.
- *
- * @param process
- * The controller process data.
- *
- * @return
- * F_okay on success.
- *
- * F_parameter (with error bit) if a parameter is invalid.
- */
-#ifndef _di_controller_process_delete_
- extern f_status_t controller_process_delete(controller_process_t * const process);
-#endif // _di_controller_process_delete_
-
-/**
- * Identify the rule action code the given name represents.
- *
- * @param action
- * The string representing an rule action.
- *
- * @return
- * The rule action type code on success.
- * 0 if name is unknown.
- */
-#ifndef _di_controller_rule_action_type_identify_
- extern uint8_t controller_rule_action_type_identify(const f_string_static_t action);
-#endif // _di_controller_rule_action_type_identify_
-
-/**
- * Get a string representing the rule action type.
- *
- * @param type
- * The rule action type code.
- *
- * @return
- * The string with used > 0 on success.
- * The string with used == 0 if no match was found.
- */
-#ifndef _di_controller_rule_action_type_name_
- extern f_string_static_t controller_rule_action_type_name(const uint8_t type);
-#endif // _di_controller_rule_action_type_name_
-
-/**
- * Identify the rule action execute code the given name represents.
- *
- * @param action
- * The string representing an rule action execute.
- *
- * @return
- * The rule action execute type code on success.
- * controller_rule_action_execute_type__enum_size_e if name is unknown.
- */
-#ifndef _di_controller_rule_action_execute_type_identify_
- extern uint8_t controller_rule_action_execute_type_identify(const f_string_static_t action);
-#endif // _di_controller_rule_action_execute_type_identify_
-
-/**
- * Get a string representing the rule action execute type.
- *
- * @param type
- * The rule action type execute code.
- *
- * @return
- * The string with used > 0 on success.
- * The string with used == 0 if no match was found.
- */
-#ifndef _di_controller_rule_action_execute_type_name_
- extern f_string_static_t controller_rule_action_execute_type_name(const uint8_t type);
-#endif // _di_controller_rule_action_execute_type_name_
-
-/**
- * Identify the rule item code the given name represents.
- *
- * @param item
- * The string representing an rule action.
- *
- * @return
- * The rule item type code on success.
- * 0 if name is unknown.
- */
-#ifndef _di_controller_rule_item_type_identify_
- extern uint8_t controller_rule_item_type_identify(const f_string_static_t item);
-#endif // _di_controller_rule_item_type_identify_
-
-/**
- * Get a string representing the rule item type.
- *
- * @param type
- * The rule item type code.
- *
- * @return
- * The string with used > 0 on success.
- * The string with used == 0 if no match was found.
- */
-#ifndef _di_controller_rule_item_type_name_
- extern f_string_static_t controller_rule_item_type_name(const uint8_t type);
-#endif // _di_controller_rule_item_type_name_
-
-/**
- * Identify the rule item code the given name represents.
- *
- * @param item
- * The string representing an rule action.
- *
- * @return
- * The rule item type code on success.
- * 0 if name is unknown.
- */
-#ifndef _di_controller_rule_setting_limit_type_identify_
- extern uint8_t controller_rule_setting_limit_type_identify(const f_string_static_t item);
-#endif // _di_controller_rule_setting_limit_type_identify_
-
-/**
- * Get a string representing the rule setting limit type.
- *
- * @param type
- * The rule setting limit type code.
- *
- * @return
- * The string with used > 0 on success.
- * The string with used == 0 if no match was found.
- */
-#ifndef _di_controller_rule_setting_limit_type_name_
- extern f_string_static_t controller_rule_setting_limit_type_name(const uint8_t type);
-#endif // di_controller_rule_setting_limit_type_name_
-
-/**
- * Delete the program main setting data.
- *
- * @param setting
- * The program main setting data.
- *
- * This does not alter setting.state.status.
- *
- * @return
- * F_okay on success.
- *
- * F_parameter (with error bit) if a parameter is invalid.
- */
-#ifndef _di_controller_setting_delete_
- extern f_status_t controller_setting_delete(controller_setting_t * const setting);
-#endif // _di_controller_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.
- *
- * This alters main.setting.state.status:
- * F_okay 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_controller_setting_load_
- extern void controller_setting_load(const f_console_arguments_t arguments, controller_main_t * const main);
-#endif // _di_controller_setting_load_
-
-/**
- * Fully de-allocate all memory for the given entry action without caring about return status.
- *
- * @param action
- * The action to de-allocate.
- *
- * @see f_memory_arrays_resize()
- *
- * @return
- * F_okay on success.
- *
- * F_parameter (with error bit) if a parameter is invalid.
- */
-#ifndef _di_controller_entry_action_delete_
- extern f_status_t controller_entry_action_delete(controller_entry_action_t * const action);
-#endif // _di_controller_entry_action_delete_
-
-/**
- * Fully de-allocate all memory for the given entry actions without caring about return status.
- *
- * @param actions
- * The entry_actions to de-allocate.
- *
- * @return
- * F_okay on success.
- *
- * F_parameter (with error bit) if a parameter is invalid.
- *
- * @see controller_entry_action_delete()
- * @see f_memory_delete()
- */
-#ifndef _di_controller_entry_actions_delete_
- extern f_status_t controller_entry_actions_delete(controller_entry_actions_t * const actions);
-#endif // _di_controller_entry_actions_delete_
-
-/**
- * Increase the size of the entry item actions array by the specified amount, but only if necessary.
- *
- * This only increases size if the current used plus amount is greater than the currently allocated size.
- *
- * @param amount
- * A positive number representing how much to increase the size by.
- * @param actions
- * The entry item actions to resize.
- *
- * @return
- * F_okay on success.
- * F_array_too_large (with error bit) if the resulting new size is bigger than the max array length.
- *
- * Errors (with error bit) from: f_memory_resize().
- *
- * @see f_memory_resize()
- */
-#ifndef _di_controller_entry_actions_increase_by_
- extern f_status_t controller_entry_actions_increase_by(const f_number_unsigned_t amount, controller_entry_actions_t * const actions);
-#endif // _di_controller_entry_actions_increase_by_
-
-/**
- * Fully de-allocate all memory for the given entry item without caring about return status.
- *
- * @param item
- * The item to de-allocate.
- *
- * @return
- * F_okay on success.
- *
- * F_parameter (with error bit) if a parameter is invalid.
- *
- * @see f_memory_array_resize()
- */
-#ifndef _di_controller_entry_item_delete_
- extern f_status_t controller_entry_item_delete(controller_entry_item_t * const item);
-#endif // _di_controller_entry_item_delete_
-
-/**
- * Fully de-allocate all memory for the given entry items without caring about return status.
- *
- * @param items
- * The entry_items to de-allocate.
- *
- * @return
- * F_okay on success.
- *
- * F_parameter (with error bit) if a parameter is invalid.
- *
- * @see controller_entry_item_delete()
- * @see f_memory_delete()
- */
-#ifndef _di_controller_entry_items_delete_
- extern f_status_t controller_entry_items_delete(controller_entry_items_t * const items);
-#endif // _di_controller_entry_items_delete_
-
-/**
- * Increase the size of the entry items array by the specified amount, but only if necessary.
- *
- * This only increases size if the current used plus amount is greater than the currently allocated size.
- *
- * @param amount
- * A positive number representing how much to increase the size by.
- * @param items
- * The entry items to resize.
- *
- * @return
- * F_okay on success.
- * F_array_too_large (with error bit) if the resulting new size is bigger than the max array length.
- *
- * Errors (with error bit) from: f_memory_resize().
- *
- * @see f_memory_resize()
- */
-#ifndef _di_controller_entry_items_increase_by_
- extern f_status_t controller_entry_items_increase_by(const f_number_unsigned_t amount, controller_entry_items_t * const items);
-#endif // _di_controller_entry_items_increase_by_
-
-/**
- * Fully de-allocate all memory for the given Rule Action without caring about return status.
- *
- * @param action
- * The action to de-allocate.
- *
- * @see f_memory_arrays_resize()
- */
-#ifndef _di_controller_rule_action_delete_
- extern void controller_rule_action_delete(controller_rule_action_t * const action);
-#endif // _di_controller_rule_action_delete_
-
-/**
- * Fully de-allocate all memory for the given Rule Actions without caring about return status.
- *
- * @param actions
- * The rule_actions to de-allocate.
- *
- * @see controller_rule_action_delete()
- * @see f_memory_delete()
- */
-#ifndef _di_controller_rule_actions_delete_
- extern void controller_rule_actions_delete(controller_rule_actions_t * const actions);
-#endif // _di_controller_rule_actions_delete_
-
-/**
- * Increase the size of the Rule Actions array by the specified amount, but only if necessary.
- *
- * This only increases size if the current used plus amount is greater than the currently allocated size.
- *
- * @param amount
- * A positive number representing how much to increase the size by.
- * @param actions
- * The actions to resize.
- *
- * @return
- * F_okay on success.
- * F_array_too_large (with error bit) if the resulting new size is bigger than the max array length.
- *
- * Errors (with error bit) from: f_memory_resize().
- */
-#ifndef _di_controller_rule_actions_increase_by_
- extern f_status_t controller_rule_actions_increase_by(const f_number_unsigned_t amount, controller_rule_actions_t * const actions);
-#endif // _di_controller_rule_actions_increase_by_
-
-/**
- * Fully de-allocate all memory for the given Rule without caring about return status.
- *
- * @param rule
- * The rule to de-allocate.
- *
- * @see controller_rule_items_delete()
- * @see f_capability_delete()
- * @see f_memory_array_resize()
- * @see f_memory_arrays_resize()
- */
-#ifndef _di_controller_rule_delete_
- extern void controller_rule_delete(controller_rule_t * const rule);
-#endif // _di_controller_rule_delete_
-
-/**
- * Fully de-allocate all memory for the given Rule Item without caring about return status.
- *
- * @param item
- * The item to de-allocate.
- *
- * @see f_memory_array_resize()
- */
-#ifndef _di_controller_rule_item_delete_
- extern void controller_rule_item_delete(controller_rule_item_t * const item);
-#endif // _di_controller_rule_item_delete_
-
-/**
- * Fully de-allocate all memory for the given Rule Items without caring about return status.
- *
- * @param items
- * The rule_items to de-allocate.
- *
- * @see controller_rule_item_delete()
- * @see f_memory_delete()
- */
-#ifndef _di_controller_rule_items_delete_
- extern void controller_rule_items_delete(controller_rule_items_t * const items);
-#endif // _di_controller_rule_items_delete_
-
-/**
- * Fully de-allocate all memory for the given Rule Item without caring about return status.
- *
- * @param on
- * The on to de-allocate.
- *
- * @see f_memory_array_resize()
- */
-#ifndef _di_controller_rule_on_delete_
- extern void controller_rule_on_delete(controller_rule_on_t * const on);
-#endif // _di_controller_rule_on_delete_
-
-/**
- * Fully de-allocate all memory for the given Rule Items without caring about return status.
- *
- * @param ons
- * The rule_ons to de-allocate.
- *
- * @see controller_rule_on_delete()
- * @see f_memory_delete()
- */
-#ifndef _di_controller_rule_ons_delete_
- extern void controller_rule_ons_delete(controller_rule_ons_t * const ons);
-#endif // _di_controller_rule_ons_delete_
-
-/**
- * Increase the size of the Rule array, but only if necessary.
- *
- * If the given length is too large for the buffer, then attempt to set max buffer size (F_number_t_size_unsigned_d).
- * If already set to the maximum buffer size, then the resize will fail.
- *
- * @param ons
- * The on array to resize.
- *
- * @return
- * F_okay on success.
- * F_data_not on success, but there is no reason to increase size (used + controller_common_allocation_small_d <= size).
- *
- * F_array_too_large (with error bit) if the new array length is too large.
- * F_memory_not (with error bit) on out of memory.
- * F_parameter (with error bit) if a parameter is invalid.
- *
- * @see controller_rule_ons_resize()
- */
-#ifndef _di_controller_rule_ons_increase_
- extern f_status_t controller_rule_ons_increase(controller_rule_ons_t * const ons);
-#endif // _di_controller_rule_increase_
-
-/**
- * Resize the Rule array.
- *
- * @param length
- * The new size to use.
- * @param ons
- * The on array to resize.
- *
- * @return
- * F_okay on success.
- *
- * F_memory_not (with error bit) on out of memory.
- * F_parameter (with error bit) if a parameter is invalid.
- *
- * @see f_memory_resize()
- */
-#ifndef _di_controller_rule_ons_resize_
- extern f_status_t controller_rule_ons_resize(const f_number_unsigned_t length, controller_rule_ons_t * const ons);
-#endif // _di_controller_rule_ons_resize_
-
-/**
- * Fully de-allocate all memory for the given Rules without caring about return status.
- *
- * @param rules
- * The rules to de-allocate.
- *
- * @see controller_rules_resize()
- */
-#ifndef _di_controller_rules_delete_
- extern void controller_rules_delete(controller_rules_t * const rules);
-#endif // _di_controller_rules_delete_
-
-/**
- * Increase the size of the Rule array, but only if necessary.
- *
- * If the given length is too large for the buffer, then attempt to set max buffer size (F_number_t_size_unsigned_d).
- * If already set to the maximum buffer size, then the resize will fail.
- *
- * @param rules
- * The rule array to resize.
- *
- * @return
- * F_okay on success.
- * F_data_not on success, but there is no reason to increase size (used + controller_common_allocation_small_d <= size).
- *
- * F_array_too_large (with error bit) if the new array length is too large.
- * F_memory_not (with error bit) on out of memory.
- * F_parameter (with error bit) if a parameter is invalid.
- *
- * @see controller_rules_resize()
- */
-#ifndef _di_controller_rules_increase_
- extern f_status_t controller_rules_increase(controller_rules_t * const rules);
-#endif // _di_controller_rule_increase_
-
-/**
- * Resize the Rule array.
- *
- * @param length
- * The new size to use.
- * @param rules
- * The rule array to resize.
- *
- * @return
- * F_okay on success.
- *
- * F_memory_not (with error bit) on out of memory.
- * F_parameter (with error bit) if a parameter is invalid.
- *
- * @see f_memory_resize()
- */
-#ifndef _di_controller_rules_resize_
- extern f_status_t controller_rules_resize(const f_number_unsigned_t length, controller_rules_t * const rules);
-#endif // _di_controller_rules_resize_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _controller_common_h
+++ /dev/null
-#include "../controller.h"
-#include "private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_cache_action_delete_simple_
- void controller_cache_action_delete_simple(controller_cache_action_t * const cache) {
-
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &cache->name_action.string, &cache->name_action.used, &cache->name_action.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &cache->name_file.string, &cache->name_file.used, &cache->name_file.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &cache->name_item.string, &cache->name_item.used, &cache->name_item.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &cache->generic.string, &cache->generic.used, &cache->generic.size);
- }
-#endif // _di_controller_cache_action_delete_simple_
-
-#ifndef _di_controller_cache_delete_simple_
- void controller_cache_delete_simple(controller_cache_t * const cache) {
-
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &cache->buffer_file.string, &cache->buffer_file.used, &cache->buffer_file.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &cache->buffer_item.string, &cache->buffer_item.used, &cache->buffer_item.size);
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &cache->buffer_path.string, &cache->buffer_path.used, &cache->buffer_path.size);
-
- f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &cache->expanded.array, &cache->expanded.used, &cache->expanded.size, &f_string_dynamics_delete_callback);
-
- f_memory_array_resize(0, sizeof(f_number_unsigned_t), (void **) &cache->ats.array, &cache->ats.used, &cache->ats.size);
- f_memory_array_resize(0, sizeof(f_number_unsigned_t), (void **) &cache->stack.array, &cache->stack.used, &cache->stack.size);
- f_memory_array_resize(0, sizeof(f_number_unsigned_t), (void **) &cache->delimits.array, &cache->delimits.used, &cache->delimits.size);
-
- f_memory_array_resize(0, sizeof(f_range_t), (void **) &cache->comments.array, &cache->comments.used, &cache->comments.size);
- f_memory_array_resize(0, sizeof(f_range_t), (void **) &cache->content_action.array, &cache->content_action.used, &cache->content_action.size);
- f_memory_array_resize(0, sizeof(f_range_t), (void **) &cache->object_actions.array, &cache->object_actions.used, &cache->object_actions.size);
- f_memory_array_resize(0, sizeof(f_range_t), (void **) &cache->object_items.array, &cache->object_items.used, &cache->object_items.size);
-
- f_memory_arrays_resize(0, sizeof(f_ranges_t), (void **) &cache->content_actions.array, &cache->content_actions.used, &cache->content_actions.size, &f_rangess_delete_callback);
- f_memory_arrays_resize(0, sizeof(f_ranges_t), (void **) &cache->content_items.array, &cache->content_items.used, &cache->content_items.size, &f_rangess_delete_callback);
-
- controller_cache_action_delete_simple(&cache->action);
- }
-#endif // _di_controller_cache_delete_simple_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_common_cache_h
-#define _PRIVATE_common_cache_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Action related cache.
- *
- * line_action: The line in some file representing an Action.
- * line_item: The line in some file representing an Item.
- * name_action: A NULL terminated name of some Action.
- * name_file: A NULL terminated name of some File.
- * name_item: A NULL terminated name of some Item.
- * generic: A NULL terminated string for general use.
- */
-#ifndef _di_controller_cache_action_t_
- typedef struct {
- f_number_unsigned_t line_action;
- f_number_unsigned_t line_item;
-
- f_string_dynamic_t name_action;
- f_string_dynamic_t name_file;
- f_string_dynamic_t name_item;
-
- f_string_dynamic_t generic;
- } controller_cache_action_t;
-
- #define controller_cache_action_t_initialize { \
- 0, \
- 0, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- }
-
- #define macro_controller_cache_action_t_clear(cache) \
- cache.line_action = 0; \
- cache.line_item = 0; \
- macro_f_string_dynamic_t_clear(cache.name_action) \
- macro_f_string_dynamic_t_clear(cache.name_file) \
- macro_f_string_dynamic_t_clear(cache.name_item) \
- macro_f_string_dynamic_t_clear(cache.generic)
-#endif // _di_controller_cache_action_t_
-
-/**
- * A cache intended for re-using memory while loading and processing rules whenever possible.
- *
- * timestamp: The timestamp.
- * range_action: The Range for some Action.
- * ats: Locations.
- * stack: Locations within a items history used as a history stack for circular recursion prevention.
- * comments: Comments associated with a buffer string.
- * delimits: Delimits associated with a buffer string.
- * content_action: The specific Content for some Action.
- * content_actions: Content for some Action.
- * content_items: Content for some Item.
- * object_actions: Objects for some Action.
- * object_items: Objects for some Item.
- * buffer_file: A generic file related buffer.
- * buffer_item: A generic item related buffer.
- * buffer_path: A generic path related buffer.
- * expanded: An array of expanded strings, generally used by the execute functions.
- * action: A cache for some Action, often used by error printing for reporting where an error happened.
- */
-#ifndef _di_controller_cache_t_
- typedef struct {
- f_time_simple_t timestamp;
-
- f_range_t range_action;
-
- f_number_unsigneds_t ats;
- f_number_unsigneds_t stack;
-
- f_ranges_t comments;
- f_number_unsigneds_t delimits;
-
- f_ranges_t content_action;
- f_rangess_t content_actions;
- f_rangess_t content_items;
- f_ranges_t object_actions;
- f_ranges_t object_items;
-
- f_string_dynamic_t buffer_file;
- f_string_dynamic_t buffer_item;
- f_string_dynamic_t buffer_path;
-
- f_string_dynamics_t expanded;
-
- controller_cache_action_t action;
- } controller_cache_t;
-
- #define controller_cache_t_initialize { \
- f_time_simple_t_initialize, \
- f_range_t_initialize, \
- f_number_unsigneds_t_initialize, \
- f_number_unsigneds_t_initialize, \
- f_ranges_t_initialize, \
- f_number_unsigneds_t_initialize, \
- f_ranges_t_initialize, \
- f_rangess_t_initialize, \
- f_rangess_t_initialize, \
- f_ranges_t_initialize, \
- f_ranges_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamic_t_initialize, \
- f_string_dynamics_t_initialize, \
- controller_cache_action_t_initialize, \
- }
-#endif // _di_controller_cache_t_
-
-/**
- * Fully de-allocate all memory for the given cache without caring about return status.
- *
- * @param cache
- * The cache to de-allocate.
- *
- * @see f_memory_array_resize()
- */
-#ifndef _di_controller_cache_action_delete_simple_
- extern void controller_cache_action_delete_simple(controller_cache_action_t * const cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_cache_action_delete_simple_
-
-/**
- * Fully de-allocate all memory for the given cache without caring about return status.
- *
- * @param cache
- * The cache to de-allocate.
- *
- * @see controller_cache_action_delete_simple()
- *
- * @see f_memory_array_resize()
- * @see f_memory_arrays_resize()
- */
-#ifndef _di_controller_cache_delete_simple_
- extern void controller_cache_delete_simple(controller_cache_t * const cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_cache_delete_simple_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_common_cache_h
+++ /dev/null
-#include "../controller.h"
-#include "private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_string_s_
- const f_string_static_t controller_action_s = macro_f_string_static_t_initialize_1(CONTROLLER_action_s, 0, CONTROLLER_action_s_length);
- const f_string_static_t controller_actions_s = macro_f_string_static_t_initialize_1(CONTROLLER_actions_s, 0, CONTROLLER_actions_s_length);
- const f_string_static_t controller_affinity_s = macro_f_string_static_t_initialize_1(CONTROLLER_affinity_s, 0, CONTROLLER_affinity_s_length);
- const f_string_static_t controller_as_s = macro_f_string_static_t_initialize_1(CONTROLLER_as_s, 0, CONTROLLER_as_s_length);
- const f_string_static_t controller_asynchronous_s = macro_f_string_static_t_initialize_1(CONTROLLER_asynchronous_s, 0, CONTROLLER_asynchronous_s_length);
- const f_string_static_t controller_bash_s = macro_f_string_static_t_initialize_1(CONTROLLER_bash_s, 0, CONTROLLER_bash_s_length);
- const f_string_static_t controller_batch_s = macro_f_string_static_t_initialize_1(CONTROLLER_batch_s, 0, CONTROLLER_batch_s_length);
- const f_string_static_t controller_capability_s = macro_f_string_static_t_initialize_1(CONTROLLER_capability_s, 0, CONTROLLER_capability_s_length);
- const f_string_static_t controller_cgroup_s = macro_f_string_static_t_initialize_1(CONTROLLER_cgroup_s, 0, CONTROLLER_cgroup_s_length);
- const f_string_static_t controller_create_s = macro_f_string_static_t_initialize_1(CONTROLLER_create_s, 0, CONTROLLER_create_s_length);
- const f_string_static_t controller_command_s = macro_f_string_static_t_initialize_1(CONTROLLER_command_s, 0, CONTROLLER_command_s_length);
- const f_string_static_t controller_consider_s = macro_f_string_static_t_initialize_1(CONTROLLER_consider_s, 0, CONTROLLER_consider_s_length);
- const f_string_static_t controller_control_s = macro_f_string_static_t_initialize_1(CONTROLLER_control_s, 0, CONTROLLER_control_s_length);
- const f_string_static_t controller_control_group_s = macro_f_string_static_t_initialize_1(CONTROLLER_control_group_s, 0, CONTROLLER_control_group_s_length);
- const f_string_static_t controller_control_has_s = macro_f_string_static_t_initialize_1(CONTROLLER_control_has_s, 0, CONTROLLER_control_has_s_length);
- const f_string_static_t controller_control_mode_s = macro_f_string_static_t_initialize_1(CONTROLLER_control_mode_s, 0, CONTROLLER_control_mode_s_length);
- const f_string_static_t controller_control_user_s = macro_f_string_static_t_initialize_1(CONTROLLER_control_user_s, 0, CONTROLLER_control_user_s_length);
- const f_string_static_t controller_controller_s = macro_f_string_static_t_initialize_1(CONTROLLER_controller_s, 0, CONTROLLER_controller_s_length);
- const f_string_static_t controller_cpu_s = macro_f_string_static_t_initialize_1(CONTROLLER_cpu_s, 0, CONTROLLER_cpu_s_length);
- const f_string_static_t controller_core_s = macro_f_string_static_t_initialize_1(CONTROLLER_core_s, 0, CONTROLLER_core_s_length);
- const f_string_static_t controller_data_s = macro_f_string_static_t_initialize_1(CONTROLLER_data_s, 0, CONTROLLER_data_s_length);
- const f_string_static_t controller_deadline_s = macro_f_string_static_t_initialize_1(CONTROLLER_deadline_s, 0, CONTROLLER_deadline_s_length);
- const f_string_static_t controller_default_s = macro_f_string_static_t_initialize_1(CONTROLLER_default_s, 0, CONTROLLER_default_s_length);
- const f_string_static_t controller_define_s = macro_f_string_static_t_initialize_1(CONTROLLER_define_s, 0, CONTROLLER_define_s_length);
- const f_string_static_t controller_delay_s = macro_f_string_static_t_initialize_1(CONTROLLER_delay_s, 0, CONTROLLER_delay_s_length);
- const f_string_static_t controller_directory_s = macro_f_string_static_t_initialize_1(CONTROLLER_directory_s, 0, CONTROLLER_directory_s_length);
- const f_string_static_t controller_disable_s = macro_f_string_static_t_initialize_1(CONTROLLER_disable_s, 0, CONTROLLER_disable_s_length);
- const f_string_static_t controller_engine_s = macro_f_string_static_t_initialize_1(CONTROLLER_engine_s, 0, CONTROLLER_engine_s_length);
- const f_string_static_t controller_entry_s = macro_f_string_static_t_initialize_1(CONTROLLER_entry_s, 0, CONTROLLER_entry_s_length);
- const f_string_static_t controller_entries_s = macro_f_string_static_t_initialize_1(CONTROLLER_entries_s, 0, CONTROLLER_entries_s_length);
- const f_string_static_t controller_environment_s = macro_f_string_static_t_initialize_1(CONTROLLER_environment_s, 0, CONTROLLER_environment_s_length);
- const f_string_static_t controller_error_s = macro_f_string_static_t_initialize_1(CONTROLLER_error_s, 0, CONTROLLER_error_s_length);
- const f_string_static_t controller_execute_s = macro_f_string_static_t_initialize_1(CONTROLLER_execute_s, 0, CONTROLLER_execute_s_length);
- const f_string_static_t controller_existing_s = macro_f_string_static_t_initialize_1(CONTROLLER_existing_s, 0, CONTROLLER_existing_s_length);
- const f_string_static_t controller_exit_s = macro_f_string_static_t_initialize_1(CONTROLLER_exit_s, 0, CONTROLLER_exit_s_length);
- const f_string_static_t controller_exits_s = macro_f_string_static_t_initialize_1(CONTROLLER_exits_s, 0, CONTROLLER_exits_s_length);
- const f_string_static_t controller_fail_s = macro_f_string_static_t_initialize_1(CONTROLLER_fail_s, 0, CONTROLLER_fail_s_length);
- const f_string_static_t controller_failsafe_s = macro_f_string_static_t_initialize_1(CONTROLLER_failsafe_s, 0, CONTROLLER_failsafe_s_length);
- const f_string_static_t controller_failure_s = macro_f_string_static_t_initialize_1(CONTROLLER_failure_s, 0, CONTROLLER_failure_s_length);
- const f_string_static_t controller_fifo_s = macro_f_string_static_t_initialize_1(CONTROLLER_fifo_s, 0, CONTROLLER_fifo_s_length);
- const f_string_static_t controller_file_s = macro_f_string_static_t_initialize_1(CONTROLLER_file_s, 0, CONTROLLER_file_s_length);
- const f_string_static_t controller_freeze_s = macro_f_string_static_t_initialize_1(CONTROLLER_freeze_s, 0, CONTROLLER_freeze_s_length);
- const f_string_static_t controller_fsize_s = macro_f_string_static_t_initialize_1(CONTROLLER_fsize_s, 0, CONTROLLER_fsize_s_length);
- const f_string_static_t controller_full_path_s = macro_f_string_static_t_initialize_1(CONTROLLER_full_path_s, 0, CONTROLLER_full_path_s_length);
- const f_string_static_t controller_group_s = macro_f_string_static_t_initialize_1(CONTROLLER_group_s, 0, CONTROLLER_group_s_length);
- const f_string_static_t controller_groups_s = macro_f_string_static_t_initialize_1(CONTROLLER_groups_s, 0, CONTROLLER_groups_s_length);
- const f_string_static_t controller_helper_s = macro_f_string_static_t_initialize_1(CONTROLLER_helper_s, 0, CONTROLLER_helper_s_length);
- const f_string_static_t controller_how_s = macro_f_string_static_t_initialize_1(CONTROLLER_how_s, 0, CONTROLLER_how_s_length);
- const f_string_static_t controller_idle_s = macro_f_string_static_t_initialize_1(CONTROLLER_idle_s, 0, CONTROLLER_idle_s_length);
- const f_string_static_t controller_iki_s = macro_f_string_static_t_initialize_1(CONTROLLER_iki_s, 0, CONTROLLER_iki_s_length);
- const f_string_static_t controller_item_s = macro_f_string_static_t_initialize_1(CONTROLLER_item_s, 0, CONTROLLER_item_s_length);
- const f_string_static_t controller_init_s = macro_f_string_static_t_initialize_1(CONTROLLER_init_s, 0, CONTROLLER_init_s_length);
- const f_string_static_t controller_kexec_s = macro_f_string_static_t_initialize_1(CONTROLLER_kexec_s, 0, CONTROLLER_kexec_s_length);
- const f_string_static_t controller_kill_s = macro_f_string_static_t_initialize_1(CONTROLLER_kill_s, 0, CONTROLLER_kill_s_length);
- const f_string_static_t controller_length_s = macro_f_string_static_t_initialize_1(CONTROLLER_length_s, 0, CONTROLLER_length_s_length);
- const f_string_static_t controller_limit_s = macro_f_string_static_t_initialize_1(CONTROLLER_limit_s, 0, CONTROLLER_limit_s_length);
- const f_string_static_t controller_locks_s = macro_f_string_static_t_initialize_1(CONTROLLER_locks_s, 0, CONTROLLER_locks_s_length);
- const f_string_static_t controller_main_s = macro_f_string_static_t_initialize_1(CONTROLLER_main_s, 0, CONTROLLER_main_s_length);
- const f_string_static_t controller_max_s = macro_f_string_static_t_initialize_1(CONTROLLER_max_s, 0, CONTROLLER_max_s_length);
- const f_string_static_t controller_memlock_s = macro_f_string_static_t_initialize_1(CONTROLLER_memlock_s, 0, CONTROLLER_memlock_s_length);
- const f_string_static_t controller_method_s = macro_f_string_static_t_initialize_1(CONTROLLER_method_s, 0, CONTROLLER_method_s_length);
- const f_string_static_t controller_mode_s = macro_f_string_static_t_initialize_1(CONTROLLER_mode_s, 0, CONTROLLER_mode_s_length);
- const f_string_static_t controller_msgqueue_s = macro_f_string_static_t_initialize_1(CONTROLLER_msgqueue_s, 0, CONTROLLER_msgqueue_s_length);
- const f_string_static_t controller_name_s = macro_f_string_static_t_initialize_1(CONTROLLER_name_s, 0, CONTROLLER_name_s_length);
- const f_string_static_t controller_need_s = macro_f_string_static_t_initialize_1(CONTROLLER_need_s, 0, CONTROLLER_need_s_length);
- const f_string_static_t controller_new_s = macro_f_string_static_t_initialize_1(CONTROLLER_new_s, 0, CONTROLLER_new_s_length);
- const f_string_static_t controller_nice_s = macro_f_string_static_t_initialize_1(CONTROLLER_nice_s, 0, CONTROLLER_nice_s_length);
- const f_string_static_t controller_no_s = macro_f_string_static_t_initialize_1(CONTROLLER_no_s, 0, CONTROLLER_no_s_length);
- const f_string_static_t controller_nofile_s = macro_f_string_static_t_initialize_1(CONTROLLER_nofile_s, 0, CONTROLLER_nofile_s_length);
- const f_string_static_t controller_normal_s = macro_f_string_static_t_initialize_1(CONTROLLER_normal_s, 0, CONTROLLER_normal_s_length);
- const f_string_static_t controller_nproc_s = macro_f_string_static_t_initialize_1(CONTROLLER_nproc_s, 0, CONTROLLER_nproc_s_length);
- const f_string_static_t controller_on_s = macro_f_string_static_t_initialize_1(CONTROLLER_on_s, 0, CONTROLLER_on_s_length);
- const f_string_static_t controller_optional_s = macro_f_string_static_t_initialize_1(CONTROLLER_optional_s, 0, CONTROLLER_optional_s_length);
- const f_string_static_t controller_other_s = macro_f_string_static_t_initialize_1(CONTROLLER_other_s, 0, CONTROLLER_other_s_length);
- const f_string_static_t controller_parameter_s = macro_f_string_static_t_initialize_1(CONTROLLER_parameter_s, 0, CONTROLLER_parameter_s_length);
- const f_string_static_t controller_parameters_s = macro_f_string_static_t_initialize_1(CONTROLLER_parameters_s, 0, CONTROLLER_parameters_s_length);
- const f_string_static_t controller_path_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_s, 0, CONTROLLER_path_s_length);
- const f_string_static_t controller_pause_s = macro_f_string_static_t_initialize_1(CONTROLLER_pause_s, 0, CONTROLLER_pause_s_length);
- const f_string_static_t controller_payload_type_s = macro_f_string_static_t_initialize_1(CONTROLLER_payload_type_s, 0, CONTROLLER_payload_type_s_length);
- const f_string_static_t controller_pid_s = macro_f_string_static_t_initialize_1(CONTROLLER_pid_s, 0, CONTROLLER_pid_s_length);
- const f_string_static_t controller_pid_file_s = macro_f_string_static_t_initialize_1(CONTROLLER_pid_file_s, 0, CONTROLLER_pid_file_s_length);
- const f_string_static_t controller_processor_s = macro_f_string_static_t_initialize_1(CONTROLLER_processor_s, 0, CONTROLLER_processor_s_length);
- const f_string_static_t controller_program_s = macro_f_string_static_t_initialize_1(CONTROLLER_program_s, 0, CONTROLLER_program_s_length);
- const f_string_static_t controller_readonly_s = macro_f_string_static_t_initialize_1(CONTROLLER_readonly_s, 0, CONTROLLER_readonly_s_length);
- const f_string_static_t controller_ready_s = macro_f_string_static_t_initialize_1(CONTROLLER_ready_s, 0, CONTROLLER_ready_s_length);
- const f_string_static_t controller_reboot_s = macro_f_string_static_t_initialize_1(CONTROLLER_reboot_s, 0, CONTROLLER_reboot_s_length);
- const f_string_static_t controller_reload_s = macro_f_string_static_t_initialize_1(CONTROLLER_reload_s, 0, CONTROLLER_reload_s_length);
- const f_string_static_t controller_require_s = macro_f_string_static_t_initialize_1(CONTROLLER_require_s, 0, CONTROLLER_require_s_length);
- const f_string_static_t controller_required_s = macro_f_string_static_t_initialize_1(CONTROLLER_required_s, 0, CONTROLLER_required_s_length);
- const f_string_static_t controller_rerun_s = macro_f_string_static_t_initialize_1(CONTROLLER_rerun_s, 0, CONTROLLER_rerun_s_length);
- const f_string_static_t controller_reset_s = macro_f_string_static_t_initialize_1(CONTROLLER_reset_s, 0, CONTROLLER_reset_s_length);
- const f_string_static_t controller_restart_s = macro_f_string_static_t_initialize_1(CONTROLLER_restart_s, 0, CONTROLLER_restart_s_length);
- const f_string_static_t controller_resume_s = macro_f_string_static_t_initialize_1(CONTROLLER_resume_s, 0, CONTROLLER_resume_s_length);
- const f_string_static_t controller_round_robin_s = macro_f_string_static_t_initialize_1(CONTROLLER_round_robin_s, 0, CONTROLLER_round_robin_s_length);
- const f_string_static_t controller_rss_s = macro_f_string_static_t_initialize_1(CONTROLLER_rss_s, 0, CONTROLLER_rss_s_length);
- const f_string_static_t controller_rtprio_s = macro_f_string_static_t_initialize_1(CONTROLLER_rtprio_s, 0, CONTROLLER_rtprio_s_length);
- const f_string_static_t controller_rttime_s = macro_f_string_static_t_initialize_1(CONTROLLER_rttime_s, 0, CONTROLLER_rttime_s_length);
- const f_string_static_t controller_rule_s = macro_f_string_static_t_initialize_1(CONTROLLER_rule_s, 0, CONTROLLER_rule_s_length);
- const f_string_static_t controller_rules_s = macro_f_string_static_t_initialize_1(CONTROLLER_rules_s, 0, CONTROLLER_rules_s_length);
- const f_string_static_t controller_same_s = macro_f_string_static_t_initialize_1(CONTROLLER_same_s, 0, CONTROLLER_same_s_length);
- const f_string_static_t controller_scheduler_s = macro_f_string_static_t_initialize_1(CONTROLLER_scheduler_s, 0, CONTROLLER_scheduler_s_length);
- const f_string_static_t controller_script_s = macro_f_string_static_t_initialize_1(CONTROLLER_script_s, 0, CONTROLLER_script_s_length);
- const f_string_static_t controller_service_s = macro_f_string_static_t_initialize_1(CONTROLLER_service_s, 0, CONTROLLER_service_s_length);
- const f_string_static_t controller_settings_s = macro_f_string_static_t_initialize_1(CONTROLLER_settings_s, 0, CONTROLLER_settings_s_length);
- const f_string_static_t controller_session_s = macro_f_string_static_t_initialize_1(CONTROLLER_session_s, 0, CONTROLLER_session_s_length);
- const f_string_static_t controller_session_new_s = macro_f_string_static_t_initialize_1(CONTROLLER_session_new_s, 0, CONTROLLER_session_new_s_length);
- const f_string_static_t controller_session_same_s = macro_f_string_static_t_initialize_1(CONTROLLER_session_same_s, 0, CONTROLLER_session_same_s_length);
- const f_string_static_t controller_show_s = macro_f_string_static_t_initialize_1(CONTROLLER_show_s, 0, CONTROLLER_show_s_length);
- const f_string_static_t controller_shutdown_s = macro_f_string_static_t_initialize_1(CONTROLLER_shutdown_s, 0, CONTROLLER_shutdown_s_length);
- const f_string_static_t controller_sigpending_s = macro_f_string_static_t_initialize_1(CONTROLLER_sigpending_s, 0, CONTROLLER_sigpending_s_length);
- const f_string_static_t controller_stack_s = macro_f_string_static_t_initialize_1(CONTROLLER_stack_s, 0, CONTROLLER_stack_s_length);
- const f_string_static_t controller_start_s = macro_f_string_static_t_initialize_1(CONTROLLER_start_s, 0, CONTROLLER_start_s_length);
- const f_string_static_t controller_status_s = macro_f_string_static_t_initialize_1(CONTROLLER_status_s, 0, CONTROLLER_status_s_length);
- const f_string_static_t controller_stop_s = macro_f_string_static_t_initialize_1(CONTROLLER_stop_s, 0, CONTROLLER_stop_s_length);
- const f_string_static_t controller_succeed_s = macro_f_string_static_t_initialize_1(CONTROLLER_succeed_s, 0, CONTROLLER_succeed_s_length);
- const f_string_static_t controller_success_s = macro_f_string_static_t_initialize_1(CONTROLLER_success_s, 0, CONTROLLER_success_s_length);
- const f_string_static_t controller_synchronous_s = macro_f_string_static_t_initialize_1(CONTROLLER_synchronous_s, 0, CONTROLLER_synchronous_s_length);
- const f_string_static_t controller_thaw_s = macro_f_string_static_t_initialize_1(CONTROLLER_thaw_s, 0, CONTROLLER_thaw_s_length);
- const f_string_static_t controller_timeout_s = macro_f_string_static_t_initialize_1(CONTROLLER_timeout_s, 0, CONTROLLER_timeout_s_length);
- const f_string_static_t controller_type_s = macro_f_string_static_t_initialize_1(CONTROLLER_type_s, 0, CONTROLLER_type_s_length);
- const f_string_static_t controller_use_s = macro_f_string_static_t_initialize_1(CONTROLLER_use_s, 0, CONTROLLER_use_s_length);
- const f_string_static_t controller_user_s = macro_f_string_static_t_initialize_1(CONTROLLER_user_s, 0, CONTROLLER_user_s_length);
- const f_string_static_t controller_utility_s = macro_f_string_static_t_initialize_1(CONTROLLER_utility_s, 0, CONTROLLER_utility_s_length);
- const f_string_static_t controller_value_s = macro_f_string_static_t_initialize_1(CONTROLLER_value_s, 0, CONTROLLER_value_s_length);
- const f_string_static_t controller_wait_s = macro_f_string_static_t_initialize_1(CONTROLLER_wait_s, 0, CONTROLLER_wait_s_length);
- const f_string_static_t controller_want_s = macro_f_string_static_t_initialize_1(CONTROLLER_want_s, 0, CONTROLLER_want_s_length);
- const f_string_static_t controller_wish_s = macro_f_string_static_t_initialize_1(CONTROLLER_wish_s, 0, CONTROLLER_wish_s_length);
- const f_string_static_t controller_with_s = macro_f_string_static_t_initialize_1(CONTROLLER_with_s, 0, CONTROLLER_with_s_length);
- const f_string_static_t controller_yes_s = macro_f_string_static_t_initialize_1(CONTROLLER_yes_s, 0, CONTROLLER_yes_s_length);
-
- const f_string_static_t controller_Entry_s = macro_f_string_static_t_initialize_1(CONTROLLER_Entry_s, 0, CONTROLLER_Entry_s_length);
- const f_string_static_t controller_Exit_s = macro_f_string_static_t_initialize_1(CONTROLLER_Exit_s, 0, CONTROLLER_Exit_s_length);
- const f_string_static_t controller_Item_s = macro_f_string_static_t_initialize_1(CONTROLLER_Item_s, 0, CONTROLLER_Item_s_length);
-
- const f_string_static_t controller_parameter_map_option_s = macro_f_string_static_t_initialize_1(CONTROLLER_parameter_map_option_s, 0, CONTROLLER_parameter_map_option_s_length);
- const f_string_static_t controller_parameter_map_value_s = macro_f_string_static_t_initialize_1(CONTROLLER_parameter_map_value_s, 0, CONTROLLER_parameter_map_value_s_length);
-#endif // _di_controller_string_s_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_common_h
-#define _PRIVATE_common_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// These are included in the order of their dependencies.
-#include "private-cache.h"
-#include "private-execute_set.h"
-#include "private-lock.h"
-#include "private-rule.h"
-#include "private-process.h"
-#include "private-entry.h"
-#include "private-control.h"
-#include "private-setting.h"
-#include "private-thread.h"
-#include "private-state.h"
-
-/**
- * All special strings used within this program.
- *
- * These are generally the names to match, representing some action or setting.
- */
-#ifndef _di_controller_string_s_
- #define CONTROLLER_action_s "action"
- #define CONTROLLER_actions_s "actions"
- #define CONTROLLER_affinity_s "affinity"
- #define CONTROLLER_as_s "as"
- #define CONTROLLER_asynchronous_s "asynchronous"
- #define CONTROLLER_bash_s "bash"
- #define CONTROLLER_batch_s "batch"
- #define CONTROLLER_capability_s "capability"
- #define CONTROLLER_cgroup_s "cgroup"
- #define CONTROLLER_create_s "create"
- #define CONTROLLER_command_s "command"
- #define CONTROLLER_consider_s "consider"
- #define CONTROLLER_control_s "control"
- #define CONTROLLER_control_group_s "control_group"
- #define CONTROLLER_control_has_s "control_has"
- #define CONTROLLER_control_mode_s "control_mode"
- #define CONTROLLER_control_user_s "control_user"
- #define CONTROLLER_controller_s "controller"
- #define CONTROLLER_cpu_s "cpu"
- #define CONTROLLER_core_s "core"
- #define CONTROLLER_data_s "data"
- #define CONTROLLER_deadline_s "deadline"
- #define CONTROLLER_default_s "default"
- #define CONTROLLER_define_s "define"
- #define CONTROLLER_delay_s "delay"
- #define CONTROLLER_directory_s "directory"
- #define CONTROLLER_disable_s "disable"
- #define CONTROLLER_engine_s "engine"
- #define CONTROLLER_entry_s "entry"
- #define CONTROLLER_entries_s "entries"
- #define CONTROLLER_environment_s "environment"
- #define CONTROLLER_error_s "error"
- #define CONTROLLER_execute_s "execute"
- #define CONTROLLER_existing_s "existing"
- #define CONTROLLER_exit_s "exit"
- #define CONTROLLER_exits_s "exits"
- #define CONTROLLER_fail_s "fail"
- #define CONTROLLER_failsafe_s "failsafe"
- #define CONTROLLER_failure_s "failure"
- #define CONTROLLER_fifo_s "fifo"
- #define CONTROLLER_file_s "file"
- #define CONTROLLER_freeze_s "freeze"
- #define CONTROLLER_fsize_s "fsize"
- #define CONTROLLER_full_path_s "full_path"
- #define CONTROLLER_group_s "group"
- #define CONTROLLER_groups_s "groups"
- #define CONTROLLER_helper_s "helper"
- #define CONTROLLER_how_s "how"
- #define CONTROLLER_idle_s "idle"
- #define CONTROLLER_iki_s "iki"
- #define CONTROLLER_item_s "item"
- #define CONTROLLER_init_s "init"
- #define CONTROLLER_kexec_s "kexec"
- #define CONTROLLER_kill_s "kill"
- #define CONTROLLER_length_s "length"
- #define CONTROLLER_limit_s "limit"
- #define CONTROLLER_locks_s "locks"
- #define CONTROLLER_main_s "main"
- #define CONTROLLER_max_s "max"
- #define CONTROLLER_memlock_s "memlock"
- #define CONTROLLER_method_s "method"
- #define CONTROLLER_mode_s "mode"
- #define CONTROLLER_msgqueue_s "msgqueue"
- #define CONTROLLER_name_s "name"
- #define CONTROLLER_need_s "need"
- #define CONTROLLER_new_s "new"
- #define CONTROLLER_nice_s "nice"
- #define CONTROLLER_no_s "no"
- #define CONTROLLER_nofile_s "nofile"
- #define CONTROLLER_normal_s "normal"
- #define CONTROLLER_nproc_s "nproc"
- #define CONTROLLER_on_s "on"
- #define CONTROLLER_optional_s "optional"
- #define CONTROLLER_other_s "other"
- #define CONTROLLER_parameter_s "parameter"
- #define CONTROLLER_parameters_s "parameters"
- #define CONTROLLER_path_s "path"
- #define CONTROLLER_pause_s "pause"
- #define CONTROLLER_payload_type_s "# fss-000e\n"
- #define CONTROLLER_pid_s "pid"
- #define CONTROLLER_pid_file_s "pid_file"
- #define CONTROLLER_processor_s "processor"
- #define CONTROLLER_program_s "program"
- #define CONTROLLER_readonly_s "readonly"
- #define CONTROLLER_ready_s "ready"
- #define CONTROLLER_reboot_s "reboot"
- #define CONTROLLER_reload_s "reload"
- #define CONTROLLER_require_s "require"
- #define CONTROLLER_required_s "required"
- #define CONTROLLER_rerun_s "rerun"
- #define CONTROLLER_reset_s "reset"
- #define CONTROLLER_restart_s "restart"
- #define CONTROLLER_resume_s "resume"
- #define CONTROLLER_round_robin_s "round_robin"
- #define CONTROLLER_rss_s "rss"
- #define CONTROLLER_rtprio_s "rtprio"
- #define CONTROLLER_rttime_s "rttime"
- #define CONTROLLER_rule_s "rule"
- #define CONTROLLER_rules_s "rules"
- #define CONTROLLER_same_s "same"
- #define CONTROLLER_scheduler_s "scheduler"
- #define CONTROLLER_script_s "script"
- #define CONTROLLER_service_s "service"
- #define CONTROLLER_session_s "session"
- #define CONTROLLER_session_new_s "session_new"
- #define CONTROLLER_session_same_s "session_same"
- #define CONTROLLER_settings_s "settings"
- #define CONTROLLER_sigpending_s "sigpending"
- #define CONTROLLER_show_s "show"
- #define CONTROLLER_shutdown_s "shutdown"
- #define CONTROLLER_stack_s "stack"
- #define CONTROLLER_start_s "start"
- #define CONTROLLER_status_s "status"
- #define CONTROLLER_stop_s "stop"
- #define CONTROLLER_succeed_s "succeed"
- #define CONTROLLER_success_s "success"
- #define CONTROLLER_synchronous_s "synchronous"
- #define CONTROLLER_thaw_s "thaw"
- #define CONTROLLER_timeout_s "timeout"
- #define CONTROLLER_type_s "type"
- #define CONTROLLER_use_s "use"
- #define CONTROLLER_user_s "user"
- #define CONTROLLER_utility_s "utility"
- #define CONTROLLER_value_s "value"
- #define CONTROLLER_wait_s "wait"
- #define CONTROLLER_want_s "want"
- #define CONTROLLER_wish_s "wish"
- #define CONTROLLER_with_s "with"
- #define CONTROLLER_yes_s "yes"
-
- #define CONTROLLER_Entry_s "Entry"
- #define CONTROLLER_Exit_s "Exit"
- #define CONTROLLER_Item_s "Item"
-
- #define CONTROLLER_parameter_map_option_s ":option"
- #define CONTROLLER_parameter_map_value_s ":value"
-
- #define CONTROLLER_action_s_length 6
- #define CONTROLLER_actions_s_length 7
- #define CONTROLLER_affinity_s_length 8
- #define CONTROLLER_as_s_length 2
- #define CONTROLLER_asynchronous_s_length 12
- #define CONTROLLER_bash_s_length 4
- #define CONTROLLER_batch_s_length 5
- #define CONTROLLER_capability_s_length 10
- #define CONTROLLER_cgroup_s_length 6
- #define CONTROLLER_create_s_length 6
- #define CONTROLLER_command_s_length 7
- #define CONTROLLER_consider_s_length 8
- #define CONTROLLER_control_s_length 7
- #define CONTROLLER_control_group_s_length 13
- #define CONTROLLER_control_has_s_length 11
- #define CONTROLLER_control_mode_s_length 12
- #define CONTROLLER_control_user_s_length 12
- #define CONTROLLER_controller_s_length 10
- #define CONTROLLER_core_s_length 4
- #define CONTROLLER_cpu_s_length 3
- #define CONTROLLER_data_s_length 4
- #define CONTROLLER_deadline_s_length 8
- #define CONTROLLER_default_s_length 7
- #define CONTROLLER_define_s_length 6
- #define CONTROLLER_delay_s_length 5
- #define CONTROLLER_directory_s_length 9
- #define CONTROLLER_disable_s_length 7
- #define CONTROLLER_engine_s_length 6
- #define CONTROLLER_entry_s_length 5
- #define CONTROLLER_entries_s_length 7
- #define CONTROLLER_environment_s_length 11
- #define CONTROLLER_error_s_length 5
- #define CONTROLLER_existing_s_length 8
- #define CONTROLLER_execute_s_length 7
- #define CONTROLLER_exit_s_length 4
- #define CONTROLLER_exits_s_length 5
- #define CONTROLLER_fail_s_length 4
- #define CONTROLLER_failure_s_length 7
- #define CONTROLLER_failsafe_s_length 8
- #define CONTROLLER_fifo_s_length 4
- #define CONTROLLER_file_s_length 4
- #define CONTROLLER_freeze_s_length 6
- #define CONTROLLER_fsize_s_length 5
- #define CONTROLLER_full_path_s_length 9
- #define CONTROLLER_group_s_length 5
- #define CONTROLLER_groups_s_length 6
- #define CONTROLLER_helper_s_length 6
- #define CONTROLLER_how_s_length 3
- #define CONTROLLER_idle_s_length 4
- #define CONTROLLER_iki_s_length 3
- #define CONTROLLER_init_s_length 4
- #define CONTROLLER_item_s_length 4
- #define CONTROLLER_kexec_s_length 5
- #define CONTROLLER_kill_s_length 4
- #define CONTROLLER_length_s_length 6
- #define CONTROLLER_limit_s_length 5
- #define CONTROLLER_locks_s_length 5
- #define CONTROLLER_main_s_length 4
- #define CONTROLLER_max_s_length 3
- #define CONTROLLER_memlock_s_length 7
- #define CONTROLLER_method_s_length 6
- #define CONTROLLER_mode_s_length 4
- #define CONTROLLER_msgqueue_s_length 8
- #define CONTROLLER_name_s_length 4
- #define CONTROLLER_need_s_length 4
- #define CONTROLLER_new_s_length 3
- #define CONTROLLER_nice_s_length 4
- #define CONTROLLER_no_s_length 2
- #define CONTROLLER_nofile_s_length 6
- #define CONTROLLER_normal_s_length 6
- #define CONTROLLER_nproc_s_length 5
- #define CONTROLLER_on_s_length 2
- #define CONTROLLER_optional_s_length 8
- #define CONTROLLER_other_s_length 5
- #define CONTROLLER_parameter_s_length 9
- #define CONTROLLER_parameters_s_length 10
- #define CONTROLLER_path_s_length 4
- #define CONTROLLER_pause_s_length 5
- #define CONTROLLER_payload_type_s_length 11
- #define CONTROLLER_pid_s_length 3
- #define CONTROLLER_pid_file_s_length 8
- #define CONTROLLER_processor_s_length 9
- #define CONTROLLER_program_s_length 7
- #define CONTROLLER_readonly_s_length 8
- #define CONTROLLER_ready_s_length 5
- #define CONTROLLER_reboot_s_length 6
- #define CONTROLLER_reload_s_length 6
- #define CONTROLLER_require_s_length 7
- #define CONTROLLER_required_s_length 8
- #define CONTROLLER_rerun_s_length 5
- #define CONTROLLER_reset_s_length 5
- #define CONTROLLER_restart_s_length 7
- #define CONTROLLER_resume_s_length 6
- #define CONTROLLER_round_robin_s_length 11
- #define CONTROLLER_rss_s_length 3
- #define CONTROLLER_rtprio_s_length 6
- #define CONTROLLER_rttime_s_length 6
- #define CONTROLLER_rule_s_length 4
- #define CONTROLLER_rules_s_length 5
- #define CONTROLLER_same_s_length 4
- #define CONTROLLER_scheduler_s_length 9
- #define CONTROLLER_script_s_length 6
- #define CONTROLLER_service_s_length 7
- #define CONTROLLER_session_s_length 7
- #define CONTROLLER_session_new_s_length 11
- #define CONTROLLER_session_same_s_length 12
- #define CONTROLLER_settings_s_length 8
- #define CONTROLLER_show_s_length 4
- #define CONTROLLER_shutdown_s_length 8
- #define CONTROLLER_sigpending_s_length 10
- #define CONTROLLER_stack_s_length 5
- #define CONTROLLER_start_s_length 5
- #define CONTROLLER_status_s_length 6
- #define CONTROLLER_stop_s_length 4
- #define CONTROLLER_succeed_s_length 7
- #define CONTROLLER_success_s_length 7
- #define CONTROLLER_synchronous_s_length 11
- #define CONTROLLER_thaw_s_length 4
- #define CONTROLLER_timeout_s_length 7
- #define CONTROLLER_type_s_length 4
- #define CONTROLLER_use_s_length 3
- #define CONTROLLER_user_s_length 4
- #define CONTROLLER_utility_s_length 7
- #define CONTROLLER_value_s_length 5
- #define CONTROLLER_wait_s_length 4
- #define CONTROLLER_want_s_length 4
- #define CONTROLLER_wish_s_length 4
- #define CONTROLLER_with_s_length 4
- #define CONTROLLER_yes_s_length 3
-
- #define CONTROLLER_Entry_s_length 5
- #define CONTROLLER_Exit_s_length 4
- #define CONTROLLER_Item_s_length 4
-
- #define CONTROLLER_parameter_map_option_s_length 7
- #define CONTROLLER_parameter_map_value_s_length 6
-
- extern const f_string_static_t controller_action_s;
- extern const f_string_static_t controller_actions_s;
- extern const f_string_static_t controller_affinity_s;
- extern const f_string_static_t controller_as_s;
- extern const f_string_static_t controller_asynchronous_s;
- extern const f_string_static_t controller_bash_s;
- extern const f_string_static_t controller_batch_s;
- extern const f_string_static_t controller_capability_s;
- extern const f_string_static_t controller_cgroup_s;
- extern const f_string_static_t controller_create_s;
- extern const f_string_static_t controller_command_s;
- extern const f_string_static_t controller_consider_s;
- extern const f_string_static_t controller_control_s;
- extern const f_string_static_t controller_control_group_s;
- extern const f_string_static_t controller_control_has_s;
- extern const f_string_static_t controller_control_mode_s;
- extern const f_string_static_t controller_control_user_s;
- extern const f_string_static_t controller_controller_s;
- extern const f_string_static_t controller_core_s;
- extern const f_string_static_t controller_cpu_s;
- extern const f_string_static_t controller_data_s;
- extern const f_string_static_t controller_deadline_s;
- extern const f_string_static_t controller_default_s;
- extern const f_string_static_t controller_define_s;
- extern const f_string_static_t controller_delay_s;
- extern const f_string_static_t controller_directory_s;
- extern const f_string_static_t controller_disable_s;
- extern const f_string_static_t controller_engine_s;
- extern const f_string_static_t controller_entry_s;
- extern const f_string_static_t controller_entries_s;
- extern const f_string_static_t controller_environment_s;
- extern const f_string_static_t controller_error_s;
- extern const f_string_static_t controller_existing_s;
- extern const f_string_static_t controller_execute_s;
- extern const f_string_static_t controller_exit_s;
- extern const f_string_static_t controller_exits_s;
- extern const f_string_static_t controller_fail_s;
- extern const f_string_static_t controller_failsafe_s;
- extern const f_string_static_t controller_failure_s;
- extern const f_string_static_t controller_fifo_s;
- extern const f_string_static_t controller_file_s;
- extern const f_string_static_t controller_freeze_s;
- extern const f_string_static_t controller_fsize_s;
- extern const f_string_static_t controller_full_path_s;
- extern const f_string_static_t controller_group_s;
- extern const f_string_static_t controller_groups_s;
- extern const f_string_static_t controller_helper_s;
- extern const f_string_static_t controller_how_s;
- extern const f_string_static_t controller_idle_s;
- extern const f_string_static_t controller_iki_s;
- extern const f_string_static_t controller_init_s;
- extern const f_string_static_t controller_item_s;
- extern const f_string_static_t controller_kexec_s;
- extern const f_string_static_t controller_kill_s;
- extern const f_string_static_t controller_length_s;
- extern const f_string_static_t controller_limit_s;
- extern const f_string_static_t controller_locks_s;
- extern const f_string_static_t controller_main_s;
- extern const f_string_static_t controller_max_s;
- extern const f_string_static_t controller_memlock_s;
- extern const f_string_static_t controller_method_s;
- extern const f_string_static_t controller_mode_s;
- extern const f_string_static_t controller_msgqueue_s;
- extern const f_string_static_t controller_name_s;
- extern const f_string_static_t controller_need_s;
- extern const f_string_static_t controller_new_s;
- extern const f_string_static_t controller_nice_s;
- extern const f_string_static_t controller_no_s;
- extern const f_string_static_t controller_nofile_s;
- extern const f_string_static_t controller_normal_s;
- extern const f_string_static_t controller_nproc_s;
- extern const f_string_static_t controller_on_s;
- extern const f_string_static_t controller_optional_s;
- extern const f_string_static_t controller_other_s;
- extern const f_string_static_t controller_parameter_s;
- extern const f_string_static_t controller_parameters_s;
- extern const f_string_static_t controller_path_s;
- extern const f_string_static_t controller_pause_s;
- extern const f_string_static_t controller_payload_type_s;
- extern const f_string_static_t controller_pid_s;
- extern const f_string_static_t controller_pid_file_s;
- extern const f_string_static_t controller_processor_s;
- extern const f_string_static_t controller_program_s;
- extern const f_string_static_t controller_readonly_s;
- extern const f_string_static_t controller_ready_s;
- extern const f_string_static_t controller_reboot_s;
- extern const f_string_static_t controller_reload_s;
- extern const f_string_static_t controller_require_s;
- extern const f_string_static_t controller_required_s;
- extern const f_string_static_t controller_rerun_s;
- extern const f_string_static_t controller_reset_s;
- extern const f_string_static_t controller_restart_s;
- extern const f_string_static_t controller_resume_s;
- extern const f_string_static_t controller_round_robin_s;
- extern const f_string_static_t controller_rss_s;
- extern const f_string_static_t controller_rtprio_s;
- extern const f_string_static_t controller_rttime_s;
- extern const f_string_static_t controller_rule_s;
- extern const f_string_static_t controller_rules_s;
- extern const f_string_static_t controller_same_s;
- extern const f_string_static_t controller_scheduler_s;
- extern const f_string_static_t controller_script_s;
- extern const f_string_static_t controller_service_s;
- extern const f_string_static_t controller_session_s;
- extern const f_string_static_t controller_session_new_s;
- extern const f_string_static_t controller_session_same_s;
- extern const f_string_static_t controller_settings_s;
- extern const f_string_static_t controller_show_s;
- extern const f_string_static_t controller_shutdown_s;
- extern const f_string_static_t controller_sigpending_s;
- extern const f_string_static_t controller_stack_s;
- extern const f_string_static_t controller_start_s;
- extern const f_string_static_t controller_status_s;
- extern const f_string_static_t controller_stop_s;
- extern const f_string_static_t controller_succeed_s;
- extern const f_string_static_t controller_success_s;
- extern const f_string_static_t controller_synchronous_s;
- extern const f_string_static_t controller_thaw_s;
- extern const f_string_static_t controller_timeout_s;
- extern const f_string_static_t controller_type_s;
- extern const f_string_static_t controller_use_s;
- extern const f_string_static_t controller_user_s;
- extern const f_string_static_t controller_utility_s;
- extern const f_string_static_t controller_value_s;
- extern const f_string_static_t controller_wait_s;
- extern const f_string_static_t controller_want_s;
- extern const f_string_static_t controller_wish_s;
- extern const f_string_static_t controller_with_s;
- extern const f_string_static_t controller_yes_s;
-
- extern const f_string_static_t controller_Entry_s;
- extern const f_string_static_t controller_Exit_s;
- extern const f_string_static_t controller_Item_s;
-
- extern const f_string_static_t controller_parameter_map_option_s;
- extern const f_string_static_t controller_parameter_map_value_s;
-#endif // _di_controller_string_s_
-
-/**
- * Provide common/generic definitions.
- *
- * The controller_common_allocation_large_d or controller_common_allocation_small_d must be at least 2 for this project.
- *
- * controller_common_allocation_*:
- * - iki_large: An allocation step used for IKI buffers that are anticipated to have large buffers.
- * - iki_small: An allocation step used for IKI buffers that are anticipated to have small buffers.
- * - large: An allocation step used for buffers that are anticipated to have large buffers.
- * - small: An allocation step used for buffers that are anticipated to have small buffers.
- */
-#ifndef _di_controller_common_
- #define controller_common_allocation_iki_large_d 128
- #define controller_common_allocation_iki_small_d 8
- #define controller_common_allocation_large_d 256
- #define controller_common_allocation_small_d 16
-#endif // _di_controller_common_
-
-/**
- * A set of codes representing different with flags.
- */
-#ifndef _di_controller_with_defines_
- #define controller_with_full_path_d 0x1
- #define controller_with_session_new_d 0x2
- #define controller_with_session_same_d 0x4
-#endif // _di_controller_with_defines_
-
-/**
- * A wrapper used for passing a common set of all data, particularly for sharing between threads.
- *
- * main: The main program data.
- * setting: All loaded settings.
- * thread: All thread related data.
- */
-#ifndef _di_controller_main_old_t_
- typedef struct {
- controller_main_t *main;
- controller_process_t *setting;
- controller_thread_t *thread;
- } controller_global_t;
-
- #define controller_global_t_initialize { 0, 0, 0 }
-
- #define macro_controller_global_t_initialize_1(main, setting, thread) { \
- main, \
- setting, \
- thread, \
- }
-#endif // _di_controller_main_old_t_
-
-/**
- * A wrapper used for passing a set of entry processing and execution related data.
- *
- * global: All data globally shared.
- * setting: The setting data.
- */
-#ifndef _di_controller_main_entry_t_
- typedef struct {
- controller_global_t *global;
- controller_process_t *setting;
- } controller_main_entry_t;
-
- #define controller_main_entry_t_initialize { 0, 0 }
-
- #define macro_controller_main_entry_t_initialize_1(global, setting) { \
- global, \
- setting, \
- }
-#endif // _di_controller_main_entry_t_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_common_h
+++ /dev/null
-#include "../controller.h"
-#include "private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_common_control_h
-#define _PRIVATE_common_control_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_common_control_h
+++ /dev/null
-#include "../controller.h"
-#include "private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_common_entry_h
-#define _PRIVATE_common_entry_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_common_entry_h
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_common_execute_set_h
-#define _PRIVATE_common_execute_set_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * A structure for passing execution arguments to the execute functions.
- *
- * parameter: All parameters sent to the program on execution.
- * as: All special properties to apply, such as cpu affinity.
- */
-#ifndef _di_controller_execute_set_t_
- typedef struct {
- fl_execute_parameter_t parameter;
- fl_execute_as_t as;
- } controller_execute_set_t;
-
- #define controller_execute_set_t_initialize_1 { \
- fl_execute_parameter_t_initialize, \
- fl_execute_as_t_initialize \
- }
-
- #define macro_controller_execute_set_t_initialize_1(option, wait, environment, signals, main, as) { \
- macro_fl_execute_parameter_t_initialize_1(option, wait, environment, signals, main), \
- as, \
- }
-#endif // _di_controller_execute_set_t_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_common_execute_set_h
+++ /dev/null
-#include "../controller.h"
-#include "private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_lock_delete_mutex_
- void controller_lock_delete_mutex(f_thread_mutex_t *mutex) {
-
- const f_status_t status = f_thread_mutex_delete(mutex);
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) == F_busy) {
- if (f_thread_mutex_delete(mutex) == F_okay) {
- mutex = 0;
- }
- }
- }
- else {
- mutex = 0;
- }
- }
-#endif // _di_controller_lock_delete_mutex_
-
-#ifndef _di_controller_lock_delete_rw_
- void controller_lock_delete_rw(f_thread_lock_t *lock) {
-
- const f_status_t status = f_thread_lock_delete(lock);
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) == F_busy) {
- if (f_thread_lock_delete(lock) == F_okay) {
- lock = 0;
- }
- }
- }
- else {
- lock = 0;
- }
- }
-#endif // _di_controller_lock_delete_rw_
-
-#ifndef _di_controller_lock_delete_simple_
- void controller_lock_delete_simple(controller_lock_t * const lock) {
-
- controller_lock_delete_mutex(&lock->alert);
- controller_lock_delete_mutex(&lock->cancel);
- controller_lock_delete_mutex(&lock->print);
-
- controller_lock_delete_rw(&lock->process);
- controller_lock_delete_rw(&lock->rule);
-
- f_thread_condition_delete(&lock->alert_condition);
- }
-#endif // _di_controller_lock_delete_simple_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_common_lock_h
-#define _PRIVATE_common_lock_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * A structure for sharing mutexes globally between different threads.
- *
- * The alert lock is intended for a generic waiting on alerts operations.
- * The cancel lock is intended for preventing double cancellation calls (which can happen due to interrupts).
- * The print lock is intended to lock any activity printing to stdout/stderr.
- * The process lock is intended to lock any activity on the processs structure.
- * The rule lock is intended to lock any activity on the rules structure.
- *
- * alert: The alert mutex lock for waking up on alerts.
- * cancel: The cancel mutex lock for locking the cancel operation.
- * print: The print mutex lock.
- * process: The process r/w lock.
- * rule: The rule r/w lock.
- * alert_condition: The condition used to trigger alerts.
- */
-#ifndef _di_controller_lock_t_
- typedef struct {
- f_thread_mutex_t alert;
- f_thread_mutex_t cancel;
- f_thread_mutex_t print;
-
- f_thread_lock_t process;
- f_thread_lock_t rule;
-
- f_thread_condition_t alert_condition;
- } controller_lock_t;
-
- #define controller_lock_t_initialize { \
- f_thread_mutex_t_initialize, \
- f_thread_mutex_t_initialize, \
- f_thread_mutex_t_initialize, \
- f_thread_lock_t_initialize, \
- f_thread_lock_t_initialize, \
- f_thread_condition_t_initialize, \
- }
-#endif // _di_controller_lock_t_
-
-/**
- * Delete the mutex lock and if the mutex lock is busy, forcibly unlock it and then delete it.
- *
- * @param mutex
- * The mutex lock to delete.
- * Will be set to NULL if delete succeeded.
- */
-#ifndef _di_controller_lock_delete_mutex_
- extern void controller_lock_delete_mutex(f_thread_mutex_t *mutex) F_attribute_visibility_internal_d;
-#endif // _di_controller_lock_delete_mutex_
-
-/**
- * Delete the r/w lock and if the r/w lock is busy, forcibly unlock it and then delete it.
- *
- * @param lock
- * The r/w lock to delete.
- * Will be set to NULL if delete succeeded.
- */
-#ifndef _di_controller_lock_delete_rw_
- extern void controller_lock_delete_rw(f_thread_lock_t *lock) F_attribute_visibility_internal_d;
-#endif // _di_controller_lock_delete_rw_
-
-/**
- * Fully de-allocate all memory for the given lock without caring about return status.
- *
- * @param lock
- * The lock to de-allocate.
- *
- * @see f_thread_lock_delete()
- * @see f_thread_mutex_delete()
- */
-#ifndef _di_controller_lock_delete_simple_
- extern void controller_lock_delete_simple(controller_lock_t * const lock) F_attribute_visibility_internal_d;
-#endif // _di_controller_lock_delete_simple_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_common_lock_h
+++ /dev/null
-#include "../controller.h"
-#include "private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_pids_increase_
- f_status_t controller_pids_increase(controller_pids_t * const pids) {
-
- if (pids->used + 1 > pids->size) {
- f_number_unsigned_t length = pids->used + controller_common_allocation_small_d;
-
- if (length > F_number_t_size_unsigned_d) {
- if (pids->used + 1 > F_number_t_size_unsigned_d) {
- return F_status_set_error(F_array_too_large);
- }
-
- length = F_number_t_size_unsigned_d;
- }
-
- return controller_pids_resize(length, pids);
- }
-
- return F_data_not;
- }
-#endif // _di_controller_pids_increase_
-
-#ifndef _di_controller_pids_resize_
- f_status_t controller_pids_resize(const f_number_unsigned_t length, controller_pids_t * const pids) {
-
- const f_status_t status = f_memory_resize(pids->size, length, sizeof(controller_rule_t), (void **) & pids->array);
- if (F_status_is_error(status)) return status;
-
- pids->size = length;
-
- if (pids->used > pids->size) {
- pids->used = length;
- }
-
- return F_okay;
- }
-#endif // _di_controller_pids_resize_
-
-#ifndef _di_controller_data_delete_simple_
- void controller_data_delete_simple(controller_data_t * const data) {
-
- if (data->id_thread) {
- f_thread_signal_write(data->id_thread, F_signal_kill);
- f_thread_join(data->id_thread, 0);
-
- data->id_thread = 0;
- }
-
- f_thread_condition_delete(&data->wait);
-
- controller_lock_delete_rw(&data->lock);
- controller_lock_delete_rw(&data->active);
- controller_lock_delete_mutex(&data->wait_lock);
-
- controller_cache_delete_simple(&data->cache);
- controller_pids_resize(0, &data->childs);
- controller_rule_delete(&data->rule);
-
- f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &data->path_pids.array, &data->path_pids.used, &data->path_pids.size, &f_string_dynamics_delete_callback);
-
- f_memory_array_resize(0, sizeof(f_number_unsigned_t), (void **) &data->stack.array, &data->stack.used, &data->stack.size);
- }
-#endif // _di_controller_data_delete_simple_
-
-#ifndef _di_controller_processs_delete_simple_
- void controller_processs_delete_simple(controller_processs_t * const processs) {
-
- controller_processs_resize(0, processs);
- }
-#endif // _di_controller_processs_delete_simple_
-
-#ifndef _di_controller_processs_increase_
- f_status_t controller_processs_increase(controller_processs_t * const processs) {
-
- if (processs->used + 1 > processs->size) {
- f_number_unsigned_t length = processs->used + controller_common_allocation_small_d;
-
- if (length > F_number_t_size_unsigned_d) {
- if (processs->used + 1 > F_number_t_size_unsigned_d) {
- return F_status_set_error(F_array_too_large);
- }
-
- length = F_number_t_size_unsigned_d;
- }
-
- return controller_processs_resize(length, processs);
- }
-
- return F_data_not;
- }
-#endif // _di_controller_processs_increase_
-
-#ifndef _di_controller_processs_resize_
- f_status_t controller_processs_resize(const f_number_unsigned_t length, controller_processs_t * const processs) {
-
- f_status_t status = F_okay;
-
- for (f_number_unsigned_t i = length; i < processs->size; ++i) {
-
- if (processs->array[i]) {
- controller_data_delete_simple(processs->array[i]);
-
- f_memory_delete(1, sizeof(f_number_unsigned_t *), (void **) & processs->array[i]);
- }
- } // for
-
- status = f_memory_resize(processs->size, length, sizeof(controller_data_t), (void **) & processs->array);
- if (F_status_is_error(status)) return status;
-
- if (length) {
- controller_data_t *process = 0;
-
- // The lock must be initialized, but only once, so initialize immediately upon allocation.
- for (; processs->size < length; ++processs->size) {
-
- status = f_memory_new(1, sizeof(controller_data_t), (void **) &processs->array[processs->size]);
-
- if (F_status_is_error_not(status)) {
- process = processs->array[processs->size];
-
- status = f_thread_lock_create(0, &process->lock);
- }
-
- if (F_status_is_error_not(status)) {
- status = f_thread_lock_create(0, &process->active);
- }
-
- if (F_status_is_error_not(status)) {
- status = f_thread_condition_create(0, &process->wait);
- }
-
- if (F_status_is_error_not(status)) {
- status = f_thread_mutex_create(0, &process->wait_lock);
- }
-
- if (F_status_is_error(status)) {
- processs->size = length;
-
- return status;
- }
-
- for (f_number_unsigned_t i = 0; i < controller_rule_action_type__enum_size_e; ++i) {
- process->rule.status[i] = F_known_not;
- } // for
- } // for
-
- processs->size = length;
-
- if (processs->used > processs->size) {
- processs->used = length;
- }
- }
-
- return F_okay;
- }
-#endif // _di_controller_processs_resize_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_common_process_h
-#define _PRIVATE_common_process_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * An array of PIDs.
- *
- * array: An array of rule PIDs.
- * size: Total amount of allocated space.
- * used: Total number of allocated spaces used.
- */
-#ifndef _di_controller_pids_t_
- typedef struct {
- pid_t *array;
-
- f_number_unsigned_t size;
- f_number_unsigned_t used;
- } controller_pids_t;
-
- #define controller_pids_t_initialize { \
- 0, \
- 0, \
- 0, \
- }
-#endif // _di_controller_pids_t_
-
-/**
- * A Rule Process.
- *
- * This refers to "process" as in the processing of a single rule for the given Rule ID and does not refer to "process" as in a CPU Process.
- *
- * The "cache" should only be used by the function processing/executing the process and as such should not require a write lock on the "process".
- * There should only be a single thread running any given Rule process at a time, guaranteeing the cache to not need read/write locks.
- *
- * Process States:
- * - idle: No process is running for this rule.
- * - busy: A process is actively using this, and is running synchronously.
- * - active: A process is actively using this, and is running asynchronously.
- * - done: A process has finished running on this and there is a thread that needs to be cleaned up.
- *
- * Process Types:
- * - entry: The process is started from an entry.
- * - exit: The process is started from an exit.
- * - control: The process is started from a control operation.
- *
- * id: The ID of this process relative to the processes array.
- * id_thread: The thread id, a valid ID when state is "active", and an invalid ID when the state is "busy".
- * action: The action being performed.
- * active: A read/write lock representing that something is currently using this (read locks = in use, write lock = begin deleting).
- * cache: The cache used in this process.
- * child: The process id of a child process, if one is running (when forking to execute a child process).
- * lock: A read/write lock on the structure.
- * options: Configuration options for this thread.
- * result: The last return code from an execution of a process.
- * rule: A copy of the rule actively being executed.
- * stack: A stack used to represent dependencies as Rule ID's to avoid circular rule dependencies (If Rule A waits on Rule B, then Rule B must not wait on Rule A).
- * state: The state of the process.
- * status: The last execution status of the process.
- * type: The currently active process type (from the controller_data_type_*_e).
- * wait: A thread condition to tell a process waiting process that the rule has is done being processed.
- * wait_lock: A mutex lock for working with "wait".
- *
- * main_data: Used for passing the controller_main_t data to the process thread (to populate controller_global_t).
- * main_setting: Used for passing the controller_process_t data to the process thread (to populate controller_global_t).
- * main_thread: Used for passing the controller_thread_t data to the process thread (to populate controller_global_t).
- */
-#ifndef _di_controller_data_t_
- #define controller_process_option_asynchronous_d 0x1
- #define controller_process_option_require_d 0x2
- #define controller_process_option_simulate_d 0x4
- #define controller_process_option_validate_d 0x8
- #define controller_process_option_wait_d 0x10
-
- enum {
- controller_process_state_idle_e = 1,
- controller_process_state_busy_e,
- controller_process_state_active_e,
- controller_process_state_done_e,
- };
-
- enum {
- controller_data_type_entry_e = 1,
- controller_data_type_exit_e,
- controller_data_type_control_e,
- };
-
- typedef struct {
- f_number_unsigned_t id;
-
- uint8_t state;
- uint8_t action;
- uint8_t options;
- uint8_t type;
-
- int result;
-
- f_thread_id_t id_thread;
- f_thread_lock_t lock;
- f_thread_lock_t active;
- f_thread_condition_t wait;
- f_thread_mutex_t wait_lock;
-
- controller_cache_t cache;
- f_number_unsigneds_t stack;
-
- f_string_dynamics_t path_pids;
-
- controller_pids_t childs;
- controller_rule_t rule;
-
- void *main_data;
- void *main_setting;
- void *main_thread;
- } controller_data_t;
-
- #define controller_data_t_initialize { \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- f_thread_id_t_initialize, \
- f_thread_lock_t_initialize, \
- f_thread_lock_t_initialize, \
- f_thread_condition_t_initialize, \
- controller_cache_t_initialize, \
- f_number_unsigneds_t_initialize, \
- f_string_dynamics_t_initialize, \
- controller_pids_t_initialize, \
- controller_rule_t_initialize, \
- 0, \
- 0, \
- 0, \
- }
-#endif // _di_controller_data_t_
-
-/**
- * The Rule Processes.
- *
- * Each process is a pointer of a process, to preserve memory locations that may ultimately change due to the resizing the array.
- *
- * array: An array of rule processes.
- * size: Total amount of allocated space.
- * used: Total number of allocated spaces used.
- */
-#ifndef _di_controller_processs_t_
- typedef struct {
- controller_data_t **array;
-
- f_number_unsigned_t size;
- f_number_unsigned_t used;
- } controller_processs_t;
-
- #define controller_processs_t_initialize { \
- 0, \
- 0, \
- 0, \
- }
-#endif // _di_controller_processs_t_
-
-/**
- * Increase the size of the pid array, but only if necessary.
- *
- * If the given length is too large for the buffer, then attempt to set max buffer size (F_number_t_size_unsigned_d).
- * If already set to the maximum buffer size, then the resize will fail.
- *
- * @param pids
- * The pid array to resize.
- *
- * @return
- * F_okay on success.
- * F_data_not on success, but there is no reason to increase size (used + controller_common_allocation_small_d <= size).
- *
- * F_array_too_large (with error bit) if the new array length is too large.
- * F_memory_not (with error bit) on out of memory.
- * F_parameter (with error bit) if a parameter is invalid.
- *
- * @see controller_pids_resize()
- */
-#ifndef _di_controller_pids_increase_
- extern f_status_t controller_pids_increase(controller_pids_t * const pids) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_increase_
-
-/**
- * Resize the pid array.
- *
- * @param length
- * The new size to use.
- * @param pids
- * The pid array to resize.
- *
- * @return
- * F_okay on success.
- *
- * F_memory_not (with error bit) on out of memory.
- * F_parameter (with error bit) if a parameter is invalid.
- *
- * @see f_memory_resize()
- */
-#ifndef _di_controller_pids_resize_
- extern f_status_t controller_pids_resize(const f_number_unsigned_t length, controller_pids_t * const pids) F_attribute_visibility_internal_d;
-#endif // _di_controller_pids_resize_
-
-/**
- * Fully de-allocate all memory for the given process without caring about return status.
- *
- * @param data
- * The data to de-allocate.
- *
- * @see f_memory_array_resize()
- * @see f_thread_condition_delete()
- * @see f_thread_mutex_delete()
- */
-#ifndef _di_controller_data_delete_simple_
- extern void controller_data_delete_simple(controller_data_t * const data) F_attribute_visibility_internal_d;
-#endif // _di_controller_data_delete_simple_
-
-/**
- * Fully de-allocate all memory for the given processs without caring about return status.
- *
- * @param processs
- * The process array to de-allocate.
- *
- * @see controller_processs_resize()
- */
-#ifndef _di_controller_processs_delete_simple_
- extern void controller_processs_delete_simple(controller_processs_t * const processs) F_attribute_visibility_internal_d;
-#endif // _di_controller_processs_delete_simple_
-
-/**
- * Increase the size of the rule array, but only if necessary.
- *
- * If the given length is too large for the buffer, then attempt to set max buffer size (F_number_t_size_unsigned_d).
- * If already set to the maximum buffer size, then the resize will fail.
- *
- * @param processs
- * The process array to resize.
- *
- * @return
- * F_okay on success.
- * F_data_not on success, but there is no reason to increase size (used + controller_common_allocation_small_d <= size).
- *
- * F_array_too_large (with error bit) if the new array length is too large.
- * F_memory_not (with error bit) on out of memory.
- * F_parameter (with error bit) if a parameter is invalid.
- *
- * @see controller_processs_resize()
- */
-#ifndef _di_controller_processs_increase_
- extern f_status_t controller_processs_increase(controller_processs_t * const processs) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_increase_
-
-/**
- * Resize the rule array.
- *
- * @param length
- * The new size to use.
- * @param processs
- * The process array to resize.
- *
- * @return
- * F_okay on success.
- *
- * Errors (with error bit) from: controller_data_delete_simple().
- * Errors (with error bit) from: f_memory_resize().
- * Errors (with error bit) from: f_thread_condition_create().
- * Errors (with error bit) from: f_thread_lock_create().
- *
- * @see controller_data_delete_simple()
- * @see f_memory_resize()
- * @see f_thread_condition_create()
- * @see f_thread_lock_create()
- */
-#ifndef _di_controller_processs_resize_
- extern f_status_t controller_processs_resize(const f_number_unsigned_t length, controller_processs_t * const processs) F_attribute_visibility_internal_d;
-#endif // _di_controller_processs_resize_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_common_process_h
+++ /dev/null
-#include "../controller.h"
-#include "private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_common_rule_h
-#define _PRIVATE_common_rule_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_common_rule_h
+++ /dev/null
-#include "../controller.h"
-#include "private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_common_setting_h
-#define _PRIVATE_common_setting_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_common_setting_h
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_common_state_h
-#define _PRIVATE_common_state_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * A structure for passing data to the interrupt state function.
- *
- * is_normal: Boolean designating if this is operating in a normal state.
- * thread: The thread data.
- */
-#ifndef _di_controller_state_interrupt_t_
- typedef struct {
- bool is_normal;
-
- controller_thread_t *thread;
- } controller_state_interrupt_t;
-
- #define controller_state_interrupt_t_initialize { \
- F_true, \
- 0, \
- }
-
- #define macro_controller_state_interrupt_t_initialize_1(is_normal, thread) { \
- is_normal, \
- thread, \
- }
-#endif // _di_controller_state_interrupt_t_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_common_state_h
+++ /dev/null
-#include "../controller.h"
-#include "private-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_thread_delete_simple_
- void controller_thread_delete_simple(controller_thread_t * const thread) {
-
- controller_lock_delete_simple(&thread->lock);
- controller_processs_resize(0, &thread->processs);
- controller_cache_delete_simple(&thread->cache);
- }
-#endif // _di_controller_thread_delete_simple_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_common_thread_h
-#define _PRIVATE_common_thread_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * A structure for managing threads.
- *
- * This is essentially data shared globally between threads, about threads.
- *
- * The "enabled" and "signal" utilize the lock: lock.process.
- *
- * enabled: TRUE when threads are active, FALSE when inactive and the program is essentially shutting down, no new threads should be started when FALSE.
- * signal: The code of any signal received.
- * status: A status used by the main entry/rule processing thread for synchronous operations.
- * id_cleanup: The thread ID representing the Cleanup Process.
- * id_control: The thread ID representing the Control Process.
- * id_entry: The thread ID representing the Entry or Exit Process.
- * id_rule: The thread ID representing the Rule Process.
- * id_signal: The thread ID representing the Signal Process.
- * lock: A r/w lock for operating on this structure.
- * processs: All Rule Process thread data.
- * cache: A cache used by the main entry/rule processing thread for synchronous operations.
- */
-#ifndef _di_controller_thread_t_
- #define controller_thread_cleanup_interval_long_d 3600 // 1 hour in seconds.
- #define controller_thread_cleanup_interval_short_d 180 // 3 minutes in seconds.
- #define controller_thread_exit_timeout_d 500 // 0.5 seconds in milliseconds.
- #define controller_thread_exit_process_cancel_wait_d 600000000 // 0.6 seconds in nanoseconds.
- #define controller_thread_exit_process_cancel_total_d 150 // 90 seconds in multiples of wait.
- #define controller_thread_simulation_timeout_d 200 // 0.2 seconds in milliseconds.
-
- #define controller_thread_signal_wait_timeout_seconds_d 70
- #define controller_thread_signal_wait_timeout_nanoseconds_d 0
-
- #define controller_thread_lock_read_timeout_seconds_d 3
- #define controller_thread_lock_read_timeout_nanoseconds_d 0
- #define controller_thread_lock_write_timeout_seconds_d 3
- #define controller_thread_lock_write_timeout_nanoseconds_d 0
-
- #define controller_thread_wait_timeout_1_before_d 4
- #define controller_thread_wait_timeout_2_before_d 12
- #define controller_thread_wait_timeout_3_before_d 28
-
- #define controller_thread_wait_timeout_1_seconds_d 0
- #define controller_thread_wait_timeout_1_nanoseconds_d 20000000 // 0.02 seconds in nanoseconds.
- #define controller_thread_wait_timeout_2_seconds_d 0
- #define controller_thread_wait_timeout_2_nanoseconds_d 200000000 // 0.2 seconds in nanoseconds.
- #define controller_thread_wait_timeout_3_seconds_d 2
- #define controller_thread_wait_timeout_3_nanoseconds_d 0
- #define controller_thread_wait_timeout_4_seconds_d 20
- #define controller_thread_wait_timeout_4_nanoseconds_d 0
-
- #define controller_thread_exit_helper_timeout_seconds_d 0
- #define controller_thread_exit_helper_timeout_nanoseconds_d 100000000 // 0.1 seconds in nanoseconds.
-
- #define controller_thread_exit_ready_timeout_seconds_d 0
- #define controller_thread_exit_ready_timeout_nanoseconds_d 500000000 // 0.5 seconds in nanoseconds.
-
- /**
- * States for enabled, designating how to stop the process.
- *
- * controller_thread_*:
- * - enabled_not: The controller is no longer enabled, shut down and abort all work.
- * - enabled: The controller is operating normally.
- * - enabled_execute: The controller is executing another process, all running operations must terminate.
- * - enabled_exit: The controller is shutting down, only process exit rules.
- * - enabled_exit_execute: The controller is executing another process while in failsafe mode, all running operations must terminate.
- * - enabled_exit_ready: The controller is shutting down, only process exit rules, and now ready to send termination signals.
- *
- * controller_thread_cancel_*:
- * - signal: Cancellation is triggered by a signal.
- * - call: Cancellation is explicitly called.
- * - execute: Cancellation is explicitly called due to an "execute" Item Action, when not during Exit.
- * - exit: Cancellation is explicitly called during Exit.
- * - exit_execute: Cancellation is explicitly called due to an "execute" Item Action during Exit.
- */
- enum {
- controller_thread_enabled_not_e = 0,
- controller_thread_enabled_e,
- controller_thread_enabled_execute_e,
- controller_thread_enabled_exit_e,
- controller_thread_enabled_exit_execute_e,
- controller_thread_enabled_exit_ready_e,
- };
-
- enum {
- controller_thread_cancel_signal_e = 0,
- controller_thread_cancel_call_e,
- controller_thread_cancel_execute_e,
- controller_thread_cancel_exit_e,
- controller_thread_cancel_exit_execute_e,
- };
-
- typedef struct {
- uint8_t enabled;
- int signal;
- f_status_t status;
-
- f_thread_id_t id_cleanup;
- f_thread_id_t id_control;
- f_thread_id_t id_entry;
- f_thread_id_t id_rule;
- f_thread_id_t id_signal;
-
- controller_lock_t lock;
- controller_processs_t processs;
- controller_cache_t cache;
- } controller_thread_t;
-
- #define controller_thread_t_initialize { \
- controller_thread_enabled_e, \
- 0, \
- F_okay, \
- f_thread_id_t_initialize, \
- f_thread_id_t_initialize, \
- f_thread_id_t_initialize, \
- f_thread_id_t_initialize, \
- f_thread_id_t_initialize, \
- controller_lock_t_initialize, \
- controller_processs_t_initialize, \
- controller_cache_t_initialize, \
- }
-#endif // _di_controller_thread_t_
-
-/**
- * Fully de-allocate all memory for the given setting without caring about return status.
- *
- * @param thread
- * The thread to de-allocate.
- *
- * @see controller_asynchronouss_resize()
- * @see f_thread_mutex_unlock()
- */
-#ifndef _di_controller_thread_delete_simple_
- extern void controller_thread_delete_simple(controller_thread_t * const thread) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_delete_simple_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_common_thread_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "private-control.h"
-#include "../controller/private-controller_print.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_control_h
-#define _PRIVATE_control_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_control_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "private-control.h"
-#include "../lock/private-lock_print.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * 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
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_control_print_h
+++ /dev/null
-#include "controller.h"
-#include "common/private-common.h"
-#include "control/private-control.h"
-#include "controller/private-controller.h"
-#include "controller/private-controller_print.h"
-#include "entry/private-entry.h"
-#include "lock/private-lock_print.h"
-#include "rule/private-rule.h"
-#include "thread/private-thread.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_main_
- void controller_main(controller_main_t * const main) {
-
- if (F_status_is_error(main->setting.state.status)) return;
-
- main->setting.state.status = F_okay;
-
- if (main->setting.flag & controller_main_flag_version_copyright_help_e) {
- if (main->setting.flag & controller_main_flag_help_e) {
- controller_print_message_help(&main->program.message);
- }
- else if (main->setting.flag & controller_main_flag_version_e) {
- fll_program_print_version(&main->program.message, controller_program_version_s);
- }
- else if (main->setting.flag & controller_main_flag_copyright_e) {
- fll_program_print_copyright(&main->program.message, fll_program_copyright_year_author_s);
- }
-
- return;
- }
-
- f_string_static_t * const argv = main->program.parameters.arguments.array;
-
- main->setting.state.status = f_path_current(F_false, &main->process->path_current);
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "f_path_current", fll_error_file_flag_fallback_e);
- }
- else {
- if (main->program.parameters.array[controller_parameter_settings_e].result & f_console_result_found_e) {
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(main->program.error.to, 0);
-
- fl_print_format("%r%[%QThe parameter '%]", main->program.error.to, f_string_eol_s, main->program.error.context, main->program.error.prefix, main->program.error.context);
- fl_print_format(f_string_format_rr_single_s.string, main->program.error.to, main->program.context.set.notable, f_console_symbol_long_normal_s, controller_long_settings_s, main->program.context.set.notable);
- fl_print_format("%[' is specified, but no value is given.%]%r", main->program.error.to, main->program.error.context, main->program.error.context, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.error.to, 0);
- }
-
- main->setting.state.status = F_status_set_error(F_parameter);
- }
- else if (main->program.parameters.array[controller_parameter_settings_e].locations.used) {
- const f_number_unsigned_t index = main->program.parameters.array[controller_parameter_settings_e].values.array[main->program.parameters.array[controller_parameter_settings_e].values.used - 1];
-
- main->setting.state.status = controller_path_canonical_relative(main->process, argv[index], &main->process->path_setting);
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_file_print(&main->program.error, F_status_set_fine(main->setting.state.status), "controller_path_canonical_relative", fll_error_file_flag_fallback_e, argv[index], f_file_operation_verify_s, fll_error_file_type_path_e);
- }
- }
- else {
- main->process->path_setting.used = 0;
-
- if (main->setting.flag & controller_main_flag_init_e) {
- main->setting.state.status = f_string_dynamic_append(*main->setting.default_path_setting_init, &main->process->path_setting);
- }
- else {
- main->setting.state.status = f_string_dynamic_append(*main->setting.default_path_setting, &main->process->path_setting);
- }
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "f_string_dynamic_append", fll_error_file_flag_fallback_e);
- }
- }
- }
-
- if (F_status_is_error_not(main->setting.state.status)) {
- if (main->program.parameters.array[controller_parameter_pid_e].result & f_console_result_found_e) {
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(main->program.error.to, 0);
-
- fl_print_format("%r%[%QThe parameter '%]", main->program.error.to, f_string_eol_s, main->program.error.context, main->program.error.prefix, main->program.error.context);
- fl_print_format(f_string_format_rr_single_s.string, main->program.error.to, main->program.context.set.notable, f_console_symbol_long_normal_s, controller_long_pid_s, main->program.context.set.notable);
- fl_print_format("%[' is specified, but no value is given.%]%r", main->program.error.to, main->program.error.context, main->program.error.context, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.error.to, 0);
- }
-
- main->setting.state.status = F_status_set_error(F_parameter);
- }
- else if (main->program.parameters.array[controller_parameter_pid_e].locations.used) {
- main->process->path_pid.used = 0;
-
- const f_number_unsigned_t index = main->program.parameters.array[controller_parameter_pid_e].values.array[main->program.parameters.array[controller_parameter_pid_e].values.used - 1];
-
- if (argv[index].used) {
- main->setting.state.status = controller_path_canonical_relative(main->process, argv[index], &main->process->path_pid);
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_file_print(&main->program.error, F_status_set_fine(main->setting.state.status), "controller_path_canonical_relative", fll_error_file_flag_fallback_e, argv[index], f_file_operation_verify_s, fll_error_file_type_path_e);
- }
- }
- }
- }
-
- if (F_status_is_error_not(main->setting.state.status) && !main->process->path_pid.used && !main->program.parameters.array[controller_parameter_pid_e].locations.used) {
- if (main->setting.flag & controller_main_flag_init_e) {
- main->setting.state.status = f_string_dynamic_append(*main->setting.default_path_pid_init, &main->process->path_pid);
- }
- else {
- main->setting.state.status = f_string_dynamic_append(*main->setting.default_path_pid, &main->process->path_pid);
- }
-
- if (F_status_is_error_not(main->setting.state.status)) {
- main->setting.state.status = f_string_dynamic_append(f_path_separator_s, &main->process->path_pid);
- }
-
- if (F_status_is_error_not(main->setting.state.status)) {
- main->setting.state.status = f_string_dynamic_append(*main->setting.default_path_pid_prefix, &main->process->path_pid);
- }
-
- if (F_status_is_error_not(main->setting.state.status)) {
- main->setting.state.status = f_string_dynamic_append(main->process->name_entry, &main->process->path_pid);
- }
-
- if (F_status_is_error_not(main->setting.state.status)) {
- main->setting.state.status = f_string_dynamic_append(*main->setting.default_path_pid_suffix, &main->process->path_pid);
- }
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "f_string_dynamic_append", fll_error_file_flag_fallback_e);
- }
- }
-
- if (F_status_is_error_not(main->setting.state.status)) {
- if (main->program.parameters.array[controller_parameter_cgroup_e].result & f_console_result_found_e) {
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(main->program.error.to, 0);
-
- fl_print_format("%r%[%QThe parameter '%]", main->program.error.to, f_string_eol_s, main->program.error.context, main->program.error.prefix, main->program.error.context);
- fl_print_format(f_string_format_rr_single_s.string, main->program.error.to, main->program.context.set.notable, f_console_symbol_long_normal_s, controller_long_cgroup_s, main->program.context.set.notable);
- fl_print_format("%[' is specified, but no value is given.%]%r", main->program.error.to, main->program.error.context, main->program.error.context, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.error.to, 0);
- }
-
- main->setting.state.status = F_status_set_error(F_parameter);
- }
- else if (main->program.parameters.array[controller_parameter_cgroup_e].locations.used) {
- const f_number_unsigned_t index = main->program.parameters.array[controller_parameter_cgroup_e].values.array[main->program.parameters.array[controller_parameter_cgroup_e].values.used - 1];
-
- if (argv[index].used) {
- main->setting.state.status = controller_path_canonical_relative(main->process, argv[index], &main->process->path_cgroup);
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_file_print(&main->program.error, F_status_set_fine(main->setting.state.status), "controller_path_canonical_relative", fll_error_file_flag_fallback_e, argv[index], f_file_operation_verify_s, fll_error_file_type_path_e);
- }
- else {
- main->setting.state.status = f_string_append_assure(F_path_separator_s, 1, &main->process->path_cgroup);
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "f_string_append_assure", fll_error_file_flag_fallback_e);
- }
- }
- }
- else {
- if (main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(main->program.warning.to, 0);
-
- fl_print_format("%r%[%QThe parameter '%]", main->program.warning.to, f_string_eol_s, main->program.warning.context, main->program.warning.prefix, main->program.warning.context);
- fl_print_format(f_string_format_rr_single_s.string, main->program.warning.to, main->program.context.set.notable, f_console_symbol_long_normal_s, controller_long_cgroup_s, main->program.context.set.notable);
- fl_print_format("%[' must be a file directory path but instead is an empty string, falling back to the default.%]%r", main->program.warning.to, main->program.warning.context, main->program.warning.context, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.warning.to, 0);
- }
- }
- }
- }
-
- if (F_status_is_error_not(main->setting.state.status) && (main->program.parameters.array[controller_parameter_daemon_e].result & f_console_result_found_e)) {
- if (main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e) {
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(main->program.error.to, 0);
-
- fl_print_format("%r%[%QThe parameter '%]", main->program.error.to, f_string_eol_s, main->program.error.context, main->program.error.prefix, main->program.error.context);
- fl_print_format("%[' must not be specified with the parameter '%]", main->program.error.to, main->program.error.context, main->program.error.context);
- fl_print_format(f_string_format_rr_single_s.string, main->program.error.to, main->program.context.set.notable, f_console_symbol_long_normal_s, controller_long_daemon_s, main->program.context.set.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, main->program.error.to, main->program.error.context, main->program.error.context, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.error.to, 0);
- }
-
- main->setting.state.status = F_status_set_error(F_parameter);
- }
- }
-
- // Handle defaults dependent on the "as init" execution state.
- if (main->setting.flag & controller_main_flag_init_e) {
- main->process->entry.pid = controller_entry_pid_disable_e;
- main->process->entry.show = controller_entry_show_init_e;
-
- if (main->program.parameters.array[controller_parameter_interruptible_e].result & f_console_result_found_e) {
- main->process->flag |= controller_setting_flag_interruptible_e;
- }
- else {
- main->process->flag &= ~controller_setting_flag_interruptible_e;
- }
- }
- else {
- if (main->program.parameters.array[controller_parameter_uninterruptible_e].result & f_console_result_found_e) {
- main->process->flag &= ~controller_setting_flag_interruptible_e;
- }
- else {
- main->process->flag |= controller_setting_flag_interruptible_e;
- }
- }
-
- if (F_status_is_error_not(main->setting.state.status)) {
- f_signal_set_fill(&main->program.signal.set);
-
- main->setting.state.status = f_thread_signal_mask(SIG_BLOCK, &main->program.signal.set, 0);
-
- if (F_status_is_error_not(main->setting.state.status)) {
- main->setting.state.status = f_signal_open(&main->program.signal);
- }
-
- // If there is an error opening a signal descriptor, then do not handle signals.
- if (F_status_is_error(main->setting.state.status)) {
- f_signal_mask(SIG_UNBLOCK, &main->program.signal.set, 0);
- f_signal_close(&main->program.signal);
- }
-
- // A control file path is required.
- if (!main->process->path_cgroup.used) {
- main->setting.state.status = f_string_append_nulless(F_control_group_path_system_prefix_s, F_control_group_path_system_prefix_s_length, &main->process->path_cgroup);
-
- if (F_status_is_error_not(main->setting.state.status)) {
- main->setting.state.status = f_string_append_nulless(F_control_group_path_system_default_s, F_control_group_path_system_default_s_length, &main->process->path_cgroup);
- }
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "f_string_append_nulless", fll_error_file_flag_fallback_e);
- }
- else {
- main->setting.state.status = f_string_append_assure(F_path_separator_s, 1, &main->process->path_cgroup);
-
- if (F_status_is_error(main->setting.state.status)) {
- fll_error_print(&main->program.error, F_status_set_fine(main->setting.state.status), "f_string_append_assure", fll_error_file_flag_fallback_e);
- }
- }
- }
- }
-
- if (F_status_is_error_not(main->setting.state.status)) {
- main->setting.state.status = controller_thread_main(main, main->process);
- }
-
- // Ensure a newline is always put at the end of the program execution, unless in quiet mode.
- if (F_status_is_error(main->setting.state.status) && main->program.output.verbosity != f_console_verbosity_quiet_e) {
- if (F_status_set_fine(main->setting.state.status) == F_interrupt) {
- f_file_stream_flush(main->program.output.to);
- }
-
- fll_print_dynamic_raw(f_string_eol_s, main->program.output.to);
- }
-
- if (main->setting.state.status != F_child && (main->process->flag & controller_setting_flag_pid_created_e)) {
- const f_status_t status_delete = controller_file_pid_delete(main->program.pid, main->process->path_pid);
-
- if (F_status_is_error(status_delete) && main->program.warning.verbosity == f_console_verbosity_debug_e) {
- if (F_status_set_fine(status_delete) == F_number_not) {
- controller_lock_print(main->program.warning.to, 0);
-
- fl_print_format("%r%[%QThe pid file '%]", main->program.warning.to, f_string_eol_s, main->program.warning.context, main->program.warning.prefix, main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, main->program.warning.to, main->program.warning.notable, main->process->path_pid, main->program.warning.notable);
- fl_print_format("%[' must not be specified with the parameter '%]", main->program.warning.to, main->program.warning.context, main->program.warning.context);
- fl_print_format("%[%i%]", main->program.warning.to, main->program.warning.notable, main->program.pid, main->program.warning.notable);
- fl_print_format("%[' doesn't contain the expected number, not deleting file.%]%r", main->program.warning.to, main->program.warning.context, main->program.warning.context, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.warning.to, 0);
- }
- else if (F_status_set_fine(status_delete) != F_interrupt) {
- fll_error_file_print(&main->program.warning, F_status_set_fine(status_delete), "controller_file_pid_delete", fll_error_file_flag_fallback_e, main->process->path_pid, f_file_operation_delete_s, fll_error_file_type_file_e);
- }
- }
- }
-
- if (main->setting.state.status != F_child && main->process->path_control.used) {
- f_socket_disconnect(&main->process->control.server, f_socket_close_read_write_e);
-
- if (!(main->process->control.flag & controller_control_flag_readonly_e)) {
- f_file_remove(main->process->path_control);
- }
- }
- }
-#endif // _di_controller_main_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- *
- * This is the Controller program.
- *
- * This program utilizes the Featureless Linux Library.
- * This program provides system service management, much like sysvcontroller and controllerng.
- * This program can be controlled from user-space via the "control" program.
- * This program can be used in an initrd and should be capable of pivot root operations.
- */
-#ifndef _controller_h
-#define _controller_h
-
-// Include pre-requirements.
-#ifndef _GNU_SOURCE
- #define _GNU_SOURCE
-#endif // _GNU_SOURCE
-
-// Libc includes.
-#include <sched.h>
-#include <string.h>
-#include <time.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <linux/sched.h>
-#include <unistd.h>
-
-// FLL-0 includes.
-#include <fll/level_0/type.h>
-#include <fll/level_0/status.h>
-#include <fll/level_0/memory.h>
-#include <fll/level_0/type_array.h>
-#include <fll/level_0/string.h>
-#include <fll/level_0/utf.h>
-#include <fll/level_0/account.h>
-#include <fll/level_0/capability.h>
-#include <fll/level_0/color.h>
-#include <fll/level_0/compare.h>
-#include <fll/level_0/console.h>
-#include <fll/level_0/control_group.h>
-#include <fll/level_0/directory.h>
-#include <fll/level_0/environment.h>
-#include <fll/level_0/execute.h>
-#include <fll/level_0/file.h>
-#include <fll/level_0/fss.h>
-#include <fll/level_0/iki.h>
-#include <fll/level_0/path.h>
-#include <fll/level_0/pipe.h>
-#include <fll/level_0/print.h>
-#include <fll/level_0/rip.h>
-#include <fll/level_0/signal.h>
-#include <fll/level_0/socket.h>
-#include <fll/level_0/status_string.h>
-
-// FLL-1 includes.
-#include <fll/level_1/control_group.h>
-#include <fll/level_1/environment.h>
-#include <fll/level_1/fss.h>
-#include <fll/level_1/iki.h>
-#include <fll/level_1/path.h>
-#include <fll/level_1/print.h>
-#include <fll/level_1/status_string.h>
-
-// FLL-2 includes.
-#include <fll/level_2/control_group.h>
-#include <fll/level_2/error.h>
-#include <fll/level_2/execute.h>
-#include <fll/level_2/fss.h>
-#include <fll/level_2/fss/basic_list.h>
-#include <fll/level_2/fss/extended.h>
-#include <fll/level_2/fss/extended_list.h>
-#include <fll/level_2/fss/payload.h>
-#include <fll/level_2/print.h>
-#include <fll/level_2/program.h>
-
-// Controller includes.
-#include <program/controller/common.h>
-#include <program/controller/print.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Execute main program.
- *
- * If main.program.signal is non-zero, then this blocks and handles the following signals: @todo review and upadate this comment.
- * - 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.setting.state.status:
- * F_okay on success.
- * F_child if this is a child process returning.
- *
- * F_interrupt (with error bit) on interrupt signal received.
- */
-#ifndef _di_controller_main_
- extern void controller_main(controller_main_t * const main);
-#endif // _di_controller_main_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _controller_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "private-controller.h"
-#include "private-controller_print.h"
-#include "../entry/private-entry_print.h"
-#include "../lock/private-lock_print.h"
-#include "../thread/private-thread_control.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_range_after_number_sign_
- f_range_t controller_range_after_number_sign(const f_string_static_t buffer, const f_range_t range) {
-
- f_range_t result = range;
-
- for (; result.start <= result.stop; ++result.start) {
-
- if (!buffer.string[result.start]) continue;
-
- if (buffer.string[result.start] == f_string_ascii_minus_s.string[0] || buffer.string[result.start] == f_string_ascii_plus_s.string[0]) {
- ++result.start;
- }
-
- break;
- } // for
-
- return result;
- }
-#endif // _di_controller_range_after_number_sign_
-
-#ifndef _di_controller_file_load_
- f_status_t controller_file_load(const controller_global_t global, const bool required, const f_string_static_t path_prefix, const f_string_static_t path_name, const f_string_static_t path_suffix, controller_cache_t * const cache) {
-
- f_status_t status = F_okay;
- f_file_t file = f_file_t_initialize;
-
- cache->action.name_file.used = 0;
- cache->buffer_file.used = 0;
-
- macro_f_time_simple_t_clear(cache->timestamp);
-
- status = f_string_dynamic_append(path_prefix, &cache->action.name_file);
-
- if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(f_path_separator_s, &cache->action.name_file);
- }
-
- if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(path_name, &cache->action.name_file);
- }
-
- if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(f_path_extension_separator_s, &cache->action.name_file);
- }
-
- if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(path_suffix, &cache->action.name_file);
- }
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_append", F_true);
-
- return status;
- }
-
- f_string_static_t path = f_string_static_t_initialize;
-
- if (global.setting->path_setting.used) {
- path.used = global.setting->path_setting.used + F_path_separator_s_length + cache->action.name_file.used;
- }
- else {
- path.used = cache->action.name_file.used;
- }
-
- f_char_t path_string[path.used + 1];
- path.string = path_string;
-
- if (global.setting->path_setting.used) {
- memcpy(path_string, global.setting->path_setting.string, sizeof(f_char_t) * global.setting->path_setting.used);
- memcpy(path_string + global.setting->path_setting.used + F_path_separator_s_length, cache->action.name_file.string, sizeof(f_char_t) * cache->action.name_file.used);
-
- path_string[global.setting->path_setting.used] = f_path_separator_s.string[0];
- }
- else {
- memcpy(path_string, cache->action.name_file.string, sizeof(f_char_t) * cache->action.name_file.used);
- }
-
- path_string[path.used] = 0;
-
-
- status = f_file_stream_open(path, f_string_empty_s, &file);
-
- if (F_status_is_error(status)) {
- if (!required && F_status_set_fine(status) == F_file_found_not) {
- f_file_stream_flush(file);
- f_file_stream_close(&file);
-
- return F_file_found_not;
- }
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_print_error_file(global.thread, &global.main->program.error, F_status_set_fine(status), "f_file_stream_open", F_true, path, f_file_operation_open_s, fll_error_file_type_file_e);
- }
- }
- else {
- status = f_file_stream_read(file, &cache->buffer_file);
-
- if (F_status_is_error(status)) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_print_error_file(global.thread, &global.main->program.error, F_status_set_fine(status), "f_file_stream_read", F_true, path, f_file_operation_read_s, fll_error_file_type_file_e);
- }
- }
- }
-
- f_file_stream_flush(file);
- f_file_stream_close(&file);
-
- if (F_status_is_error_not(status)) {
- struct stat stat_file;
-
- status = f_file_stat(path, F_true, &stat_file);
-
- if (F_status_is_error(status)) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_print_error_file(global.thread, &global.main->program.error, F_status_set_fine(status), "f_file_stat", F_true, path, f_file_operation_stat_s, fll_error_file_type_file_e);
- }
- }
- else {
- cache->timestamp.seconds = stat_file.st_ctim.tv_sec;
- cache->timestamp.seconds_nano = stat_file.st_ctim.tv_nsec;
- }
- }
-
- if (F_status_is_error(status)) return status;
-
- return F_okay;
- }
-#endif // _di_controller_file_load_
-
-#ifndef _di_controller_file_pid_create_
- f_status_t controller_file_pid_create(const pid_t pid, const f_string_static_t path) {
-
- f_status_t status = F_okay;
-
- // The file exists, do not attempt to overwrite.
- if (f_file_exists(path, F_true) == F_true) {
- return F_status_set_error(F_file_found);
- }
-
- {
- f_string_dynamic_t path_directory = f_string_dynamic_t_initialize;
-
- status = f_file_name_directory(path, &path_directory);
-
- if (F_status_is_error_not(status)) {
- status = f_directory_exists(path_directory);
- }
-
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &path_directory.string, &path_directory.used, &path_directory.size);
-
- if (F_status_is_error(status)) return status;
-
- // The directory does not exist so do not bother attempting to create a pid file.
- if (status == F_false) {
- return F_status_set_error(F_directory_not);
- }
- }
-
- f_file_t file = f_file_t_initialize;
-
- file.flag = F_file_flag_write_only_d;
-
- status = f_file_stream_open(path, f_file_open_mode_read_truncate_s, &file);
- if (F_status_is_error(status)) return status;
-
- fll_print_format("%i%r", file, pid, f_string_eol_s);
-
- f_file_stream_flush(file);
- f_file_stream_close(&file);
-
- if (F_status_is_error(status)) return status;
-
- return F_okay;
- }
-#endif // _di_controller_file_pid_create_
-
-#ifndef _di_controller_file_pid_delete_
- f_status_t controller_file_pid_delete(const pid_t pid, const f_string_static_t path) {
-
- // Only delete if the file exists and there is no error while checking.
- if (f_file_exists(path, F_true) != F_true) {
- return F_okay;
- }
-
- f_status_t status = F_okay;
- f_file_t pid_file = f_file_t_initialize;
-
- status = f_file_stream_open(path, f_file_open_mode_read_s, &pid_file);
- if (F_status_is_error(status)) return status;
-
- f_string_dynamic_t pid_buffer = f_string_dynamic_t_initialize;
-
- status = f_file_stream_read(pid_file, &pid_buffer);
-
- if (F_status_is_error_not(status)) {
- status = f_file_stream_flush(pid_file);
- }
-
- if (F_status_is_error_not(status)) {
- status = f_file_stream_close(&pid_file);
- }
-
- if (F_status_is_error_not(status)) {
- f_number_unsigned_t number = 0;
- f_range_t range = macro_f_range_t_initialize_2(pid_buffer.used);
-
- for (; range.start < pid_buffer.used; ++range.start) {
- if (!isspace(pid_buffer.string[range.start])) break;
- } // for
-
- for (; range.stop > 0; --range.stop) {
- if (!isspace(pid_buffer.string[range.stop])) break;
- } // for
-
- status = fl_conversion_dynamic_partial_to_unsigned(fl_conversion_data_base_10_c, pid_buffer, range, &number);
-
- if (F_status_is_error_not(status) && number == pid) {
- status = f_file_remove(path);
- }
- else {
- status = F_status_set_error(F_number_not);
- }
- }
-
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &pid_buffer.string, &pid_buffer.used, &pid_buffer.size);
-
- return status;
- }
-#endif // _di_controller_file_pid_delete_
-
-#ifndef _di_controller_file_pid_read_
- f_status_t controller_file_pid_read(const f_string_static_t path, pid_t * const pid) {
-
- *pid = 0;
-
- f_status_t status = f_file_exists(path, F_true);
- if (F_status_is_error(status)) return status;
-
- if (status != F_true) {
- return F_data_not;
- }
-
- f_file_t pid_file = f_file_t_initialize;
-
- status = f_file_stream_open(path, f_file_open_mode_read_s, &pid_file);
- if (F_status_is_error(status)) return status;
-
- f_string_dynamic_t pid_buffer = f_string_dynamic_t_initialize;
-
- status = f_file_stream_read(pid_file, &pid_buffer);
-
- if (F_status_is_error_not(status)) {
- status = f_file_stream_flush(pid_file);
- }
-
- if (F_status_is_error_not(status)) {
- status = f_file_stream_close(&pid_file);
- }
-
- if (F_status_is_error_not(status)) {
- f_number_unsigned_t number = 0;
- f_range_t range = macro_f_range_t_initialize_2(pid_buffer.used);
-
- for (; range.start < pid_buffer.used; ++range.start) {
- if (!isspace(pid_buffer.string[range.start])) break;
- } // for
-
- for (; range.stop > 0; --range.stop) {
- if (!isspace(pid_buffer.string[range.stop])) break;
- } // for
-
- status = fl_conversion_dynamic_partial_to_unsigned(fl_conversion_data_base_10_c, pid_buffer, range, &number);
-
- if (F_status_is_error_not(status)) {
- *pid = (pid_t) number;
- }
- }
-
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &pid_buffer.string, &pid_buffer.used, &pid_buffer.size);
-
- return status;
- }
-#endif // _di_controller_file_pid_read_
-
-#ifndef _di_controller_get_id_user_
- f_status_t controller_get_id_user(const f_string_static_t buffer, const f_range_t range, controller_cache_t * const cache, uid_t * const id) {
-
- f_number_unsigned_t number = 0;
-
- f_status_t status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, buffer, range, &number);
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) == F_number) {
- cache->action.generic.used = 0;
-
- status = f_rip_dynamic_partial_nulless(buffer, range, &cache->action.generic);
- if (F_status_is_error(status)) return status;
-
- status = f_account_id_by_name(cache->action.generic, id);
- if (F_status_is_error(status)) return status;
-
- if (status == F_exist_not) {
- return F_status_set_error(F_exist_not);
- }
-
- return F_okay;
- }
-
- return status;
- }
-
- if (number > F_type_size_32_unsigned_d) {
- return F_status_set_error(F_number_too_large);
- }
-
- return status;
- }
-#endif // _di_controller_get_id_user_
-
-#ifndef _di_controller_get_id_group_
- f_status_t controller_get_id_group(const f_string_static_t buffer, const f_range_t range, controller_cache_t * const cache, gid_t * const id) {
-
- f_number_unsigned_t number = 0;
-
- f_status_t status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, buffer, range, &number);
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) == F_number) {
- cache->action.generic.used = 0;
-
- status = f_rip_dynamic_partial_nulless(buffer, range, &cache->action.generic);
- if (F_status_is_error(status)) return status;
-
- status = f_account_group_id_by_name(cache->action.generic, id);
- if (F_status_is_error(status)) return status;
-
- if (status == F_exist_not) {
- return F_status_set_error(F_exist_not);
- }
-
- return F_okay;
- }
-
- return status;
- }
-
- if (number > F_type_size_32_unsigned_d) {
- return F_status_set_error(F_number_too_large);
- }
-
- return status;
- }
-#endif // _di_controller_get_id_group_
-
-#ifndef _di_controller_path_canonical_relative_
- f_status_t controller_path_canonical_relative(const controller_process_t * const setting, const f_string_static_t source, f_string_dynamic_t * const destination) {
-
- {
- const f_status_t status = fl_path_canonical(source, destination);
- if (F_status_is_error(status)) return status;
- }
-
- if (destination->used >= setting->path_current.used) {
- const f_range_t range = macro_f_range_t_initialize_2(setting->path_current.used);
-
- if (f_compare_dynamic_partial_string(destination->string, setting->path_current, destination->used, range) == F_equal_to) {
- f_number_unsigned_t length = destination->used - setting->path_current.used;
-
- if (length) {
- f_char_t temporary[--length];
- temporary[length] = 0;
-
- memcpy(temporary, destination->string + setting->path_current.used + 1, sizeof(f_char_t) * length);
- memcpy(destination->string, temporary, sizeof(f_char_t) * length);
-
- destination->string[length] = 0;
- destination->used = length;
- }
- else {
- destination->used = 0;
- }
- }
- }
-
- return F_okay;
- }
-#endif // _di_controller_path_canonical_relative_
-
-#ifndef _di_controller_perform_ready_
- f_status_t controller_perform_ready(const controller_global_t * const global, controller_cache_t * const cache, const bool is_entry) {
-
- if (!is_entry) {
- return F_okay;
- }
-
- if (global->main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e) {
- if ((global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) && global->main->program.output.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%rPID file '", global->main->program.output.to, f_string_eol_s);
- fl_print_format("%[%Q%]'.%r", global->main->program.output.to, global->main->program.context.set.notable, global->setting->path_pid, global->main->program.context.set.notable, f_string_eol_s);
-
- if (global->setting->path_control.used) {
- fl_print_format("%rControl socket '", global->main->program.output.to, f_string_eol_s);
- fl_print_format(f_string_format_Q_single_s.string, global->main->program.output.to, global->main->program.context.set.notable, global->setting->path_control, global->main->program.context.set.notable);
- fl_print_format("'.%r", global->main->program.output.to, f_string_eol_s);
- }
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
-
- return F_okay;
- }
-
- f_status_t status = F_okay;
-
- if (global->setting->entry.pid != controller_entry_pid_disable_e && !global->setting->path_pid.used) {
- status = controller_file_pid_create(global->main->program.pid, global->setting->path_pid);
-
- // Report pid file error but because this could be an "init" program, consider the pid file as optional and continue on.
- if (F_status_is_error(status)) {
-
- // Always return immediately on memory errors.
- if (F_status_set_fine(status) == F_memory_not) {
- if (global->main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global->main->program.error.to, global->thread);
-
- controller_print_error_file(0, &global->main->program.error, F_status_set_fine(status), "controller_file_pid_create", F_true, global->setting->path_pid, f_file_operation_create_s, fll_error_file_type_file_e);
-
- f_file_stream_lock(global->main->program.error.to);
-
- controller_entry_print_error_cache(is_entry, &global->main->program.error, cache->action);
-
- controller_unlock_print_flush(global->main->program.error.to, global->thread);
- }
-
- return status;
- }
-
- if (global->main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global->main->program.warning.to, global->thread);
-
- if (F_status_set_fine(status) == F_read_only) {
- fl_print_format("%r%[%QThe pid file '%]", global->main->program.warning.to, f_string_eol_s, global->main->program.warning.context, global->main->program.warning.prefix, global->main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global->main->program.warning.to, global->main->program.warning.notable, global->setting->path_pid, global->main->program.warning.notable);
- fl_print_format("%[' could not be written because the destination is read only.%]%r", global->main->program.warning.to, global->main->program.warning.context, global->main->program.warning.context, f_string_eol_s);
- }
- else {
- controller_print_error_file(0, &global->main->program.warning, F_status_set_fine(status), "controller_file_pid_create", F_true, global->setting->path_pid, f_file_operation_create_s, fll_error_file_type_file_e);
- }
-
- controller_entry_print_error_cache(is_entry, &global->main->program.warning, cache->action);
-
- controller_unlock_print_flush(global->main->program.warning.to, global->thread);
- }
-
- status = F_okay;
- }
- else {
- global->setting->flag |= controller_setting_flag_pid_created_e;
-
- if (global->main->program.output.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%rPID file '", global->main->program.output.to, f_string_eol_s);
- fl_print_format("%[%Q%]' created.%r", global->main->program.output.to, global->main->program.context.set.notable, global->setting->path_pid, global->main->program.context.set.notable, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
- }
- }
-
- // Disabled, all parts are not yet implemented.
- /*if (global->setting->path_control.used) {
- status = controller_perform_ready_socket(global, cache, is_entry);
-
- // Do not fail on non-memory errors related to creating the control socket.
- if (F_status_is_error(status) && F_status_set_fine(status) != F_memory) {
- status = F_okay;
- }
- }*/
-
- return status;
- }
-#endif // _di_controller_perform_ready_
-
-#ifndef _di_controller_perform_ready_socket_
- f_status_t controller_perform_ready_socket(const controller_global_t * const global, controller_cache_t * const cache, const bool is_entry) {
-
- f_status_t status = F_okay;
-
- if (global->setting->control.flag & controller_control_flag_readonly_e) {
- if (f_file_exists(global->setting->path_control, F_true) != F_true) {
- if (global->main->program.output.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%r%[%QControl socket '%]", global->main->program.warning.to, f_string_eol_s, global->main->program.warning.context, global->main->program.warning.prefix, global->main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global->main->program.output.to, global->main->program.context.set.notable, global->setting->path_control, global->main->program.context.set.notable);
- fl_print_format("' .%r", global->main->program.output.to, f_string_eol_s);
- fl_print_format("%[' cannot be found while read only mode is enabled and so the Control socket is unavailable.%]%r", global->main->program.output.to, global->main->program.warning.context, global->main->program.warning.context, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
-
- return F_data_not;
- }
- }
-
- status = f_socket_create(&global->setting->control.server);
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) == F_memory_not) {
- controller_print_error(global->thread, &global->main->program.error, F_status_set_fine(status), "f_socket_create", F_true);
- }
- else if (global->main->program.output.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%r%[%QControl socket '%]", global->main->program.warning.to, f_string_eol_s, global->main->program.warning.context, global->main->program.warning.prefix, global->main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global->main->program.output.to, global->main->program.context.set.notable, global->setting->path_control, global->main->program.context.set.notable);
- fl_print_format("%[' could not be created, code %]", global->main->program.output.to, global->main->program.warning.context, global->main->program.warning.context);
- fl_print_format(f_string_format_ui_single_s.string, global->main->program.output.to, global->main->program.context.set.notable, F_status_set_fine(status), global->main->program.context.set.notable);
- fl_print_format(f_string_format_sentence_end_s.string, global->main->program.output.to, global->main->program.warning.context, global->main->program.warning.context, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
-
- return status;
- }
-
- if (!(global->setting->control.flag & controller_control_flag_readonly_e)) {
- status = f_file_remove(global->setting->path_control);
-
- if (F_status_set_fine(status) == F_memory_not) {
- controller_print_error(global->thread, &global->main->program.error, F_status_set_fine(status), "f_file_remove", F_true);
-
- return status;
- }
- }
-
- global->setting->control.server.name = global->setting->path_control;
-
- status = f_socket_bind(&global->setting->control.server);
-
- if (F_status_is_error(status)) {
- f_socket_disconnect(&global->setting->control.server, f_socket_close_fast_e);
-
- if (!(global->setting->control.flag & controller_control_flag_readonly_e)) {
- f_file_remove(global->setting->path_control);
- }
-
- if (F_status_set_fine(status) == F_memory_not) {
- controller_print_error(global->thread, &global->main->program.error, F_status_set_fine(status), "f_socket_bind", F_true);
- }
- else if (global->main->program.output.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%r%[%QControl socket '%]", global->main->program.warning.to, f_string_eol_s, global->main->program.warning.context, global->main->program.warning.prefix, global->main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global->main->program.output.to, global->main->program.context.set.notable, global->setting->path_control, global->main->program.context.set.notable);
- fl_print_format("%[' could not be bound, code %]", global->main->program.output.to, global->main->program.warning.context, global->main->program.warning.context);
- fl_print_format(f_string_format_ui_single_s.string, global->main->program.output.to, global->main->program.context.set.notable, F_status_set_fine(status), global->main->program.context.set.notable);
- fl_print_format(f_string_format_sentence_end_s.string, global->main->program.output.to, global->main->program.warning.context, global->main->program.warning.context, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
-
- return status;
- }
-
- if (global->setting->control.flag & (controller_control_flag_has_user_e | controller_control_flag_has_group_e)) {
- status = f_file_role_change(global->setting->path_control, global->setting->control.user, global->setting->control.group, F_true);
-
- if (F_status_is_error(status)) {
- f_socket_disconnect(&global->setting->control.server, f_socket_close_fast_e);
-
- if (!(global->setting->control.flag & controller_control_flag_readonly_e)) {
- f_file_remove(global->setting->path_control);
- }
-
- if (F_status_set_fine(status) == F_memory_not) {
- controller_print_error(global->thread, &global->main->program.error, F_status_set_fine(status), "f_file_role_change", F_true);
- }
- else if (global->main->program.output.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%r%[%QControl socket '%]", global->main->program.warning.to, f_string_eol_s, global->main->program.warning.context, global->main->program.warning.prefix, global->main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global->main->program.output.to, global->main->program.context.set.notable, global->setting->path_control, global->main->program.context.set.notable);
- fl_print_format("%[' failed to set file roles, code %]", global->main->program.output.to, global->main->program.warning.context, global->main->program.warning.context);
- fl_print_format(f_string_format_ui_single_s.string, global->main->program.output.to, global->main->program.context.set.notable, F_status_set_fine(status), global->main->program.context.set.notable);
- fl_print_format(f_string_format_sentence_end_s.string, global->main->program.output.to, global->main->program.warning.context, global->main->program.warning.context, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
-
- return status;
- }
- }
-
- if (global->setting->control.flag & controller_control_flag_has_mode_e) {
- status = f_file_mode_set(global->setting->path_control, global->setting->control.mode);
-
- if (F_status_is_error(status)) {
- f_socket_disconnect(&global->setting->control.server, f_socket_close_fast_e);
-
- if (!(global->setting->control.flag & controller_control_flag_readonly_e)) {
- f_file_remove(global->setting->path_control);
- }
-
- if (F_status_set_fine(status) == F_memory_not) {
- controller_print_error(global->thread, &global->main->program.error, F_status_set_fine(status), "f_file_role_change", F_true);
- }
- else if (global->main->program.output.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%r%[%QControl socket '%]", global->main->program.warning.to, f_string_eol_s, global->main->program.warning.context, global->main->program.warning.prefix, global->main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global->main->program.output.to, global->main->program.context.set.notable, global->setting->path_control, global->main->program.context.set.notable);
- fl_print_format("%[' failed to set file mode, code %]", global->main->program.output.to, global->main->program.warning.context, global->main->program.warning.context);
- fl_print_format(f_string_format_ui_single_s.string, global->main->program.output.to, global->main->program.context.set.notable, F_status_set_fine(status), global->main->program.context.set.notable);
- fl_print_format(f_string_format_sentence_end_s.string, global->main->program.output.to, global->main->program.warning.context, global->main->program.warning.context, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
-
- return status;
- }
- }
-
- if (global->main->program.output.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%rControl socket '", global->main->program.output.to, f_string_eol_s);
- fl_print_format(f_string_format_Q_single_s.string, global->main->program.output.to, global->main->program.context.set.notable, global->setting->path_control, global->main->program.context.set.notable);
- fl_print_format("' created.%r", global->main->program.output.to, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
-
- // Disabled, not yet implemented.
- //status = f_thread_create(0, &global->thread->id_control, &controller_thread_control, (void *) global);
-
- if (status == F_child) {
- return status;
- }
-
- if (F_status_is_error(status)) {
- f_socket_disconnect(&global->setting->control.server, f_socket_close_fast_e);
-
- if (!(global->setting->control.flag & controller_control_flag_readonly_e)) {
- f_file_remove(global->setting->path_control);
- }
-
- if (global->thread->id_control) {
- f_thread_cancel(global->thread->id_control);
- f_thread_join(global->thread->id_control, 0);
-
- global->thread->id_control = 0;
- }
-
- if (global->main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_print_error(global->thread, &global->main->program.error, F_status_set_fine(status), "f_thread_create", F_true);
- }
- }
-
- return F_okay;
- }
-#endif // _di_controller_perform_ready_socket_
-
-#ifndef _di_controller_status_simplify_error_
- f_status_t controller_status_simplify_error(const f_status_t status) {
-
- if (status == F_memory_not) {
- return F_status_set_error(F_memory);
- }
-
- if (status == F_file_open_max || status == F_space_not || status == F_busy) {
- return F_status_set_error(F_resource);
- }
-
- if (status == F_access_denied || status == F_filesystem_quota_block || status == F_prohibited || status == F_input_output) {
- return F_status_set_error(F_access);
- }
-
- if (status == F_complete_not_utf || status == F_complete_not_utf_block || status == F_complete_not_utf_eof || status == F_complete_not_utf_eol || status == F_complete_not_utf_eos || status == F_complete_not_utf_stop) {
- return F_status_set_error(F_encoding);
- }
-
- if (status == F_number || status == F_number_negative || status == F_number_positive || status == F_number_overflow) {
- return F_status_set_error(F_number);
- }
-
- if (status == F_parameter || status == F_found_not || status == F_interrupt || status == F_support_not || status == F_critical) {
- return F_status_set_error(status);
- }
-
- if (status == F_valid_not) {
- return F_status_set_error(F_valid_not);
- }
-
- return F_status_set_error(F_failure);
- }
-#endif // _di_controller_status_simplify_error_
-
-#ifndef _di_controller_time_
- void controller_time(const time_t seconds, const long nanoseconds, f_time_spec_t *time) {
-
- struct timeval now;
-
- gettimeofday(&now, 0);
-
- time->tv_sec = now.tv_sec + seconds;
- time->tv_nsec = (now.tv_usec * 1000) + nanoseconds;
-
- // If tv_nsec is 1 second or greater, then increment seconds.
- if (time->tv_nsec >= 1000000000) {
- ++(time->tv_sec);
-
- time->tv_nsec -= 1000000000;
- }
- }
-#endif // _di_controller_time_
-
-#ifndef _di_controller_time_milliseconds_
- f_time_spec_t controller_time_milliseconds(const f_number_unsigned_t milliseconds) {
- // @todo update all of these type of functions to use the newer f_time_spec_milliseconds() and f_time_spec_nanoseconds() as appropriate.
-
- f_time_spec_t time;
- time.tv_sec = milliseconds > 1000 ? milliseconds / 1000 : 0;
- time.tv_nsec = (time.tv_sec ? milliseconds - time.tv_sec : milliseconds) * 1000;
-
- return time;
- }
-#endif // _di_controller_time_milliseconds_
-
-#ifndef _di_controller_time_seconds_
- f_time_spec_t controller_time_seconds(const f_number_unsigned_t seconds) {
-
- f_time_spec_t time;
- time.tv_sec = seconds;
- time.tv_nsec = 0;
-
- return time;
- }
-#endif // _di_controller_time_seconds_
-
-#ifndef _di_controller_time_sleep_nanoseconds_
- int controller_time_sleep_nanoseconds(controller_main_t * const main, controller_process_t * const setting, f_time_spec_t time) {
-
- // When sleep is a second or more, instead wait for terminating signals if interruptible.
- if ((setting->flag & controller_setting_flag_interruptible_e) && time.tv_sec) {
- siginfo_t information;
- f_signal_t signal = f_signal_t_initialize;
-
- memset(&information, 0, sizeof(siginfo_t));
-
- f_signal_set_empty(&signal.set);
- f_signal_set_add(F_signal_abort, &signal.set);
- f_signal_set_add(F_signal_interrupt, &signal.set);
- f_signal_set_add(F_signal_quit, &signal.set);
- f_signal_set_add(F_signal_termination, &signal.set);
-
- if (F_status_is_error(f_signal_wait_until(&signal.set, &time, &information))) {
- return -1;
- }
-
- return 0;
- }
-
- return nanosleep(&time, 0);
- }
-#endif // _di_controller_time_sleep_nanoseconds_
-
-#ifndef _di_controller_validate_define_name_
- f_status_t controller_validate_environment_name(const f_string_static_t name) {
-
- if (!name.used) return F_okay;
-
- f_status_t status = F_okay;
-
- if (name.string[0] != '_') {
- status = f_utf_is_alphabetic(name.string, name.used);
-
- if (F_status_is_error(status)) return status;
- if (status == F_false) return F_false;
- }
-
- for (f_number_unsigned_t i = macro_f_utf_byte_width(name.string[0]); i < name.used; i += macro_f_utf_byte_width(name.string[i])) {
-
- if (name.string[i] == '_') continue;
-
- status = f_utf_is_alphabetic_digit(name.string, name.used, 0);
-
- if (F_status_is_error(status)) return status;
- if (status == F_false) return F_false;
- } // for
-
- return F_true;
- }
-#endif // _di_controller_validate_define_name_
-
-#ifndef _di_controller_validate_has_graph_
- f_status_t controller_validate_has_graph(const f_string_static_t name) {
-
- if (!name.used) return F_okay;
-
- f_status_t status = F_okay;
-
- for (f_number_unsigned_t i = 0; i < name.used; i += macro_f_utf_byte_width(name.string[i])) {
-
- status = f_utf_is_graph(name.string, name.used);
-
- if (F_status_is_error(status)) return status;
- if (status == F_true) return F_true;
- } // for
-
- return F_false;
- }
-#endif // _di_controller_validate_has_graph_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_controller_h
-#define _PRIVATE_controller_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Given a string whose range represents a number, seek past the first positive or negative sign.
- *
- * This will stop at the first non-NULL, non-'+' and non-'-' characters.
- *
- * Only the first '+' or '-' are processed.
- *
- * @param buffer
- * The string referenced by the range.
- * @param range
- * The range within the buffer to process.
- *
- * @return
- * The string range.
- * The start range will be past the stop range on overflow or on any failure.
- */
-#ifndef _di_controller_range_after_number_sign_
- extern f_range_t controller_range_after_number_sign(const f_string_static_t buffer, const f_range_t range) F_attribute_visibility_internal_d;
-#endif // _di_controller_range_after_number_sign_
-
-/**
- * Load a file from the controller settings directory.
- *
- * @param global
- * The global data.
- * @param required
- * If TRUE, the file is required to exist and will throw an error if not found.
- * If FALSE, the file is not required to exist and will return without error if not found.
- * @param path_prefix
- * The path prefix, such as 'entries' from '/etc/controller/entries/default.entry'.
- * @param path_name
- * The path name, such as 'default' from '/etc/controller/entries/default.entry'.
- * @param path_suffix
- * The path suffix, such as 'entry' from '/etc/controller/entries/default.entry'.
- * @param cache
- * The following within the cache is updated:
- * - name_file: The partial path of the file is inserted.
- * - buffer_file: The contents of the file is inserted.
- * - timestamp: This is updated to reflect the last changed timestamp.
- *
- * @return
- * F_okay on success.
- * F_file_found_not if required is FALSE and the file is not found.
- *
- * Errors (with error bit) from: f_file_stat().
- * Errors (with error bit) from: f_file_stream_open().
- * Errors (with error bit) from: f_file_stream_read().
- * Errors (with error bit) from: f_string_append().
- *
- * @see f_file_stat()
- * @see f_file_stream_open()
- * @see f_file_stream_read()
- * @see f_string_append()
- */
-#ifndef _di_controller_file_load_
- extern f_status_t controller_file_load(const controller_global_t global, const bool required, const f_string_static_t path_prefix, const f_string_static_t path_name, const f_string_static_t path_suffix, controller_cache_t * const cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_file_load_
-
-/**
- * Create the pid file, if possible.
- *
- * @param pid
- * The PID (process id).
- * @param path
- * The file path to the pid file to create.
- *
- * @return
- * F_okay on success.
- * F_access_denied if pid file is not created due to access denied errors.
- * F_directory_not if pid file is not created due to a parent directory is unavailable or invalid.
- *
- * Errors (with error bit) from: f_directory_exists().
- * Errors (with error bit) from: f_file_name_directory().
- * Errors (with error bit) from: f_file_stream_open().
- *
- * @see f_directory_exists()
- * @see f_file_name_directory()
- * @see f_file_stream_open()
- */
-#ifndef _di_controller_file_pid_create_
- f_status_t controller_file_pid_create(const pid_t pid, const f_string_static_t path) F_attribute_visibility_internal_d;
-#endif // _di_controller_file_pid_create_
-
-/**
- * Delete the pid file, if exists and is valid.
- *
- * This is meant to be called on exit and avoids checking status codes, returning void.
- *
- * @param pid
- * The PID (process id).
- * @param path
- * The file path to the pid file to create.
- *
- * @return
- * F_okay on success.
- *
- * F_number_not (with error bit) if the number from the pid file doesn't match the expected pid.
- *
- * Errors (with error bit) from: f_file_stream_close().
- * Errors (with error bit) from: f_file_stream_open().
- * Errors (with error bit) from: f_file_stream_read().
- * Errors (with error bit) from: fl_conversion_dynamic_partial_to_unsigned()
- */
-#ifndef _di_controller_file_pid_delete_
- f_status_t controller_file_pid_delete(const pid_t pid, const f_string_static_t path) F_attribute_visibility_internal_d;
-#endif // _di_controller_file_pid_delete_
-
-/**
- * Read the PID from a PID file.
- *
- * @param path
- * The file path to the pid file to create.
- * @param pid
- * The PID to be read.
- *
- * @return
- * F_okay on success.
- *
- * Errors (with error bit) from: f_file_stream_close().
- * Errors (with error bit) from: f_file_stream_open().
- * Errors (with error bit) from: f_file_stream_read().
- * Errors (with error bit) from: fl_conversion_dynamic_partial_to_unsigned()
- */
-#ifndef _di_controller_file_pid_read_
- f_status_t controller_file_pid_read(const f_string_static_t path, pid_t * const pid) F_attribute_visibility_internal_d;
-#endif // _di_controller_file_pid_read_
-
-/**
- * Convert the string from a string representation of an ID or a user name into the numeric representation of that ID or user name.
- *
- * @param buffer
- * A string containing user name or ID.
- * @param range
- * The range within the buffer specifically containing the name or ID.
- * @param cache
- * The cache.
- * @param id
- * The determined user ID.
- *
- * @return
- * F_okay on success.
- * F_exist_not (with error bit) if failed to match the name to an ID.
- * F_number_too_large (with error bit) if the given ID is too large.
- *
- * Errors (with error bit) from: f_account_id_by_name().
- * Errors (with error bit) from: fl_conversion_dynamic_partial_to_unsigned_detect().
- * Errors (with error bit) from: f_rip_dynamic_partial_nulless().
- *
- * @see f_account_id_by_name()
- * @see fl_conversion_dynamic_partial_to_unsigned_detect()
- * @see f_rip_dynamic_partial_nulless()
- */
-#ifndef _di_controller_get_id_user_
- f_status_t controller_get_id_user(const f_string_static_t buffer, const f_range_t range, controller_cache_t * const cache, uid_t * const id) F_attribute_visibility_internal_d;
-#endif // _di_controller_get_id_user_
-
-/**
- * Convert the string from a string representation of an ID or a group name into the numeric representation of that ID or group name.
- *
- * @param buffer
- * A string containing group name or ID.
- * @param range
- * The range within the buffer specifically containing the name or ID.
- * @param cache
- * The cache.
- * @param id
- * The determined group ID.
- *
- * @return
- * F_okay on success.
- * F_exist_not (with error bit) if failed to match the name to an ID.
- * F_number_too_large (with error bit) if the given ID is too large.
- *
- * Errors (with error bit) from: f_account_group_id_by_name().
- * Errors (with error bit) from: fl_conversion_dynamic_partial_to_unsigned_detect().
- * Errors (with error bit) from: f_rip_dynamic_partial_nulless().
- *
- * @see f_account_group_id_by_name()
- * @see fl_conversion_dynamic_partial_to_unsigned_detect()
- * @see f_rip_dynamic_partial_nulless()
- */
-#ifndef _di_controller_get_id_group_
- f_status_t controller_get_id_group(const f_string_static_t buffer, const f_range_t range, controller_cache_t * const cache, gid_t * const id) F_attribute_visibility_internal_d;
-#endif // _di_controller_get_id_group_
-
-/**
- * Determine a canonical path and then if it is relative to the current working directory, make it relative.
- *
- * For example, given the paths "../hello/world/" and "../controller/files/" with a current working directory of "/tmp/controller", then a canonical path for these might look like:
- * - "/tmp/hello/world/"
- * - "/tmp/controller/files/"
- *
- * This function would instead result in the following:
- * - "/tmp/hello/world/"
- * - "files/"
- *
- * @param setting
- * The controller settings data.
- * @param source
- * The source path to determine the relative canonical from.
- * @param destination
- * The resulting relative canonical path.
- * The destination will be completely replaced on success.
- *
- * @return
- * F_okay on success.
- *
- * Errors (with error bit) from: fl_path_canonical().
- *
- * @see fl_path_canonical()
- */
-#ifndef _di_controller_path_canonical_relative_
- extern f_status_t controller_path_canonical_relative(const controller_process_t * const global, const f_string_static_t source, f_string_dynamic_t * const destination) F_attribute_visibility_internal_d;
-#endif // _di_controller_path_canonical_relative_
-
-/**
- * Perform all activities requiring the state to be "ready".
- *
- * This prints messages on errors.
- *
- * This does not do any locking or unlocking for the setting data, be sure to lock appropriately before and after calling this.
- *
- * @param global
- * The global data.
- * @param cache
- * The cache.
- * @param is_entry
- * If TRUE, then this operate as an entry.
- * If FALSE, then this operate as an exit.
- *
- * @return
- * F_okay on success.
- *
- * Errors from controller_file_pid_create() are not returned, unless it is a memory error.
- *
- * @see controller_file_pid_create()
- */
-#ifndef _di_controller_perform_ready_
- extern f_status_t controller_perform_ready(const controller_global_t * const global, controller_cache_t * const cache, const bool is_entry) F_attribute_visibility_internal_d;
-#endif // _di_controller_perform_ready_
-
-/**
- * Perform the socket loading when "ready".
- *
- * This prints messages on errors.
- *
- * This does not do any locking or unlocking for the setting data, be sure to lock appropriately before and after calling this.
- *
- * @param global
- * The global data.
- * @param cache
- * The cache.
- * @param is_entry
- * If TRUE, then this operate as an entry.
- * If FALSE, then this operate as an exit.
- *
- * @return
- * F_okay on success.
- * F_data_not on success but socket file not created.
- *
- * Errors (with error bit) from: f_file_mode_set().
- * Errors (with error bit) from: f_file_remove().
- * Errors (with error bit) from: f_file_role_change().
- * Errors (with error bit) from: f_socket_bind_local().
- * Errors (with error bit) from: f_socket_create().
- * Errors (with error bit) from: f_thread_create().
- *
- * @see f_file_mode_set()
- * @see f_file_remove()
- * @see f_file_role_change()
- * @see f_socket_bind_local()
- * @see f_socket_create()
- * @see f_thread_create()
- */
-#ifndef _di_controller_perform_ready_socket_
- extern f_status_t controller_perform_ready_socket(const controller_global_t * const global, controller_cache_t * const cache, const bool is_entry) F_attribute_visibility_internal_d;
-#endif // _di_controller_perform_ready_socket_
-
-/**
- * Given a wide range of status codes (that are errors), simplify them down to a small subset.
- *
- * @param status
- * The status code (without the error bit set) to simplify.
- *
- * @return
- * A subset of status codes with error bit.
- */
-#ifndef _di_controller_status_simplify_error_
- extern f_status_t controller_status_simplify_error(const f_status_t status) F_attribute_visibility_internal_d;
-#endif // _di_controller_status_simplify_error_
-
-/**
- * Get the current time, plus the given offset.
- *
- * @todo this is basic enough that there needs to be an f_time class with this function f_time_now(), f_time_future(), f_time_past().
- * "f_time_spec_t" -> f_time_nano_t, "struct timeval" -> f_time_micro_t.
- *
- * @param seconds
- * The seconds to add to current time.
- * @param nanoseconds
- * The nanoseconds to add to current time.
- * @param time
- * The resulting current time.
- */
-#ifndef _di_controller_time_
- void controller_time(const time_t seconds, const long nanoseconds, f_time_spec_t *time) F_attribute_visibility_internal_d;
-#endif // _di_controller_time_
-
-/**
- * Convert milliseconds to nanoseconds.
- *
- * @param milliseconds
- * The number of milliseconds.
- *
- * @return
- * A time structure suitable for passing to nanosleep() and similar functions.
- *
- * @see nanosleep()
- */
-#ifndef _di_controller_time_milliseconds_
- extern f_time_spec_t controller_time_milliseconds(const f_number_unsigned_t milliseconds) F_attribute_visibility_internal_d;
-#endif // _di_controller_time_milliseconds_
-
-/**
- * Convert seconds to nanoseconds.
- *
- * @param seconds
- * The number of seconds.
- *
- * @return
- * A time structure suitable for passing to nanosleep() and similar functions.
- *
- * @see nanosleep()
- */
-#ifndef _di_controller_time_seconds_
- extern f_time_spec_t controller_time_seconds(const f_number_unsigned_t seconds) F_attribute_visibility_internal_d;
-#endif // _di_controller_time_seconds_
-
-/**
- * Sleep for a given number of nanoseconds.
- *
- * @param main
- * The main program data.
- * @param setting
- * The controller settings data.
- * @param time
- * The number of nanoseconds to sleep.
- *
- * @return
- * The result of nanosleep().
- *
- * @see nanosleep()
- */
-#ifndef _di_controller_time_sleep_nanoseconds_
- extern int controller_time_sleep_nanoseconds(controller_main_t * const main, controller_process_t * const setting, f_time_spec_t time) F_attribute_visibility_internal_d;
-#endif // _di_controller_time_sleep_nanoseconds_
-
-/**
- * Validate that the given string is a valid environment variable name.
- *
- * A valid environment variable name must begin with an alpha-character or an underscore.
- * Every character after that may be alphanumeric or underscore.
- * All other characters, including Unicode characters, are invalid.
- *
- * @param name
- * The string to validate.
- *
- * @return
- * F_true on valid.
- * F_false on invalid.
- * F_okay if there is no string to validate (used = 0).
- *
- * Errors (with error bit) from: f_utf_is_alphabetic().
- * Errors (with error bit) from: f_utf_is_alphabetic_digit().
- *
- * @see f_utf_is_alphabetic()
- * @see f_utf_is_alphabetic_digit()
- */
-#ifndef _di_controller_validate_define_name_
- extern f_status_t controller_validate_environment_name(const f_string_static_t name) F_attribute_visibility_internal_d;
-#endif // _di_controller_validate_define_name_
-
-/**
- * Validate that the given string has at least one graph character.
- *
- * @param name
- * The string to validate.
- *
- * @return
- * F_true on valid.
- * F_false on invalid.
- * F_okay if there is no string to validate (used = 0).
- *
- * Errors (with error bit) from: f_utf_is_graph().
- *
- * @see f_utf_is_graph()
- */
-#ifndef _di_controller_validate_has_graph_
- extern f_status_t controller_validate_has_graph(const f_string_static_t name) F_attribute_visibility_internal_d;
-#endif // _di_controller_validate_has_graph_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_controller_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "private-controller_print.h"
-#include "../lock/private-lock_print.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_print_error_
- void controller_print_error(controller_thread_t * const thread, fl_print_t * const print, const f_status_t status, const f_string_t function, const uint8_t flag) {
-
- if (print->verbosity == f_console_verbosity_quiet_e) return;
- if (status == F_interrupt) return;
-
- // fll_error_print() automatically locks, so manually handle only the mutex locking and flushing rather than calling controller_lock_print().
- if (thread) {
- f_thread_mutex_lock(&thread->lock.print);
- }
-
- fll_error_print(print, status, function, flag);
-
- if (thread) {
- f_thread_mutex_unlock(&thread->lock.print);
- }
- }
-#endif // _di_controller_print_error_
-
-#ifndef _di_controller_print_error_file_
- void controller_print_error_file(controller_thread_t * const thread, fl_print_t * const print, const f_status_t status, const f_string_t function, const uint8_t flag, const f_string_static_t name, const f_string_static_t operation, const uint8_t type) {
-
- if (print->verbosity == f_console_verbosity_quiet_e) return;
- if (status == F_interrupt) return;
-
- // fll_error_print() automatically locks, so manually handle only the mutex locking and flushing rather than calling controller_lock_print().
- if (thread) {
- f_thread_mutex_lock(&thread->lock.print);
- }
-
- fll_error_file_print(print, status, function, flag, name, operation, type);
-
- if (thread) {
- f_thread_mutex_unlock(&thread->lock.print);
- }
- }
-#endif // _di_controller_print_error_file_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_controller_print_h
-#define _PRIVATE_controller_print_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Print the error, locking the print mutex during the print.
- *
- * @param thread
- * (optional) The thread data.
- * Set to NULL to disable locking on the thread (this should be done only if the lock is already in place).
- * @param print
- * Designates how printing is to be performed.
- * @param status
- * The status code to process.
- * Make sure this has F_status_set_fine() called if the status code has any error or warning bits.
- * @param function
- * (optional) The name of the function where the error happened.
- *
- * Set to NULL to disable.
- * @param flag
- * One of the fll_error_file_flag_*_e flags.
- *
- * @see fll_error_print()
- */
-#ifndef _di_controller_print_error_
- extern void controller_print_error(controller_thread_t * const thread, fl_print_t * const print, const f_status_t status, const f_string_t function, const uint8_t flag) F_attribute_visibility_internal_d;
-#endif // _di_controller_print_error_
-
-/**
- * Print the file error, locking the print mutex during the print.
- *
- * @param thread
- * (optional) The thread data.
- *
- * Set to NULL to disable locking on the thread (this should be done only if the lock is already in place).
- * @param print
- * Designates how printing is to be performed.
- * @param status
- * The status code to process.
- * Make sure this has F_status_set_fine() called if the status code has any error or warning bits.
- * @param function
- * (optional) The name of the function where the error happened.
- *
- * Set to NULL to disable.
- * @param flag
- * One of the fll_error_file_flag_*_e flags.
- * @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.
- *
- * @see fll_error_file_print()
- */
-#ifndef _di_controller_print_error_file_
- extern void controller_print_error_file(controller_thread_t * const thread, fl_print_t * const print, const f_status_t status, const f_string_t function, const uint8_t flag, const f_string_static_t name, const f_string_static_t operation, const uint8_t type) F_attribute_visibility_internal_d;
-#endif // _di_controller_print_error_file_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_controller_print_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "../controller/private-controller.h"
-#include "../controller/private-controller_print.h"
-#include "../entry/private-entry.h"
-#include "../entry/private-entry_print.h"
-#include "../lock/private-lock.h"
-#include "../lock/private-lock_print.h"
-#include "../rule/private-rule.h"
-#include "../thread/private-thread.h"
-#include "../thread/private-thread_process.h"
-#include "../thread/private-thread_signal.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_entry_action_type_is_rule_
- f_status_t controller_entry_action_type_is_rule(uint8_t type) {
-
- switch (type) {
- case controller_entry_action_type_freeze_e:
- case controller_entry_action_type_kill_e:
- case controller_entry_action_type_pause_e:
- case controller_entry_action_type_reload_e:
- case controller_entry_action_type_restart_e:
- case controller_entry_action_type_resume_e:
- case controller_entry_action_type_start_e:
- case controller_entry_action_type_stop_e:
- case controller_entry_action_type_thaw_e:
- return F_true;
- }
-
- return F_false;
- }
-#endif // _di_controller_entry_action_type_is_rule_
-
-#ifndef _di_controller_entry_action_type_to_rule_action_type_
- uint8_t controller_entry_action_type_to_rule_action_type(uint8_t type) {
-
- switch (type) {
- case controller_entry_action_type_freeze_e:
- return controller_rule_action_type_freeze_e;
-
- case controller_entry_action_type_kill_e:
- return controller_rule_action_type_kill_e;
-
- case controller_entry_action_type_pause_e:
- return controller_rule_action_type_pause_e;
-
- case controller_entry_action_type_reload_e:
- return controller_rule_action_type_reload_e;
-
- case controller_entry_action_type_restart_e:
- return controller_rule_action_type_restart_e;
-
- case controller_entry_action_type_resume_e:
- return controller_rule_action_type_resume_e;
-
- case controller_entry_action_type_start_e:
- return controller_rule_action_type_start_e;
-
- case controller_entry_action_type_stop_e:
- return controller_rule_action_type_stop_e;
-
- case controller_entry_action_type_thaw_e:
- return controller_rule_action_type_thaw_e;
- }
-
- return 0;
- }
-#endif // _di_controller_entry_action_type_to_rule_action_type_
-
-#ifndef _di_controller_entry_actions_read_
- f_status_t controller_entry_actions_read(const controller_global_t global, const bool is_entry, const f_range_t content_range, controller_cache_t * const cache, controller_entry_actions_t *actions) {
-
- f_status_t status = F_okay;
- f_status_t status_action = F_okay;
-
- actions->used = 0;
-
- cache->object_actions.used = cache->object_actions.size;
-
- while (cache->object_actions.used) {
-
- cache->object_actions.array[--cache->object_actions.used].start = 1;
- cache->object_actions.array[cache->object_actions.used].stop = 0;
- } // while
-
- cache->content_actions.used = cache->content_actions.size;
-
- while (cache->content_actions.used) {
- cache->content_actions.array[--cache->content_actions.used].used = 0;
- } // while
-
- {
- controller_state_interrupt_t custom = macro_controller_state_interrupt_t_initialize_1(is_entry, global.thread);
- f_state_t state = macro_f_state_t_initialize_1(controller_common_allocation_large_d, controller_common_allocation_small_d, F_okay, 0, 0, 0, &controller_thread_signal_state_fss, 0, (void *) &custom, 0);
- f_range_t range = content_range;
-
- fll_fss_extended_read(cache->buffer_file, &range, &cache->object_actions, &cache->content_actions, 0, 0, &cache->delimits, 0, &state);
- }
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "fll_fss_extended_read", F_true, global.thread);
-
- return status;
- }
-
- f_state_t state = f_state_t_initialize;
-
- f_fss_apply_delimit(cache->delimits, &cache->buffer_file, &state);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_fss_apply_delimit", F_true, global.thread);
-
- return status;
- }
-
- cache->delimits.used = 0;
-
- status = controller_entry_actions_increase_by(cache->object_actions.used, actions);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "controller_entry_actions_increase_by", F_true, global.thread);
-
- return status;
- }
-
- controller_entry_action_t *action = 0;
-
- f_number_unsigned_t allocate = 0;
- f_number_unsigned_t at_least = 0;
- f_number_unsigned_t at_most = 0;
-
- f_number_unsigned_t i = 0;
- f_number_unsigned_t j = 0;
-
- for (; i < cache->object_actions.used; ++i) {
-
- cache->action.line_action = 0;
- cache->action.name_action.used = 0;
-
- action = &actions->array[actions->used];
- action->type = 0;
- action->code = 0;
- action->line = 0;
- action->number = 0;
- action->status = F_known_not;
- action->parameters.used = 0;
-
- f_fss_count_lines(cache->buffer_file, cache->object_actions.array[i].start, &cache->action.line_action, &global.main->setting.state);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_fss_count_lines", F_true, global.thread);
-
- break;
- }
-
- action->line = ++cache->action.line_action;
-
- status = f_rip_dynamic_partial_nulless(cache->buffer_file, cache->object_actions.array[i], &cache->action.name_action);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_rip_dynamic_partial_nulless", F_true, global.thread);
-
- break;
- }
-
- if (f_compare_dynamic(controller_consider_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_consider_e;
- }
- else if (f_compare_dynamic(controller_execute_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_execute_e;
- }
- else if (f_compare_dynamic(controller_failsafe_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_failsafe_e;
- }
- else if (f_compare_dynamic(controller_freeze_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_freeze_e;
- }
- else if (f_compare_dynamic(controller_item_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_item_e;
- }
- else if (f_compare_dynamic(controller_kill_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_kill_e;
- }
- else if (f_compare_dynamic(controller_pause_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_pause_e;
- }
- else if (f_compare_dynamic(controller_ready_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_ready_e;
- }
- else if (f_compare_dynamic(controller_reload_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_reload_e;
- }
- else if (f_compare_dynamic(controller_restart_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_restart_e;
- }
- else if (f_compare_dynamic(controller_resume_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_resume_e;
- }
- else if (f_compare_dynamic(controller_start_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_start_e;
- }
- else if (f_compare_dynamic(controller_stop_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_stop_e;
- }
- else if (f_compare_dynamic(controller_thaw_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_thaw_e;
- }
- else if (f_compare_dynamic(controller_timeout_s, cache->action.name_action) == F_equal_to) {
- actions->array[actions->used].type = controller_entry_action_type_timeout_e;
- }
- else {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- fl_print_format("%r%[%QUnknown %r item action '%]", global.main->program.warning.to, f_string_eol_s, global.main->program.warning.context, global.main->program.warning.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.warning.to, global.main->program.warning.notable, cache->action.name_action, global.main->program.warning.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.warning.to, global.main->program.warning.context, global.main->program.warning.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.warning, cache->action);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
-
- continue;
- }
-
- if (action->type == controller_entry_action_type_consider_e || controller_entry_action_type_is_rule(action->type)) {
- allocate = cache->content_actions.array[i].used;
- at_least = 2;
- at_most = allocate;
- }
- else if (action->type == controller_entry_action_type_execute_e) {
- allocate = cache->content_actions.array[i].used;
- at_least = 1;
- at_most = allocate;
- }
- else if (action->type == controller_entry_action_type_failsafe_e || action->type == controller_entry_action_type_item_e) {
- allocate = 1;
- at_least = 1;
- at_most = 1;
- }
- else if (action->type == controller_entry_action_type_timeout_e) {
- allocate = 2;
- at_least = 1;
- at_most = 2;
- }
- else if (action->type == controller_entry_action_type_ready_e) {
- allocate = 1;
- at_least = 0;
- at_most = 1;
- }
-
- if (cache->content_actions.array[i].used < at_least || cache->content_actions.array[i].used > at_most) {
- action->status = F_status_set_error(F_parameter);
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- f_thread_mutex_lock(&global.thread->lock.print);
-
- f_file_stream_lock(global.main->program.error.to);
-
- fl_print_format("%r%[%QThe %r item action '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->action.name_action, global.main->program.error.notable);
- fl_print_format("%[' requires ", global.main->program.error.to, global.main->program.error.context);
-
- if (at_least == at_most) {
- f_print_terminated("exactly ", global.main->program.error.to);
- }
-
- fl_print_format("%]%[%un%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.notable, at_least, global.main->program.error.notable);
-
- if (action->type == controller_entry_action_type_consider_e || controller_entry_action_type_is_rule(action->type)) {
- fl_print_format("%[ or more parameters.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
- }
- else {
- if (at_least == at_most) {
- fl_print_format("%[ parameters.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
- }
- else {
- fl_print_format("%[ to %]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%un%]", global.main->program.error.to, global.main->program.error.notable, at_most, global.main->program.error.notable);
- fl_print_format("%[ parameters.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
- }
- }
-
- f_file_stream_unlock(global.main->program.error.to);
-
- f_thread_mutex_unlock(&global.thread->lock.print);
- }
- }
- else {
- action->status = F_okay;
- }
-
- if (F_status_is_error(action->status)) {
- if (F_status_is_error_not(status_action)) {
- status_action = action->status;
- }
-
- continue;
- }
-
- if (allocate) {
- status = f_memory_array_increase_by(allocate, sizeof(f_string_dynamic_t), (void **) &action->parameters.array, &action->parameters.used, &action->parameters.size);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_memory_array_increase_by", F_true, global.thread);
-
- action->status = status;
-
- if (F_status_is_error_not(status_action)) {
- status_action = status;
- }
-
- break;
- }
-
- for (j = 0; j < allocate && j < cache->content_actions.array[i].used; ++j) {
-
- action->parameters.array[j].used = 0;
-
- if (cache->content_actions.array[i].array[j].start > cache->content_actions.array[i].array[j].stop) continue;
-
- status = f_memory_array_increase_by((cache->content_actions.array[i].array[j].stop - cache->content_actions.array[i].array[j].start) + 1, sizeof(f_char_t), (void **) &action->parameters.array[j].string, &action->parameters.array[j].used, &action->parameters.array[j].size);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_memory_array_increase_by", F_true, global.thread);
-
- break;
- }
-
- status = f_string_dynamic_partial_append_nulless(cache->buffer_file, cache->content_actions.array[i].array[j], &action->parameters.array[j]);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true, global.thread);
-
- break;
- }
-
- ++action->parameters.used;
- } // for
-
- if (F_status_is_error_not(action->status)) {
- if (action->type == controller_entry_action_type_consider_e || controller_entry_action_type_is_rule(action->type)) {
- if (action->parameters.array[0].used) {
-
- // Force the path to be canonical (removing all '../' parts).
- status = controller_path_canonical_relative(global.setting, action->parameters.array[0], &cache->buffer_path);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error_file(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "controller_path_canonical_relative", F_true, cache->action.generic, f_file_operation_analyze_s, fll_error_file_type_path_e, global.thread);
-
- action->status = status;
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_action = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_action)) {
- status_action = status;
- }
- }
- }
- else {
- action->status = F_status_set_error(F_parameter);
-
- if (F_status_is_error_not(status_action)) {
- status_action = action->status;
- }
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- fll_print_format("%r%[%QThe %r item action must not have an empty string for a path (the first parameter).%]%r", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context, f_string_eol_s);
- }
- }
-
- if (action->parameters.array[1].used) {
- cache->buffer_path.used = 0;
-
- status = f_file_name_base(action->parameters.array[1], &cache->buffer_path);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_file_name_base", F_true, global.thread);
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_action = status;
-
- break;
- }
-
- action->status = status;
-
- if (F_status_is_error_not(status_action)) {
- status_action = status;
- }
- }
- else {
- if (f_compare_dynamic(action->parameters.array[1], cache->buffer_path) == F_equal_to_not) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- f_file_stream_lock(global.main->program.error.to);
-
- fl_print_format("%r%[%QThe %r item action second parameter '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, action->parameters.array[1], global.main->program.error.notable);
- fl_print_format("%[' must be a base path name, such as '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->buffer_path, global.main->program.error.notable);
- fl_print_format("%['.%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- f_file_stream_unlock(global.main->program.error.to);
- }
-
- action->status = F_status_set_error(F_parameter);
-
- if (F_status_is_error_not(status_action)) {
- status_action = action->status;
- }
- }
- }
- }
- else {
- action->status = F_status_set_error(F_parameter);
-
- if (F_status_is_error_not(status_action)) {
- status_action = action->status;
- }
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- fll_print_format("%r%[%QThe %r item action must not have an empty string for a rule name (the second parameter).%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context, f_string_eol_s);
- }
- }
-
- for (j = 2; j < action->parameters.used; ++j) {
-
- if (f_compare_dynamic(controller_asynchronous_s, action->parameters.array[j]) == F_equal_to) {
- action->code |= controller_entry_rule_code_asynchronous_d;
- }
- else if (f_compare_dynamic(controller_require_s, action->parameters.array[j]) == F_equal_to) {
- action->code |= controller_entry_rule_code_require_d;
- }
- else if (f_compare_dynamic(controller_wait_s, action->parameters.array[j]) == F_equal_to) {
- action->code |= controller_entry_rule_code_wait_d;
- }
- else {
- if (action->status == F_okay) {
- action->status = F_status_set_error(F_support_not);
-
- if (F_status_is_error_not(status_action)) {
- status_action = action->status;
- }
- }
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- f_file_stream_lock(global.main->program.error.to);
-
- fl_print_format("%r%[%QThe %r item action third parameter (and beyond) must be one of '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_asynchronous_s, global.main->program.error.notable);
- fl_print_format("%[', '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_require_s, global.main->program.error.notable);
- fl_print_format("%[', or '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_wait_s, global.main->program.error.notable);
- fl_print_format("%[' but instead has '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, action->parameters.array[j], global.main->program.error.notable);
- fl_print_format("%['.%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- f_file_stream_unlock(global.main->program.error.to);
- }
- }
- } // for
- }
- else if (action->type == controller_entry_action_type_failsafe_e || action->type == controller_entry_action_type_item_e) {
- if (f_compare_dynamic(controller_main_s, action->parameters.array[0]) == F_equal_to) {
- action->status = F_status_set_error(F_support_not);
-
- if (F_status_is_error_not(status_action)) {
- status_action = action->status;
- }
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- f_file_stream_lock(global.main->program.error.to);
-
- fl_print_format("%r%[%QThe %r item action may not specify the reserved item '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_main_s, global.main->program.error.notable);
- fl_print_format("%['.%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- f_file_stream_unlock(global.main->program.error.to);
- }
- }
- }
- else if (action->type == controller_entry_action_type_timeout_e) {
-
- if (f_compare_dynamic(controller_kill_s, action->parameters.array[0]) == F_equal_to) {
- action->code = controller_entry_timeout_code_kill_d;
- }
- else if (f_compare_dynamic(controller_start_s, action->parameters.array[0]) == F_equal_to) {
- action->code = controller_entry_timeout_code_start_d;
- }
- else if (f_compare_dynamic(controller_stop_s, action->parameters.array[0]) == F_equal_to) {
- action->code = controller_entry_timeout_code_stop_d;
- }
- else {
- action->status = F_status_set_error(F_support_not);
-
- if (F_status_is_error_not(status_action)) {
- status_action = action->status;
- }
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- f_file_stream_lock(global.main->program.error.to);
-
- fl_print_format("%r%[%QThe %r item action must have one of '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_kill_s, global.main->program.error.notable);
- fl_print_format("%[', '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_start_s, global.main->program.error.notable);
- fl_print_format("%[', or '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_stop_s, global.main->program.error.notable);
- fl_print_format("%[' but instead has '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, action->parameters.array[0], global.main->program.error.notable);
- fl_print_format("%['.%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- f_file_stream_unlock(global.main->program.error.to);
- }
- }
-
- if (action->status == F_okay) {
- if (action->parameters.used == 2) {
- action->flag &= ~controller_entry_action_flag_undefined_e;
-
- status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, action->parameters.array[1], &action->number);
-
- if (F_status_is_error(status) || status == F_data_not) {
- action->number = 0;
-
- if (status == F_data_not) {
- action->status = F_status_set_error(F_number);
- }
- else {
- action->status = controller_status_simplify_error(F_status_set_fine(status));
- }
-
- if (F_status_set_fine(status) == F_memory_not) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "fl_conversion_dynamic_to_unsigned_detect", F_true, global.thread);
-
- status_action = status;
-
- break;
- }
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- f_file_stream_lock(global.main->program.error.to);
-
- fl_print_format("%r%[%QThe %r item action parameter '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, action->parameters.array[1], global.main->program.error.notable);
- fl_print_format("%[' is not a valid supported number.%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- f_file_stream_unlock(global.main->program.error.to);
- }
- }
- }
- else {
- action->flag |= controller_entry_action_flag_undefined_e;
- }
- }
- }
- else if (action->type == controller_entry_action_type_ready_e) {
- if (action->parameters.used) {
- if (f_compare_dynamic(controller_wait_s, action->parameters.array[0]) == F_equal_to) {
- action->code |= controller_entry_rule_code_wait_d;
- }
- else {
- action->status = F_status_set_error(F_support_not);
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- f_file_stream_lock(global.main->program.error.to);
-
- fl_print_format("%r%[%QThe %r item action may only have '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_wait_s, global.main->program.error.notable);
- fl_print_format("%[' but instead has '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, action->parameters.array[0], global.main->program.error.notable);
- fl_print_format("%['.%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- f_file_stream_unlock(global.main->program.error.to);
- }
- }
- }
- }
- }
- }
-
- ++actions->used;
- } // for
-
- if (F_status_is_error(status_action)) {
- return status_action;
- }
-
- return status;
- }
-#endif // _di_controller_entry_actions_read_
-
-#ifndef _di_controller_entry_preprocess_
- f_status_t controller_entry_preprocess(const controller_global_t global, const bool is_entry, controller_cache_t * const cache) {
-
- f_status_t status = F_okay;
- f_status_t status2 = F_okay;
-
- f_number_unsigned_t i = 0;
- f_number_unsigned_t j = 0;
-
- f_number_unsigned_t at_i = 0;
- f_number_unsigned_t at_j = 1;
-
- controller_entry_t *entry = is_entry ? &global.setting->entry : &global.setting->exit;
- controller_entry_actions_t *actions = 0;
-
- uint8_t error_has = F_false;
-
- // This effectively sets the read for an entry and resets the ready for an exit.
- global.setting->ready = controller_setting_ready_no_e;
-
- cache->ats.used = 0;
-
- cache->action.line_action = 0;
- cache->action.line_item = 0;
- cache->action.name_action.used = 0;
- cache->action.name_item.used = 0;
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_number_unsigned_t), (void **) &cache->ats.array, &cache->ats.used, &cache->ats.size);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_memory_array_increase", F_true, global.thread);
-
- return status;
- }
-
- // Utilize the ats cache as an item execution stack (at_i is for item index, and at_j (at_i + 1) is for action index).
- cache->ats.array[0] = 0;
- cache->ats.array[1] = 0;
- cache->ats.used = 2;
-
- cache->action.line_item = entry->items.array[0].line;
- cache->action.name_item.used = 0;
-
- status = f_string_dynamic_append_nulless(entry->items.array[0].name, &cache->action.name_item);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true, global.thread);
-
- return status;
- }
-
- while (controller_thread_is_enabled(is_entry, global.thread)) {
-
- actions = &entry->items.array[cache->ats.array[at_i]].actions;
-
- for (; cache->ats.array[at_j] < actions->used && controller_thread_is_enabled(is_entry, global.thread); ++cache->ats.array[at_j]) {
-
- cache->action.line_action = actions->array[cache->ats.array[at_j]].line;
- cache->action.name_action.used = 0;
-
- status2 = f_string_dynamic_append_nulless(controller_entry_action_type_name(actions->array[cache->ats.array[at_j]].type), &cache->action.name_action);
-
- if (F_status_is_error(status2)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status2), "f_string_dynamic_append_nulless", F_true, global.thread);
-
- return status2;
- }
-
- if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_ready_e) {
-
- if (global.setting->ready == controller_setting_ready_wait_e) {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- fl_print_format("%r%[%QMultiple '%]", global.main->program.warning.to, f_string_eol_s, global.main->program.warning.context, global.main->program.warning.prefix, global.main->program.warning.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.warning.to, global.main->program.warning.notable, controller_ready_s, global.main->program.warning.notable);
- fl_print_format("%[' %r item actions detected; only the first will be used.%]%r", global.main->program.warning.to, global.main->program.warning.context, is_entry ? controller_entry_s : controller_exit_s, global.main->program.warning.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.warning, cache->action);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
- }
- else {
- global.setting->ready = controller_setting_ready_wait_e;
- }
- }
- else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_item_e) {
- error_has = F_false;
-
- // "main" is not allowed to be used for an "item" and "setting" is not an executable "item".
- if (f_compare_dynamic(controller_main_s, actions->array[cache->ats.array[at_j]].parameters.array[0]) == F_equal_to) {
- continue;
- }
- else if (f_compare_dynamic(controller_settings_s, actions->array[cache->ats.array[at_j]].parameters.array[0]) == F_equal_to) {
- continue;
- }
-
- // Walk though each items and check to see if the item actually exists.
- for (i = 1; i < entry->items.used && controller_thread_is_enabled(is_entry, global.thread); ++i) {
-
- if (f_compare_dynamic(entry->items.array[i].name, actions->array[cache->ats.array[at_j]].parameters.array[0]) == F_equal_to) {
-
- // Check to see if "i" is already in the stack (to prevent recursion) (skipping main).
- for (j = 2; j < cache->ats.used; j += 2) {
-
- if (cache->ats.array[j] == i) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QThe %r item named '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, entry->items.array[i].name, global.main->program.error.notable);
- fl_print_format("%[' cannot be executed because recursion is not allowed.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.error, cache->action);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- if (F_status_is_error_not(status)) {
- status = F_status_set_error(F_recurse);
- }
-
- error_has = F_true;
- break;
- }
- } // for
-
- if (error_has) break;
-
- status2 = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_number_unsigned_t), (void **) &cache->ats.array, &cache->ats.used, &cache->ats.size);
-
- if (F_status_is_error(status2)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status2), "f_memory_array_increase", F_true, global.thread);
-
- return status2;
- }
-
- // Save the value so to avoid string comparison during normal operation.
- actions->array[cache->ats.array[at_j]].number = i;
-
- // Continue into the requested item.
- at_i = cache->ats.used;
- at_j = cache->ats.used + 1;
-
- cache->ats.array[at_i] = i;
- cache->ats.array[at_j] = 0;
- cache->ats.used += 2;
-
- cache->action.name_action.used = 0;
- cache->action.line_action = 0;
-
- cache->action.name_item.used = 0;
- cache->action.line_item = entry->items.array[i].line;
-
- status2 = f_string_dynamic_append_nulless(entry->items.array[i].name, &cache->action.name_item);
-
- if (F_status_is_error(status2)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status2), "f_string_dynamic_append_nulless", F_true, global.thread);
-
- return status2;
- }
-
- break;
- }
- } // for
-
- if (error_has || i >= entry->items.used) {
- if (i >= entry->items.used) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QThe %r item named '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, actions->array[cache->ats.array[at_j]].parameters.array[0], global.main->program.error.notable);
- fl_print_format("%[' does not exist.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.error, cache->action);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- if (F_status_is_error_not(status)) {
- status = F_status_set_error(F_valid_not);
- }
- }
- }
- else {
- break;
- }
- }
- } // for
-
- cache->action.line_action = 0;
- cache->action.name_action.used = 0;
-
- // End of actions found, so drop to previous loop in stack.
- if (cache->ats.array[at_j] == actions->used) {
-
- // All actions for "main" are processed so there is nothing left to do.
- if (at_i == 0) break;
-
- at_i -= 2;
- at_j -= 2;
-
- cache->ats.used -= 2;
- ++cache->ats.array[at_j];
-
- cache->action.line_item = entry->items.array[cache->ats.array[at_i]].line;
- cache->action.name_item.used = 0;
-
- status2 = f_string_dynamic_append_nulless(entry->items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
-
- if (F_status_is_error(status2)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status2), "f_string_dynamic_append_nulless", F_true, global.thread);
-
- return status2;
- }
- }
- } // while
-
- if (!controller_thread_is_enabled(is_entry, global.thread)) {
- return F_status_set_error(F_interrupt);
- }
-
- // If ready was never found in the entry, then default to always ready.
- if (global.setting->ready == controller_setting_ready_no_e) {
- global.setting->ready = controller_setting_ready_yes_e;
- }
-
- return status;
- }
-#endif // _di_controller_entry_preprocess_
-
-#ifndef _di_controller_entry_process_
- f_status_t controller_entry_process(const controller_global_t * const global, controller_cache_t * const cache, const bool failsafe, const bool is_entry) {
-
- f_status_t status = F_okay;
- f_status_t status_lock = F_okay;
-
- f_number_unsigned_t at_i = 0;
- f_number_unsigned_t at_j = 1;
-
- uint8_t options_force = 0;
- uint8_t options_process = 0;
-
- controller_entry_t *entry = is_entry ? &global->setting->entry : &global->setting->exit;
- controller_entry_action_t *entry_action = 0;
- controller_entry_actions_t *entry_actions = 0;
-
- // An empty stack is used here because each rule here is the first rule run in the rule's scope.
- const f_number_unsigneds_t stack = f_number_unsigneds_t_initialize;
-
- cache->ats.used = 0;
- cache->stack.used = 0;
-
- cache->action.line_action = 0;
- cache->action.line_item = 0;
- cache->action.name_action.used = 0;
- cache->action.name_item.used = 0;
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_number_unsigned_t), (void **) &cache->ats.array, &cache->ats.used, &cache->ats.size);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global->main->program.error, cache->action, F_status_set_fine(status), "f_memory_array_increase", F_true, global->thread);
-
- return status;
- }
-
- // utilize the ats cache as an item execution stack (at_i is for item index, and at_j (at_i + 1) is for action index).
- cache->ats.array[0] = failsafe ? global->setting->failsafe_item_id : 0;
- cache->ats.array[1] = 0;
- cache->ats.used = 2;
-
- cache->action.line_item = entry->items.array[cache->ats.array[0]].line;
- cache->action.name_item.used = 0;
-
- status = f_string_dynamic_append_nulless(entry->items.array[cache->ats.array[0]].name, &cache->action.name_item);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global->main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true, global->thread);
-
- return status;
- }
-
- if ((global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) || global->main->program.error.verbosity == f_console_verbosity_verbose_e || global->main->program.error.verbosity == f_console_verbosity_debug_e) {
- if ((global->main->program.error.verbosity > f_console_verbosity_error_e)) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%rProcessing %r%r item '", global->main->program.output.to, f_string_eol_s, failsafe ? controller_entry_print_failsafe_s : f_string_empty_s, is_entry ? controller_entry_s : controller_exit_s);
- fl_print_format("%[%Q%]'.%r", global->main->program.output.to, global->main->program.context.set.title, cache->action.name_item, global->main->program.context.set.notable, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
- }
-
- // The pre-process determines if ready is explicitly specified within the entry file and if it is not start as ready.
- if (global->setting->ready == controller_setting_ready_yes_e) {
- status = controller_perform_ready(global, cache, is_entry);
- if (F_status_is_error(status)) return status;
- }
-
- while (controller_thread_is_enabled(is_entry, global->thread)) {
-
- entry_actions = &entry->items.array[cache->ats.array[at_i]].actions;
-
- for (; cache->ats.array[at_j] < entry_actions->used && controller_thread_is_enabled(is_entry, global->thread); ++cache->ats.array[at_j]) {
-
- entry_action = &entry_actions->array[cache->ats.array[at_j]];
-
- cache->action.line_action = entry_action->line;
- cache->action.name_action.used = 0;
-
- status = f_string_dynamic_append_nulless(controller_entry_action_type_name(entry_action->type), &cache->action.name_action);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global->main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true, global->thread);
-
- return status;
- }
-
- if (F_status_is_error(entry_action->status)) {
- if (global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) {
- if (global->main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%rThe %r item action '", global->main->program.output.to, f_string_eol_s, is_entry ? controller_entry_s : controller_exit_s);
- fl_print_format(f_string_format_Q_single_s.string, global->main->program.output.to, global->main->program.context.set.title, cache->action.name_action, global->main->program.context.set.title);
-
- if (entry_action->parameters.used) {
- fl_print_format(" %[", global->main->program.output.to, global->main->program.context.set.notable);
-
- controller_entry_action_parameters_print(&global->main->program.output, *entry_action);
-
- fl_print_format("%]", global->main->program.output.to, global->main->program.context.set.notable);
- }
-
- fl_print_format("' is %[%r%] and is in a ", global->main->program.output.to, global->main->program.context.set.notable, entry_action->code & controller_entry_rule_code_require_d ? "required" : "optional", global->main->program.context.set.notable);
-
- fl_print_format("%[failed%] state, skipping.%r", global->main->program.output.to, global->main->program.context.set.notable, global->main->program.context.set.notable, global->main->program.context.set.notable, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
- }
- else {
- if ((entry_action->code & controller_entry_rule_code_require_d) && global->main->program.error.verbosity > f_console_verbosity_quiet_e || !(entry_action->code & controller_entry_rule_code_require_d) && (global->main->program.warning.verbosity == f_console_verbosity_verbose_e || global->main->program.warning.verbosity == f_console_verbosity_debug_e)) {
- fl_print_t *print = 0;
-
- if (entry_action->code & controller_entry_rule_code_require_d) {
- print = &global->main->program.error;
- }
- else if (global->main->program.error.verbosity != f_console_verbosity_error_e) {
- print = &global->main->program.warning;
- }
-
- if (print) {
- controller_lock_print(print->to, global->thread);
-
- fl_print_format("%r%[%QThe %r item action '%]", print->to, f_string_eol_s, print->context, print->prefix, is_entry ? controller_entry_s : controller_exit_s, print->context);
- fl_print_format(f_string_format_Q_single_s.string, print->to, print->notable, cache->action.name_action, print->notable);
-
-
- if (entry_action->parameters.used) {
- fl_print_format(" %[", print->to, global->main->program.context.set.notable);
-
- controller_entry_action_parameters_print(print, *entry_action);
-
- fl_print_format("%]", print->to, global->main->program.context.set.notable);
- }
-
- if (entry_action->code & controller_entry_rule_code_require_d) {
- fl_print_format("%[' is%] %[required%]", print->to, print->context, print->context, print->notable, print->notable);
- }
- else {
- fl_print_format("%[' is%] %[optional%]", print->to, print->context, print->context, print->notable, print->notable);
- }
-
- fl_print_format(" %[and is in a%] %[failed%]", print->to, print->context, print->context, print->notable, print->notable);
-
- if (entry_action->code & controller_entry_rule_code_require_d) {
- fl_print_format(" %[state, aborting.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else {
- fl_print_format(" %[state, skipping.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
-
- controller_entry_print_error_cache(is_entry, print, cache->action);
-
- controller_unlock_print_flush(print->to, global->thread);
- }
- }
-
- if (controller_entry_action_type_is_rule(entry_action->type) && entry_action->code & controller_entry_rule_code_require_d) {
- return F_status_is_error(F_require);
- }
- }
-
- continue;
- }
-
- if (entry_action->type == controller_entry_action_type_ready_e) {
- if ((entry_action->code & controller_entry_rule_code_wait_d) || global->setting->ready == controller_setting_ready_wait_e) {
- if ((global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) || global->main->program.error.verbosity == f_console_verbosity_verbose_e || global->main->program.error.verbosity == f_console_verbosity_debug_e || entry->show == controller_entry_show_init_e) {
- if (global->main->program.output.verbosity != f_console_verbosity_quiet_e && global->main->program.error.verbosity != f_console_verbosity_error_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%rWaiting before processing %r item action '", global->main->program.output.to, f_string_eol_s, is_entry ? controller_entry_s : controller_exit_s);
- fl_print_format(f_string_format_r_single_s.string, global->main->program.output.to, global->main->program.context.set.title, controller_ready_s, global->main->program.context.set.title);
- fl_print_format("'.%r", global->main->program.output.to, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
- }
-
- if (!(global->main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e)) {
- status = controller_rule_wait_all(*global, is_entry, F_false);
- if (F_status_is_error(status)) return status;
- }
- }
-
- if (global->setting->ready == controller_setting_ready_yes_e) {
- if ((global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) || global->main->program.error.verbosity == f_console_verbosity_verbose_e || global->main->program.error.verbosity == f_console_verbosity_debug_e) {
- if (global->main->program.output.verbosity != f_console_verbosity_quiet_e && global->main->program.error.verbosity != f_console_verbosity_error_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%rIgnoring %r item action '", global->main->program.output.to, f_string_eol_s, is_entry ? controller_entry_s : controller_exit_s);
- fl_print_format(f_string_format_r_single_s.string, global->main->program.output.to, global->main->program.context.set.title, controller_ready_s, global->main->program.context.set.title);
- fl_print_format("', state already is ready.%r", global->main->program.output.to, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
- }
- }
- else {
- if (!failsafe && (global->main->program.error.verbosity == f_console_verbosity_verbose_e || entry->show == controller_entry_show_init_e) && !(global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e)) {
- if (global->main->program.error.verbosity > f_console_verbosity_error_e) {
- fl_print_format("%rState is now '%[%r%]'.%r", global->main->program.output.to, f_string_eol_s, global->main->program.context.set.notable, controller_ready_s, global->main->program.context.set.notable, f_string_eol_s);
- }
- }
-
- status = controller_perform_ready(global, cache, is_entry);
- if (F_status_is_error(status)) return status;
- }
- }
- else if (entry_action->type == controller_entry_action_type_item_e) {
- if (entry_action->number == 0 || entry_action->number >= entry->items.used || failsafe && entry_action->number == global->setting->failsafe_item_id) {
-
- // This should not happen if the pre-process is working as intended, but in case it doesn't, return a critical error to prevent infinite recursion and similar errors.
- if (global->main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global->main->program.error.to, global->thread);
-
- fl_print_format("%r%[Invalid %r item index '%]", global->main->program.error.to, f_string_eol_s, global->main->program.error.context, is_entry ? controller_entry_s : controller_exit_s, global->main->program.error.context);
- fl_print_format("%[%un%]", global->main->program.error.to, global->main->program.error.notable, entry_action->number, global->main->program.error.notable);
- fl_print_format("%[' detected.%]%r", global->main->program.error.to, global->main->program.error.context, global->main->program.error.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global->main->program.error, cache->action);
-
- controller_unlock_print_flush(global->main->program.error.to, global->thread);
- }
-
- return F_status_is_error(F_critical);
- }
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_number_unsigned_t), (void **) &cache->ats.array, &cache->ats.used, &cache->ats.size);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global->main->program.error, cache->action, F_status_set_fine(status), "f_memory_array_increase", F_true, global->thread);
-
- return status;
- }
-
- // continue into the requested item.
- cache->ats.array[cache->ats.used] = entry_action->number;
- cache->ats.array[cache->ats.used + 1] = 0;
-
- at_i = cache->ats.used;
- at_j = cache->ats.used + 1;
-
- cache->ats.used += 2;
-
- cache->action.name_action.used = 0;
- cache->action.line_action = 0;
-
- cache->action.name_item.used = 0;
- cache->action.line_item = entry->items.array[cache->ats.array[at_i]].line;
-
- status = f_string_dynamic_append_nulless(entry->items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global->main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true, global->thread);
-
- return status;
- }
-
- if ((global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) || global->main->program.error.verbosity == f_console_verbosity_verbose_e || global->main->program.error.verbosity == f_console_verbosity_debug_e) {
- if (global->main->program.output.verbosity != f_console_verbosity_quiet_e && global->main->program.error.verbosity != f_console_verbosity_error_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%rProcessing %r item '", global->main->program.output.to, f_string_eol_s, is_entry ? controller_entry_s : controller_exit_s);
- fl_print_format(f_string_format_Q_single_s.string, global->main->program.output.to, global->main->program.context.set.title, cache->action.name_item, global->main->program.context.set.title);
- fl_print_format("'.%r", global->main->program.output.to, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
- }
-
- // Exit inner loop to force restarting and start processing the requested item.
- break;
- }
- else if (entry_action->type == controller_entry_action_type_consider_e || controller_entry_action_type_is_rule(entry_action->type)) {
- status_lock = controller_lock_write(is_entry, global->thread, &global->thread->lock.rule);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global->main->program.error, F_status_set_fine(status_lock), F_false, global->thread);
-
- break;
- }
-
- status = controller_rules_increase(&global->setting->rules);
-
- f_thread_unlock(&global->thread->lock.rule);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global->main->program.error, cache->action, F_status_set_fine(status), "controller_rules_increase", F_true, global->thread);
-
- return status;
- }
-
- const f_number_unsigned_t id_rule_length = entry_action->parameters.array[0].used + entry_action->parameters.array[1].used + 1;
- f_char_t id_rule_name[id_rule_length + 1];
- const f_string_static_t alias_rule = macro_f_string_static_t_initialize_1(id_rule_name, 0, id_rule_length);
-
- memcpy(id_rule_name, entry_action->parameters.array[0].string, sizeof(f_char_t) * entry_action->parameters.array[0].used);
- memcpy(id_rule_name + entry_action->parameters.array[0].used + 1, entry_action->parameters.array[1].string, sizeof(f_char_t) * entry_action->parameters.array[1].used);
-
- id_rule_name[entry_action->parameters.array[0].used] = f_path_separator_s.string[0];
- id_rule_name[id_rule_length] = 0;
-
- status_lock = controller_lock_read(is_entry, global->thread, &global->thread->lock.rule);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global->main->program.error, F_status_set_fine(status_lock), F_true, global->thread);
-
- break;
- }
-
- status = controller_rule_find(alias_rule, global->setting->rules, 0);
-
- f_thread_unlock(&global->thread->lock.rule);
-
- if ((global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) || global->main->program.error.verbosity == f_console_verbosity_verbose_e || global->main->program.error.verbosity == f_console_verbosity_debug_e || (entry->show == controller_entry_show_init_e && entry_action->type != controller_entry_action_type_consider_e)) {
- if (global->main->program.output.verbosity != f_console_verbosity_quiet_e && global->main->program.error.verbosity != f_console_verbosity_error_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%r%r %r item rule ", global->main->program.output.to, f_string_eol_s, entry_action->type == controller_entry_action_type_consider_e ? controller_entry_print_considering_s : controller_entry_print_processing_s, is_entry ? controller_entry_s : controller_exit_s);
- fl_print_format("'%[%Q%]'", global->main->program.output.to, global->main->program.context.set.title, alias_rule, global->main->program.context.set.title);
-
- if (entry->show == controller_entry_show_init_e && !(global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e)) {
- fl_print_format(" [%[%r%]]", global->main->program.output.to, global->main->program.context.set.notable, entry_action->code == controller_entry_rule_code_asynchronous_d ? controller_asynchronous_s : controller_synchronous_s, global->main->program.context.set.notable);
-
- if (entry_action->code == controller_entry_rule_code_wait_d) {
- fl_print_format(" [%[%r%]]", global->main->program.output.to, global->main->program.context.set.notable, controller_wait_s, global->main->program.context.set.notable);
- }
-
- if (entry_action->code == controller_entry_rule_code_require_d) {
- fl_print_format(" [%[%r%]]", global->main->program.output.to, global->main->program.context.set.notable, controller_required_s, global->main->program.context.set.notable);
- }
- }
-
- fl_print_format(".%r", global->main->program.output.to, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
- }
-
- if (!controller_thread_is_enabled(is_entry, global->thread)) break;
-
- // The rule is not yet loaded, ensure that it is loaded.
- if (status != F_true) {
-
- // Rule execution will re-use the existing cache, so save the current cache.
- const f_number_unsigned_t cache_line_action = cache->action.line_action;
- const f_number_unsigned_t cache_line_item = cache->action.line_item;
-
- const f_number_unsigned_t cache_name_action_used = cache->action.name_action.used;
- const f_number_unsigned_t cache_name_item_used = cache->action.name_item.used;
- const f_number_unsigned_t cache_name_file_used = cache->action.name_file.used;
-
- f_char_t cache_name_action[cache_name_action_used];
- f_char_t cache_name_item[cache_name_item_used];
- f_char_t cache_name_file[cache_name_file_used];
-
- memcpy(cache_name_action, cache->action.name_action.string, sizeof(f_char_t) * cache->action.name_action.used);
- memcpy(cache_name_item, cache->action.name_item.string, sizeof(f_char_t) * cache->action.name_item.used);
- memcpy(cache_name_file, cache->action.name_file.string, sizeof(f_char_t) * cache->action.name_file.used);
-
- status_lock = controller_lock_write(is_entry, global->thread, &global->thread->lock.rule);
-
- if (F_status_is_fine(status_lock)) {
- status = controller_rule_read(*global, is_entry, alias_rule, cache, entry, &global->setting->rules.array[global->setting->rules.used]);
- }
-
- // Restore cache.
- memcpy(cache->action.name_action.string, cache_name_action, sizeof(f_char_t) * cache_name_action_used);
- memcpy(cache->action.name_item.string, cache_name_item, sizeof(f_char_t) * cache_name_item_used);
- memcpy(cache->action.name_file.string, cache_name_file, sizeof(f_char_t) * cache_name_file_used);
-
- cache->action.name_action.string[cache_name_action_used] = 0;
- cache->action.name_item.string[cache_name_item_used] = 0;
- cache->action.name_file.string[cache_name_file_used] = 0;
-
- cache->action.name_action.used = cache_name_action_used;
- cache->action.name_item.used = cache_name_item_used;
- cache->action.name_file.used = cache_name_file_used;
-
- cache->action.line_action = cache_line_action;
- cache->action.line_item = cache_line_item;
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global->main->program.error, F_status_set_fine(status_lock), F_false, global->thread);
-
- break;
- }
-
- if (F_status_set_fine(status) == F_interrupt || !controller_thread_is_enabled(is_entry, global->thread)) {
- f_thread_unlock(&global->thread->lock.rule);
-
- break;
- }
-
- if (F_status_is_error(status)) {
- if (global->main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global->main->program.error.to, global->thread);
-
- controller_entry_print_error_cache(is_entry, &global->main->program.error, cache->action);
-
- controller_unlock_print_flush(global->main->program.error.to, global->thread);
- }
-
- // Designate the action as failed.
- entry_action->status = F_status_set_error(F_failure);
-
- if (!(global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e)) {
- f_thread_unlock(&global->thread->lock.rule);
-
- if (entry_action->code & controller_entry_rule_code_require_d) {
- return F_status_set_error(F_require);
- }
-
- ++cache->ats.array[at_j];
-
- break;
- }
- }
- else {
- ++global->setting->rules.used;
- }
-
- f_thread_unlock(&global->thread->lock.rule);
- }
-
- if (F_status_is_error_not(status)) {
- options_force = 0;
- options_process = 0;
-
- if (global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) {
- options_process |= controller_process_option_simulate_d;
- }
-
- if (entry_action->code & controller_entry_rule_code_require_d) {
- options_process |= controller_process_option_require_d;
- }
-
- if (entry_action->code & controller_entry_rule_code_wait_d) {
- options_process |= controller_process_option_wait_d;
- }
-
- if (global->main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e) {
- options_process |= controller_process_option_validate_d;
- }
-
- if (entry_action->code & controller_entry_rule_code_asynchronous_d) {
- if (!(global->main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e)) {
- options_force |= controller_process_option_asynchronous_d;
- }
-
- options_process |= controller_process_option_asynchronous_d;
- }
-
- status = controller_rule_process_begin(*global, options_force, alias_rule, controller_entry_action_type_to_rule_action_type(entry_action->type), options_process, is_entry ? controller_data_type_entry_e : controller_data_type_exit_e, stack, *cache);
-
- if (F_status_set_fine(status) == F_memory_not || status == F_child || F_status_set_fine(status) == F_interrupt) {
- break;
- }
-
- if (F_status_is_error(status) && !(global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) && (entry_action->code & controller_entry_rule_code_require_d)) {
- return F_status_set_error(F_require);
- }
- }
- }
- else if (entry_action->type == controller_entry_action_type_execute_e) {
- if ((global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) || global->main->program.error.verbosity == f_console_verbosity_verbose_e || global->main->program.error.verbosity == f_console_verbosity_debug_e || entry->show == controller_entry_show_init_e) {
- if (global->main->program.output.verbosity != f_console_verbosity_quiet_e && global->main->program.error.verbosity != f_console_verbosity_error_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%r%Q is executing '", global->main->program.output.to, f_string_eol_s, is_entry ? controller_entry_s : controller_exit_s);
-
- for (f_number_unsigned_t k = 0; k < entry_action->parameters.used; ++k) {
-
- fl_print_format(f_string_format_Q_single_s.string, global->main->program.output.to, global->main->program.context.set.title, entry_action->parameters.array[k], global->main->program.context.set.title);
-
- if (k + 1 < entry_action->parameters.used) {
- f_print_dynamic_raw(f_string_space_s, global->main->program.output.to);
- }
- } // for
-
- fl_print_format("'.%r", global->main->program.output.to, f_string_eol_s);
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
- }
-
- if (global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) return F_execute;
-
- controller_thread_process_cancel(*global, is_entry, is_entry ? controller_thread_cancel_execute_e : controller_thread_cancel_exit_execute_e);
-
- int result = 0;
- int option = FL_execute_parameter_option_path_d;
-
- if (entry->session == controller_entry_session_new_e) {
- option |= FL_execute_parameter_option_session_d;
- }
-
- status = fll_execute_into(f_string_empty_s, entry_action->parameters, option, 0, (void *) &result);
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) == F_file_found_not) {
- if (global->main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global->main->program.error.to, global->thread);
-
- fl_print_format("%r%[%QExecution failed, unable to find program or script '%]", global->main->program.error.to, f_string_eol_s, global->main->program.error.context, global->main->program.error.prefix, global->main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global->main->program.error.to, global->main->program.error.notable, entry_action->parameters.array[0], global->main->program.error.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global->main->program.error.to, global->main->program.error.context, global->main->program.error.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global->main->program.error, cache->action);
-
- controller_unlock_print_flush(global->main->program.error.to, global->thread);
- }
- }
- else {
- controller_entry_print_error(is_entry, &global->main->program.error, cache->action, F_status_set_fine(status), "fll_execute_into", F_true, global->thread);
- }
-
- return F_status_set_error(F_execute);
- }
- else if (result != 0) {
- if (global->main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global->main->program.error.to, global->thread);
-
- fl_print_format("%r%[%QExecution failed with return value of '%]", global->main->program.error.to, f_string_eol_s, global->main->program.error.context, global->main->program.error.prefix, global->main->program.error.context);
- fl_print_format("%[%i%]", global->main->program.error.to, global->main->program.error.notable, result, global->main->program.error.notable);
- fl_print_format("$['.%]%r", global->main->program.error.to, global->main->program.error.context, global->main->program.error.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global->main->program.error, cache->action);
-
- controller_unlock_print_flush(global->main->program.error.to, global->thread);
- }
-
- return F_status_set_error(F_execute);
- }
-
- return F_execute;
- }
- else if (entry_action->type == controller_entry_action_type_timeout_e) {
- if (entry_action->code == controller_entry_timeout_code_exit_d) {
- entry->timeout_exit = entry_action->number;
-
- controller_entry_preprocess_print_simulate_setting_value(*global, is_entry, controller_timeout_s, controller_exit_s, entry->items.array[global->setting->failsafe_item_id].name, controller_entry_print_suffix_megatime_s);
- }
- else if (entry_action->code == controller_entry_timeout_code_kill_d) {
- entry->timeout_kill = entry_action->number;
-
- controller_entry_preprocess_print_simulate_setting_value(*global, is_entry, controller_timeout_s, controller_kill_s, entry->items.array[global->setting->failsafe_item_id].name, controller_entry_print_suffix_megatime_s);
- }
- else if (entry_action->code == controller_entry_timeout_code_start_d) {
- entry->timeout_start = entry_action->number;
-
- controller_entry_preprocess_print_simulate_setting_value(*global, is_entry, controller_timeout_s, controller_start_s, entry->items.array[global->setting->failsafe_item_id].name, controller_entry_print_suffix_megatime_s);
- }
- else if (entry_action->code == controller_entry_timeout_code_stop_d) {
- entry->timeout_stop = entry_action->number;
-
- controller_entry_preprocess_print_simulate_setting_value(*global, is_entry, controller_timeout_s, controller_stop_s, entry->items.array[global->setting->failsafe_item_id].name, controller_entry_print_suffix_megatime_s);
- }
- }
- else if (entry_action->type == controller_entry_action_type_failsafe_e) {
-
- if (failsafe) {
- if (global->main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global->main->program.warning.to, global->thread);
-
- fl_print_format("%r%[%QFailsafe may not be specified when running in failsafe, ignoring.%]%r", global->main->program.warning.to, f_string_eol_s, global->main->program.warning.context, global->main->program.warning.prefix, global->main->program.warning.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global->main->program.warning, cache->action);
-
- controller_unlock_print_flush(global->main->program.warning.to, global->thread);
- }
- }
- else {
- if (entry_action->number == 0 || entry_action->number >= entry->items.used) {
-
- // This should not happen if the pre-process is working as designed, but in case it doesn't, return a critical error to prevent infinite recursion and similar errors.
- if (global->main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global->main->program.error.to, global->thread);
-
- fl_print_format("%r%[%QInvalid %r item index '%]", global->main->program.error.to, f_string_eol_s, global->main->program.error.context, global->main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global->main->program.error.context);
- fl_print_format("%[%un%]", global->main->program.error.to, global->main->program.error.notable, entry_action->number, global->main->program.error.notable);
- fl_print_format("%[' detected.%]%r", global->main->program.error.to, global->main->program.error.context, global->main->program.error.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global->main->program.error, cache->action);
-
- controller_unlock_print_flush(global->main->program.error.to, global->thread);
- }
-
- return F_status_is_error(F_critical);
- }
- else {
- global->setting->flag |= controller_setting_flag_failsafe_e;
- global->setting->failsafe_item_id = entry_action->number;
-
- controller_entry_preprocess_print_simulate_setting_value(*global, is_entry, controller_failsafe_s, f_string_empty_s, entry->items.array[global->setting->failsafe_item_id].name, f_string_empty_s);
- }
- }
- }
- } // for
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt) break;
-
- cache->action.line_action = 0;
- cache->action.name_action.used = 0;
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_require) {
- break;
- }
- }
-
- // End of actions found, so drop to previous loop in stack.
- if (cache->ats.array[at_j] == entry_actions->used) {
-
- // All actions for "main" are processed so there is nothing left to do.
- if (at_i == 0) break;
-
- at_i -= 2;
- at_j -= 2;
-
- cache->ats.used -= 2;
- ++cache->ats.array[at_j];
-
- cache->action.line_item = entry->items.array[cache->ats.array[at_i]].line;
- cache->action.name_item.used = 0;
-
- status = f_string_dynamic_append_nulless(entry->items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global->main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true, global->thread);
-
- break;
- }
- }
- } // while
-
- if (!controller_thread_is_enabled(is_entry, global->thread)) {
- return F_status_set_error(F_interrupt);
- }
-
- if (status == F_child) {
- return status;
- }
-
- if (F_status_is_error(status_lock)) {
- return status_lock;
- }
-
- // Check to see if any required processes failed, but do not do this if already operating in failsafe.
- if (F_status_is_error_not(status) && !failsafe && !(global->main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e) && global->setting->mode != controller_setting_mode_helper_e) {
- const f_status_t status_wait = controller_rule_wait_all(*global, is_entry, F_true);
- if (F_status_is_error(status_wait)) return status_wait;
- if (status_wait == F_require) return F_status_set_error(F_require);
- }
-
- if (((global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) && global->main->program.error.verbosity > f_console_verbosity_quiet_e) && global->main->program.error.verbosity != f_console_verbosity_error_e || global->main->program.error.verbosity == f_console_verbosity_verbose_e) {
- controller_lock_print(global->main->program.output.to, global->thread);
-
- fl_print_format("%rDone processing %r item '", global->main->program.output.to, f_string_eol_s, is_entry ? controller_entry_s : controller_exit_s);
- fl_print_format(f_string_format_r_single_s.string, global->main->program.output.to, global->main->program.context.set.title, controller_main_s, global->main->program.context.set.title);
- fl_print_format("'.%r", global->main->program.output.to, f_string_eol_s);
-
- // failsafe should not print the extra newline because the failure exit from controller_main should handle this.
- if (!failsafe) {
- f_print_dynamic_raw(f_string_eol_s, global->main->program.output.to);
- }
-
- controller_unlock_print_flush(global->main->program.output.to, global->thread);
- }
-
- return status;
- }
-#endif // _di_controller_entry_process_
-
-#ifndef _di_controller_entry_read_
- f_status_t controller_entry_read(const controller_global_t global, const bool is_entry, controller_cache_t * const cache) {
-
- f_status_t status = F_okay;
-
- controller_entry_t *entry = is_entry ? &global.setting->entry : &global.setting->exit;
-
- entry->status = F_known_not;
- entry->items.used = 0;
-
- if (global.main->setting.flag & controller_main_flag_init_e) {
- entry->session = controller_entry_session_new_e;
- }
- else {
- entry->session = controller_entry_session_same_e;
- }
-
- cache->action.line_action = 0;
- cache->action.line_item = 0;
-
- macro_f_time_simple_t_clear(cache->timestamp);
-
- cache->comments.used = 0;
- cache->delimits.used = 0;
-
- cache->content_action.used = 0;
-
- {
- f_number_unsigned_t i = 0;
-
- for (; i < cache->content_actions.used; ++i) {
- cache->content_actions.array[i].used = 0;
- } // for
-
- for (i = 0; i < cache->content_items.used; ++i) {
- cache->content_items.array[i].used = 0;
- } // for
- }
-
- cache->content_actions.used = 0;
- cache->content_items.used = 0;
-
- cache->object_actions.used = 0;
- cache->object_items.used = 0;
-
- cache->buffer_file.used = 0;
- cache->buffer_path.used = 0;
-
- cache->action.name_file.used = 0;
- cache->action.name_action.used = 0;
- cache->action.name_item.used = 0;
-
- if (is_entry) {
- status = controller_file_load(global, F_true, controller_entries_s, global.setting->name_entry, controller_entry_s, cache);
- }
- else {
- status = controller_file_load(global, F_false, controller_exits_s, global.setting->name_entry, controller_exit_s, cache);
-
- if (status == F_file_found_not) {
- return F_file_found_not;
- }
- }
-
- if (F_status_is_error_not(status)) {
- if (cache->buffer_file.used) {
- controller_state_interrupt_t custom = macro_controller_state_interrupt_t_initialize_1(is_entry, global.thread);
- f_state_t state = macro_f_state_t_initialize_1(controller_common_allocation_large_d, controller_common_allocation_small_d, F_okay, 0, 0, 0, &controller_thread_signal_state_fss, 0, (void *) &custom, 0);
- f_range_t range = macro_f_range_t_initialize_2(cache->buffer_file.used);
-
- fll_fss_basic_list_read(cache->buffer_file, &range, &cache->object_items, &cache->content_items, &cache->delimits, 0, &cache->comments, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true);
- }
- else {
- f_fss_apply_delimit(cache->delimits, &cache->buffer_file, &state);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_fss_apply_delimit", F_true, global.thread);
- }
- }
- }
- else {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fll_print_format("%r%[%QThe %r file is empty.%]%r", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context, f_string_eol_s);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- status = F_status_set_error(F_data_not);
- }
- }
-
- if (F_status_is_error_not(status) && cache->object_items.used) {
- status = controller_entry_items_increase_by(cache->object_items.used, &entry->items);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "controller_entry_items_increase_by", F_true, global.thread);
- }
- else {
-
- // 0x1 = main found, 0x2 = found existing.
- uint8_t code = 0;
-
- f_range_t *range = 0;
-
- f_number_unsigned_t at = 0;
- f_number_unsigned_t i = 0;
- f_number_unsigned_t j = 0;
-
- f_state_t state = f_state_t_initialize;
-
- for (; i < cache->object_items.used && controller_thread_is_enabled(is_entry, global.thread); ++i) {
-
- if (code & 0x2) {
- code -= 0x2;
- }
-
- at = 0;
- range = 0;
-
- cache->action.line_action = 0;
- cache->action.line_item = 0;
-
- cache->comments.used = 0;
- cache->delimits.used = 0;
-
- cache->content_action.used = 0;
- cache->content_actions.used = 0;
-
- cache->object_actions.used = 0;
-
- cache->buffer_path.used = 0;
-
- cache->action.name_action.used = 0;
- cache->action.name_item.used = 0;
-
- status = controller_entry_items_increase_by(controller_common_allocation_small_d, &entry->items);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "controller_entry_items_increase_by", F_true, global.thread);
-
- break;
- }
-
- status = f_string_dynamic_partial_append(cache->buffer_file, cache->object_items.array[i], &cache->action.name_item);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_partial_append", F_true, global.thread);
-
- break;
- }
-
- f_fss_count_lines(cache->buffer_file, cache->object_items.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_fss_count_lines", F_true, global.thread);
-
- break;
- }
-
- ++cache->action.line_item;
-
- for (j = (code & 0x1) ? 1 : 0; j < entry->items.used; ++j) {
-
- if (f_compare_dynamic(entry->items.array[j].name, cache->action.name_item) == F_equal_to) {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- fl_print_format("%r%[%QIgnoring duplicate %r item '%]", global.main->program.warning.to, f_string_eol_s, global.main->program.warning.context, global.main->program.warning.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.warning.to, global.main->program.warning.notable, cache->action.name_file, global.main->program.warning.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.warning.to, global.main->program.warning.context, global.main->program.warning.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.warning, cache->action);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
-
- code |= 0x2;
-
- break;
- }
- } // for
-
- if (code & 0x2) continue;
-
- range = &cache->content_items.array[i].array[0];
-
- if (f_compare_dynamic(controller_main_s, cache->action.name_item) == F_equal_to) {
- code |= 0x1;
-
- at = 0;
-
- if (!entry->items.used) {
- entry->items.used = 1;
- }
- }
- else if (f_compare_dynamic(controller_settings_s, cache->action.name_item) == F_equal_to) {
- status = controller_entry_settings_read(global, is_entry, *range, cache);
-
- continue;
- }
- else if (entry->items.used) {
- at = entry->items.used++;
- }
- else {
-
- // skip position 0, which is reserved for "main".
- entry->items.array[0].name.used = 0;
-
- at = 1;
- entry->items.used = 2;
- }
-
- entry->items.array[at].line = cache->action.line_item;
-
- status = f_string_dynamic_append_nulless(cache->action.name_item, &entry->items.array[at].name);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true);
-
- break;
- }
-
- status = controller_entry_actions_read(global, is_entry, *range, cache, &entry->items.array[at].actions);
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) != F_interrupt) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.error, cache->action);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- if (F_status_set_fine(status) == F_memory_not) {
- break;
- }
- }
- } // for
-
- if (is_entry && F_status_set_fine(status) == F_interrupt) {
- return status;
- }
-
- if (F_status_is_error_not(status)) {
- cache->action.name_action.used = 0;
- cache->action.name_item.used = 0;
-
- if (!(code & 0x1)) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QThe required %r item '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_main_s, global.main->program.error.notable);
- fl_print_format("%[' is not found.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- status = F_status_set_error(F_found_not);
- }
-
- if (F_status_is_error_not(status)) {
- controller_entry_action_t *action = 0;
-
- f_number_unsigned_t k = 0;
-
- // 0x1 = missing or not, 0x2 = one or more missing.
- uint8_t missing = 0;
-
- for (i = 0; i < entry->items.used; ++i) {
-
- for (j = 0; j < entry->items.array[i].actions.used; ++j) {
-
- if (!controller_thread_is_enabled(is_entry, global.thread)) {
- return F_status_set_error(F_interrupt);
- }
-
- action = &entry->items.array[i].actions.array[j];
-
- // Only process actions that don't already have an error.
- if (F_status_is_error(action->status)) continue;
-
- if (action->type == controller_entry_action_type_failsafe_e || action->type == controller_entry_action_type_item_e) {
- missing |= 0x1;
-
- for (k = 0; k < entry->items.used; ++k) {
-
- if (f_compare_dynamic(action->parameters.array[0], entry->items.array[k].name) == F_equal_to) {
- missing &= ~0x1;
-
- break;
- }
- } // for
-
- if (missing & 0x1) {
- missing |= 0x2;
-
- cache->action.line_action = action->line;
- cache->action.line_item = entry->items.array[i].line;
-
- status = f_string_dynamic_append_nulless(entry->items.array[i].name, &cache->action.name_item);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true);
-
- break;
- }
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QThe required %r item '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, action->parameters.array[0], global.main->program.error.notable);
- fl_print_format("%[' does not exist.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.error, cache->action);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- action->number = 0;
- action->status = controller_status_simplify_error(F_found_not);
-
- cache->action.name_action.used = 0;
- cache->action.name_item.used = 0;
- }
- else {
- action->number = k;
- }
- }
- } // for
- } // for
- }
- }
- }
- }
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) != F_interrupt) {
- controller_entry_print_error_cache(is_entry, &global.main->program.error, cache->action);
- }
-
- entry->status = controller_status_simplify_error(F_status_set_fine(status));
- }
- else {
- entry->status = F_okay;
- }
-
- return entry->status;
- }
-#endif // _di_controller_entry_read_
-
-#ifndef _di_controller_entry_settings_read_
- f_status_t controller_entry_settings_read(const controller_global_t global, const bool is_entry, const f_range_t content_range, controller_cache_t * const cache) {
-
- f_status_t status = F_okay;
-
- {
- controller_state_interrupt_t custom = macro_controller_state_interrupt_t_initialize_1(is_entry, global.thread);
- f_state_t state = macro_f_state_t_initialize_1(controller_common_allocation_large_d, controller_common_allocation_small_d, F_okay, 0, 0, 0, &controller_thread_signal_state_fss, 0, (void *) &custom, 0);
- f_range_t range = content_range;
-
- fll_fss_extended_read(cache->buffer_file, &range, &cache->object_actions, &cache->content_actions, 0, 0, &cache->delimits, 0, &state);
- }
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "fll_fss_extended_read", F_true, global.thread);
-
- return status;
- }
-
- {
- f_state_t state = f_state_t_initialize;
-
- f_fss_apply_delimit(cache->delimits, &cache->buffer_file, &state);
- }
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_fss_apply_delimit", F_true, global.thread);
-
- return status;
- }
-
- cache->delimits.used = 0;
-
- f_number_unsigned_t i = 0;
-
- controller_entry_t *entry = is_entry ? &global.setting->entry : &global.setting->exit;
- f_state_t state = f_state_t_initialize;
-
- for (; i < cache->object_actions.used; ++i) {
-
- cache->action.line_action = 0;
-
- f_fss_count_lines(cache->buffer_file, cache->object_actions.array[i].start, &cache->action.line_action, &global.main->setting.state);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_fss_count_lines", F_true, global.thread);
-
- break;
- }
-
- ++cache->action.line_action;
- cache->action.name_action.used = 0;
-
- status = f_rip_dynamic_partial_nulless(cache->buffer_file, cache->object_actions.array[i], &cache->action.name_action);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_rip_dynamic_partial_nulless", F_true, global.thread);
-
- break;
- }
-
- if (is_entry && f_compare_dynamic(controller_control_s, cache->action.name_action) == F_equal_to) {
- if (cache->content_actions.array[i].used < 1 || cache->content_actions.array[i].used > 2) {
- controller_entry_settings_read_print_setting_requires_between(global, is_entry, *cache, 1, 2);
-
- continue;
- }
-
- if (cache->content_actions.array[i].used == 2) {
- if (f_compare_dynamic_partial_string(controller_readonly_s.string, cache->buffer_file, controller_readonly_s.used, cache->content_actions.array[i].array[1]) == F_equal_to) {
- global.setting->control.flag |= controller_control_flag_readonly_e;
- }
- else {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QThe %r item setting '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_control_s, global.main->program.error.notable);
- fl_print_format("%[' does not support the option '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- fl_print_format(f_string_format_Q_range_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->buffer_file, cache->content_actions.array[i].array[1], global.main->program.error.notable);
-
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.error, cache->action);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
-
- continue;
- }
- }
- }
- else {
- global.setting->control.flag &= ~controller_control_flag_readonly_e;
- }
-
- cache->action.generic.used = 0;
- global.setting->path_control.used = 0;
-
- status = f_rip_dynamic_partial_nulless(cache->buffer_file, cache->content_actions.array[i].array[0], &cache->action.generic);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_rip_dynamic_partial_nulless", F_true, global.thread);
-
- break;
- }
-
- global.setting->path_control.used = 0;
-
- status = controller_path_canonical_relative(global.setting, cache->action.generic, &global.setting->path_control);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error_file(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "controller_path_canonical_relative", F_true, cache->action.generic, f_file_operation_analyze_s, fll_error_file_type_path_e, global.thread);
-
- continue;
- }
- }
- else if (is_entry && f_compare_dynamic(controller_control_group_s, cache->action.name_action) == F_equal_to) {
- gid_t number = 0;
-
- status = controller_get_id_group(cache->buffer_file, cache->content_actions.array[i].array[0], cache, &number);
-
- if (F_status_is_error(status)) {
- status = F_status_set_fine(status);
-
- if (status == F_exist_not) {
- controller_entry_setting_read_print_error_with_range(is_entry, &global.main->program.error, " has an invalid group", cache->content_actions.array[i].array[0], ", because no group was found by that name", global.thread, cache);
- }
- else if (status == F_number_too_large) {
- controller_entry_setting_read_print_error_with_range(is_entry, &global.main->program.error, " has an invalid group", cache->content_actions.array[i].array[0], ", because the given ID is too large", global.thread, cache);
- }
- else if (status == F_number) {
- controller_entry_setting_read_print_error_with_range(is_entry, &global.main->program.error, " has an invalid group", cache->content_actions.array[i].array[0], ", because the given ID is not a valid supported number", global.thread, cache);
- }
- else {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "controller_get_id_group", F_true, global.thread);
- }
-
- continue;
- }
-
- global.setting->control.group = number;
- global.setting->control.flag |= controller_control_flag_has_group_e;
- }
- else if (is_entry && f_compare_dynamic(controller_control_mode_s, cache->action.name_action) == F_equal_to) {
- mode_t mode = 0;
- uint8_t replace = 0;
- f_file_mode_t mode_file = f_file_mode_t_initialize;
-
- cache->action.generic.used = 0;
-
- status = f_rip_dynamic_partial_nulless(cache->buffer_file, cache->content_actions.array[i].array[0], &cache->action.generic);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_rip_dynamic_partial_nulless", F_true, global.thread);
-
- break;
- }
-
- status = f_file_mode_from_string(cache->action.generic, global.main->program.umask, &mode_file, &replace);
-
- if (F_status_is_error(status)) {
- controller_entry_setting_read_print_error_with_range(is_entry, &global.main->program.error, " has an unsupported mode", cache->content_actions.array[i].array[0], ", because the format is unknown or contains invalid data", global.thread, cache);
-
- continue;
- }
-
- status = f_file_mode_to_mode(mode_file, &mode);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_file_mode_to_mode", F_true, global.thread);
-
- continue;
- }
-
- global.setting->control.mode = mode;
- global.setting->control.flag |= controller_control_flag_has_mode_e;
- }
- else if (is_entry && f_compare_dynamic(controller_control_user_s, cache->action.name_action) == F_equal_to) {
- uid_t number = 0;
-
- status = controller_get_id_user(cache->buffer_file, cache->content_actions.array[i].array[0], cache, &number);
-
- if (F_status_is_error(status)) {
- status = F_status_set_fine(status);
-
- if (status == F_exist_not) {
- controller_entry_setting_read_print_error_with_range(is_entry, &global.main->program.error, " has an invalid user", cache->content_actions.array[i].array[0], ", because no user was found by that name", global.thread, cache);
- }
- else if (status == F_number_too_large) {
- controller_entry_setting_read_print_error_with_range(is_entry, &global.main->program.error, " has an invalid user", cache->content_actions.array[i].array[0], ", because the given ID is too large", global.thread, cache);
- }
- else if (status == F_number) {
- controller_entry_setting_read_print_error_with_range(is_entry, &global.main->program.error, " has an invalid user", cache->content_actions.array[i].array[0], ", because the given ID is not a valid supported number", global.thread, cache);
- }
- else {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "controller_get_id_user", F_true, global.thread);
- }
-
- continue;
- }
-
- global.setting->control.user = number;
- global.setting->control.flag |= controller_control_flag_has_user_e;
- }
- else if (f_compare_dynamic(controller_define_s, cache->action.name_action) == F_equal_to) {
- if (cache->content_actions.array[i].used != 2) {
- controller_entry_settings_read_print_setting_requires_exactly(global, is_entry, *cache, 2);
-
- continue;
- }
-
- status = controller_entry_settings_read_map(cache->buffer_file, cache->content_actions.array[i], &entry->define);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "controller_entry_settings_read_map", F_true, global.thread);
-
- continue;
- }
- }
- else if (is_entry && f_compare_dynamic(controller_mode_s, cache->action.name_action) == F_equal_to) {
- if (cache->content_actions.array[i].used != 1) {
- controller_entry_settings_read_print_setting_requires_exactly(global, is_entry, *cache, 1);
-
- continue;
- }
-
- if (f_compare_dynamic_partial_string(controller_service_s.string, cache->buffer_file, controller_service_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- global.setting->mode = controller_setting_mode_service_e;
- }
- else if (f_compare_dynamic_partial_string(controller_helper_s.string, cache->buffer_file, controller_helper_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- global.setting->mode = controller_setting_mode_helper_e;
- }
- else if (f_compare_dynamic_partial_string(controller_program_s.string, cache->buffer_file, controller_program_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- global.setting->mode = controller_setting_mode_program_e;
- }
- else {
- controller_entry_settings_read_print_setting_unknown_action_value(global, is_entry, *cache, i);
-
- continue;
- }
- }
- else if (f_compare_dynamic(controller_parameter_s, cache->action.name_action) == F_equal_to) {
- if (cache->content_actions.array[i].used != 2) {
- controller_entry_settings_read_print_setting_requires_exactly(global, is_entry, *cache, 2);
-
- continue;
- }
-
- status = controller_entry_settings_read_map(cache->buffer_file, cache->content_actions.array[i], &entry->parameter);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "controller_entry_settings_read_map", F_true, global.thread);
-
- continue;
- }
- }
- else if (f_compare_dynamic(controller_pid_s, cache->action.name_action) == F_equal_to) {
- if (cache->content_actions.array[i].used != 1) {
- controller_entry_settings_read_print_setting_requires_exactly(global, is_entry, *cache, 1);
-
- continue;
- }
-
- if (f_compare_dynamic_partial_string(controller_disable_s.string, cache->buffer_file, controller_disable_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- entry->pid = controller_entry_pid_disable_e;
- }
- else if (f_compare_dynamic_partial_string(controller_ready_s.string, cache->buffer_file, controller_ready_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- entry->pid = controller_entry_pid_ready_e;
- }
- else if (f_compare_dynamic_partial_string(controller_require_s.string, cache->buffer_file, controller_require_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- entry->pid = controller_entry_pid_require_e;
- }
- else {
- controller_entry_settings_read_print_setting_unknown_action_value(global, is_entry, *cache, i);
-
- continue;
- }
- }
- else if (is_entry && f_compare_dynamic(controller_pid_file_s, cache->action.name_action) == F_equal_to) {
- if (cache->content_actions.array[i].used != 1) {
- controller_entry_settings_read_print_setting_requires_exactly(global, is_entry, *cache, 1);
-
- continue;
- }
-
- if (global.main->program.parameters.array[controller_parameter_pid_e].result & f_console_result_value_e) {
- controller_entry_settings_read_print_setting_ignored(global, is_entry, *cache, i);
- }
- else {
- cache->action.generic.used = 0;
-
- status = f_rip_dynamic_partial_nulless(cache->buffer_file, cache->content_actions.array[i].array[0], &cache->action.generic);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "f_rip_dynamic_partial_nulless", F_true, global.thread);
-
- continue;
- }
-
- global.setting->path_pid.used = 0;
-
- status = controller_path_canonical_relative(global.setting, cache->action.generic, &global.setting->path_pid);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "controller_path_canonical_relative", F_true, global.thread);
-
- continue;
- }
- }
- }
- else if (f_compare_dynamic(controller_session_s, cache->action.name_action) == F_equal_to) {
- if (cache->content_actions.array[i].used != 1) {
- controller_entry_settings_read_print_setting_requires_exactly(global, is_entry, *cache, 1);
-
- continue;
- }
-
- if (f_compare_dynamic_partial_string(controller_new_s.string, cache->buffer_file, controller_new_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- entry->session = controller_entry_session_new_e;
- }
- else if (f_compare_dynamic_partial_string(controller_same_s.string, cache->buffer_file, controller_same_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- entry->session = controller_entry_session_same_e;
- }
- else {
- controller_entry_settings_read_print_setting_unknown_action_value(global, is_entry, *cache, i);
-
- continue;
- }
- }
- else if (f_compare_dynamic(controller_show_s, cache->action.name_action) == F_equal_to) {
- if (cache->content_actions.array[i].used != 1) {
- controller_entry_settings_read_print_setting_requires_exactly(global, is_entry, *cache, 1);
-
- continue;
- }
-
- if (f_compare_dynamic_partial_string(controller_normal_s.string, cache->buffer_file, controller_normal_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- entry->show = controller_entry_show_normal_e;
- }
- else if (f_compare_dynamic_partial_string(controller_init_s.string, cache->buffer_file, controller_init_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- entry->show = controller_entry_show_init_e;
- }
- else {
- controller_entry_settings_read_print_setting_unknown_action_value(global, is_entry, *cache, i);
-
- continue;
- }
- }
- else if (f_compare_dynamic(controller_timeout_s, cache->action.name_action) == F_equal_to) {
- if (cache->content_actions.array[i].used < 1 || cache->content_actions.array[i].used > 2) {
- controller_entry_settings_read_print_setting_requires_between(global, is_entry, *cache, 1, 2);
-
- continue;
- }
-
- f_number_unsigned_t *time = 0;
-
- if (f_compare_dynamic_partial_string(controller_exit_s.string, cache->buffer_file, controller_exit_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- if (cache->content_actions.array[i].used == 1) {
- entry->flag |= controller_entry_flag_timeout_exit_no_e;
-
- continue;
- }
-
- entry->flag &= ~controller_entry_flag_timeout_exit_no_e;
- time = &entry->timeout_exit;
- }
- else if (f_compare_dynamic_partial_string(controller_kill_s.string, cache->buffer_file, controller_kill_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- if (cache->content_actions.array[i].used == 1) {
- entry->flag |= controller_entry_flag_timeout_kill_no_e;
-
- continue;
- }
-
- entry->flag &= ~controller_entry_flag_timeout_kill_no_e;
- time = &entry->timeout_kill;
- }
- else if (f_compare_dynamic_partial_string(controller_start_s.string, cache->buffer_file, controller_start_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- if (cache->content_actions.array[i].used == 1) {
- entry->flag |= controller_entry_flag_timeout_start_no_e;
-
- continue;
- }
-
- entry->flag &= ~controller_entry_flag_timeout_start_no_e;
- time = &entry->timeout_start;
- }
- else if (f_compare_dynamic_partial_string(controller_stop_s.string, cache->buffer_file, controller_stop_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- if (cache->content_actions.array[i].used == 1) {
- entry->flag |= controller_entry_flag_timeout_stop_no_e;
-
- continue;
- }
-
- entry->flag &= ~controller_entry_flag_timeout_stop_no_e;
- time = &entry->timeout_stop;
- }
- else {
- controller_entry_settings_read_print_setting_unknown_action_value(global, is_entry, *cache, i);
-
- continue;
- }
-
- const f_number_unsigned_t time_previous = *time;
-
- status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, cache->buffer_file, cache->content_actions.array[i].array[1], time);
-
- if (F_status_is_error(status) || status == F_data_not) {
- *time = time_previous;
-
- if (F_status_set_fine(status) == F_memory_not) {
- controller_entry_print_error(is_entry, &global.main->program.error, cache->action, F_status_set_fine(status), "fl_conversion_dynamic_partial_to_unsigned_detect", F_true, global.thread);
-
- continue;
- }
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- f_file_stream_lock(global.main->program.error.to);
-
- fl_print_format("%r%[%QThe %r setting '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_Q_range_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->buffer_file, cache->content_actions.array[i].array[1], global.main->program.error.notable);
- fl_print_format("%[' is not a valid supported number.%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- f_file_stream_unlock(global.main->program.error.to);
- }
- }
- }
- else {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_entry_settings_read_print_setting_unknown_action(global, is_entry, *cache);
- }
-
- continue;
- }
- } // for
-
- return status;
- }
-#endif // _di_controller_entry_settings_read_
-
-#ifndef _di_controller_entry_settings_read_map_
- f_status_t controller_entry_settings_read_map(const f_string_static_t buffer, const f_ranges_t ranges, f_string_maps_t *setting_maps) {
-
- {
- f_status_t status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_string_map_t), (void **) &setting_maps->array, &setting_maps->used, &setting_maps->size);
- if (F_status_is_error(status)) return status;
-
- setting_maps->array[setting_maps->used].key.used = 0;
- setting_maps->array[setting_maps->used].value.used = 0;
-
- status = f_string_dynamic_partial_append_nulless(buffer, ranges.array[0], &setting_maps->array[setting_maps->used].key);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_partial_append_nulless(buffer, ranges.array[1], &setting_maps->array[setting_maps->used].value);
- if (F_status_is_error(status)) return status;
- }
-
- ++setting_maps->used;
-
- return F_okay;
- }
-#endif // _di_controller_entry_settings_read_map_
-
-#ifndef _di_controller_entry_setting_validate_
- void controller_entry_setting_validate(const controller_global_t global, const bool is_entry, controller_cache_t * const cache) {
-
- controller_entry_t * const entry = is_entry ? &global.setting->entry : &global.setting->exit;
-
- controller_lock_print(global.main->program.output.to, global.thread);
-
- const f_string_static_t *string = 0;
-
- f_status_t status = F_okay;
- f_number_unsigned_t i = 0;
- f_number_unsigned_t j = 0;
-
- fl_print_format("%r%Q %[%Q%] {%r", global.main->program.output.to, f_string_eol_s, is_entry ? controller_Entry_s : controller_Exit_s, global.main->program.context.set.title, controller_settings_s, global.main->program.context.set.title, f_string_eol_s);
-
-
- // Mode.
- if (global.setting->mode == controller_setting_mode_service_e) {
- string = &controller_mode_s;
- }
- else if (global.setting->mode == controller_setting_mode_helper_e) {
- string = &controller_helper_s;
- }
- else if (global.setting->mode == controller_setting_mode_program_e) {
- string = &controller_program_s;
- }
- else {
- string = &f_string_empty_s;
- }
-
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_mode_s, global.main->program.context.set.important, f_string_eol_s);
-
- if (string->used) {
- fl_print_format(" %r", global.main->program.output.to, *string);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Session.
- if (entry->pid == controller_entry_session_new_e) {
- string = &controller_new_s;
- }
- else if (entry->pid == controller_entry_session_same_e) {
- string = &controller_same_s;
- }
- else {
- string = &f_string_empty_s;
- }
-
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_session_s, global.main->program.context.set.important, f_string_eol_s);
-
- if (string->used) {
- fl_print_format(" %r", global.main->program.output.to, *string, f_string_eol_s);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Show.
- if (entry->pid == controller_entry_show_normal_e) {
- string = &controller_normal_s;
- }
- else if (entry->pid == controller_entry_show_init_e) {
- string = &controller_init_s;
- }
- else {
- string = &f_string_empty_s;
- }
-
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_show_s, global.main->program.context.set.important, f_string_eol_s);
-
- if (string->used) {
- fl_print_format(" %r", global.main->program.output.to, *string, f_string_eol_s);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Pid.
- if (entry->pid == controller_entry_pid_disable_e) {
- string = &controller_disable_s;
- }
- else if (entry->pid == controller_entry_pid_require_e) {
- string = &controller_require_s;
- }
- else if (entry->pid == controller_entry_pid_ready_e) {
- string = &controller_ready_s;
- }
- else {
- string = &f_string_empty_s;
- }
-
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_pid_s, global.main->program.context.set.important);
-
- if (string->used) {
- fl_print_format(" %r", global.main->program.output.to, *string);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Pid File.
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_pid_file_s, global.main->program.context.set.important);
-
- if (global.setting->path_pid.used) {
- fl_print_format(" %r", global.main->program.output.to, global.setting->path_pid);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Control.
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_control_s, global.main->program.context.set.important);
-
- if (global.setting->path_control.used) {
- fl_print_format(" %Q", global.main->program.output.to, global.setting->path_control);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Control Has.
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_control_has_s, global.main->program.context.set.important);
-
- if (global.setting->control.flag & controller_control_flag_readonly_e) {
- fl_print_format(" %r", global.main->program.output.to, controller_readonly_s);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Control User.
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_control_user_s, global.main->program.context.set.important);
-
- if (global.setting->control.flag & controller_control_flag_has_user_e) {
- fl_print_format(" %u", global.main->program.output.to, (unsigned int) global.setting->control.user);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Control Group.
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_control_group_s, global.main->program.context.set.important);
-
- if (global.setting->control.flag & controller_control_flag_has_group_e) {
- fl_print_format(" %u", global.main->program.output.to, (unsigned int) global.setting->control.group);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Control Mode.
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_control_mode_s, global.main->program.context.set.important);
-
- if (F_status_is_error_not(status)) {
- if (global.setting->control.flag & controller_control_flag_has_group_e) {
- fl_print_format(" %@05u", global.main->program.output.to, (unsigned int) global.setting->control.mode);
- }
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Timeout: Exit.
- fl_print_format(" %[%r%] %r", global.main->program.output.to, global.main->program.context.set.important, controller_timeout_s, global.main->program.context.set.important, controller_exit_s);
-
- if (!(entry->flag & controller_entry_flag_timeout_exit_no_e)) {
- fl_print_format(" %ul", global.main->program.output.to, entry->timeout_exit, f_string_eol_s);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Timeout: Kill.
- fl_print_format(" %[%r%] %r", global.main->program.output.to, global.main->program.context.set.important, controller_timeout_s, global.main->program.context.set.important, controller_kill_s);
-
- if (!(entry->flag & controller_entry_flag_timeout_kill_no_e)) {
- fl_print_format(" %ul", global.main->program.output.to, entry->timeout_kill, f_string_eol_s);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Timeout: Start.
- fl_print_format(" %[%r%] %r", global.main->program.output.to, global.main->program.context.set.important, controller_timeout_s, global.main->program.context.set.important, controller_start_s);
-
- if (!(entry->flag & controller_entry_flag_timeout_start_no_e)) {
- fl_print_format(" %ul", global.main->program.output.to, entry->timeout_start, f_string_eol_s);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Timeout: Stop.
- fl_print_format(" %[%r%] %r", global.main->program.output.to, global.main->program.context.set.important, controller_timeout_s, global.main->program.context.set.important, controller_stop_s);
-
- if (!(entry->flag & controller_entry_flag_timeout_stop_no_e)) {
- fl_print_format(" %ul", global.main->program.output.to, entry->timeout_stop, f_string_eol_s);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Define.
- fl_print_format(" %[%r%] {%r", global.main->program.output.to, global.main->program.context.set.important, controller_define_s, global.main->program.context.set.important, f_string_eol_s);
-
- for (i = 0; i < entry->define.used; ++i) {
- fl_print_format(" %Q %Q%r", global.main->program.output.to, entry->define.array[i].key, entry->define.array[i].value, f_string_eol_s);
- } // for
-
- fl_print_format(" }%r", global.main->program.output.to, f_string_eol_s, f_string_eol_s);
-
-
- // Parameter.
- fl_print_format(" %[%r%] {%r", global.main->program.output.to, global.main->program.context.set.important, controller_parameter_s, global.main->program.context.set.important, f_string_eol_s);
-
- for (i = 0; i < entry->parameter.used; ++i) {
- fl_print_format(" %Q %Q%r", global.main->program.output.to, entry->parameter.array[i].key, entry->parameter.array[i].value, f_string_eol_s);
- } // for
-
- fl_print_format(" }%r", global.main->program.output.to, f_string_eol_s);
-
- fl_print_format("}%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Entry Items.
- if (entry->items.used) {
- controller_entry_action_t *action = 0;
- bool raw = F_false;
- f_number_unsigned_t k = 0;
-
- for (i = 0; i < entry->items.used; ++i) {
-
- fl_print_format("%r%Q %Q %[%Q%] {%r", global.main->program.output.to, f_string_eol_s, is_entry ? controller_Entry_s : controller_Exit_s, controller_Item_s, global.main->program.context.set.title, entry->items.array[i].name, global.main->program.context.set.title, f_string_eol_s);
-
- for (j = 0; j < entry->items.array[i].actions.used; ++j) {
-
- action = &entry->items.array[i].actions.array[j];
-
- fl_print_format(" %[%r%] {%r", global.main->program.output.to, global.main->program.context.set.important, controller_action_s, global.main->program.context.set.important, f_string_eol_s);
-
-
- // Item Type.
- if (action->type == controller_entry_action_type_consider_e) {
- string = &controller_consider_s;
- raw = F_false;
- }
- else if (action->type == controller_entry_action_type_execute_e) {
- string = &controller_execute_s;
- raw = F_true;
- }
- else if (action->type == controller_entry_action_type_failsafe_e) {
- string = &controller_failsafe_s;
- raw = F_true;
- }
- else if (action->type == controller_entry_action_type_freeze_e) {
- string = &controller_freeze_s;
- raw = F_false;
- }
- else if (action->type == controller_entry_action_type_item_e) {
- string = &controller_item_s;
- raw = F_true;
- }
- else if (action->type == controller_entry_action_type_kexec_e) {
- string = &controller_kexec_s;
- raw = F_false;
- }
- else if (action->type == controller_entry_action_type_kill_e) {
- string = &controller_kill_s;
- raw = F_false;
- }
- else if (action->type == controller_entry_action_type_pause_e) {
- string = &controller_pause_s;
- raw = F_false;
- }
- else if (action->type == controller_entry_action_type_ready_e) {
- string = &controller_ready_s;
- raw = F_true;
- }
- else if (action->type == controller_entry_action_type_reboot_e) {
- string = &controller_reboot_s;
- raw = F_false;
- }
- else if (action->type == controller_entry_action_type_reload_e) {
- string = &controller_reload_s;
- raw = F_false;
- }
- else if (action->type == controller_entry_action_type_restart_e) {
- string = &controller_restart_s;
- raw = F_false;
- }
- else if (action->type == controller_entry_action_type_resume_e) {
- string = &controller_resume_s;
- raw = F_false;
- }
- else if (action->type == controller_entry_action_type_shutdown_e) {
- string = &controller_shutdown_s;
- raw = F_false;
- }
- else if (action->type == controller_entry_action_type_start_e) {
- string = &controller_start_s;
- raw = F_false;
- }
- else if (action->type == controller_entry_action_type_stop_e) {
- string = &controller_stop_s;
- raw = F_false;
- }
- else if (action->type == controller_entry_action_type_timeout_e) {
- string = &controller_timeout_s;
- raw = F_true;
- }
- else if (action->type == controller_entry_action_type_thaw_e) {
- string = &controller_thaw_s;
- raw = F_false;
- }
- else {
- string = &f_string_empty_s;
- }
-
- fl_print_format(" %[%r%] %r%r", global.main->program.output.to, global.main->program.context.set.important, controller_type_s, global.main->program.context.set.important, *string, f_string_eol_s);
-
-
- // Item Code (How).
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_how_s, global.main->program.context.set.important);
-
- if (action->code) {
- if (action->code == controller_entry_rule_code_asynchronous_d) {
- fl_print_format(" %r", global.main->program.output.to, controller_asynchronous_s);
- }
-
- if (action->type == controller_entry_rule_code_require_d) {
- fl_print_format(" %r", global.main->program.output.to, controller_require_s);
- }
-
- if (action->type == controller_entry_rule_code_wait_d) {
- fl_print_format(" %r", global.main->program.output.to, controller_wait_s);
- }
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Parameters.
- if (action->type == controller_entry_action_type_item_e) {
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_item_s, global.main->program.context.set.important);
-
- if (action->parameters.used && action->parameters.array[0].used) {
- fl_print_format(" %Q", global.main->program.output.to, action->parameters.array[0], f_string_eol_s);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
- }
- else if (raw) {
- for (k = 0; k < action->parameters.used; ++k) {
- fl_print_format(" %[%r%] %Q%r", global.main->program.output.to, global.main->program.context.set.important, controller_parameter_s, global.main->program.context.set.important, action->parameters.array[k], f_string_eol_s);
- } // for
- }
- else {
-
- // Parameter, Directory.
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_directory_s, global.main->program.context.set.important);
-
- if (action->parameters.used && action->parameters.array[0].used) {
- fl_print_format(" %Q", global.main->program.output.to, action->parameters.array[0], f_string_eol_s);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
-
-
- // Parameter, File.
- fl_print_format(" %[%r%]", global.main->program.output.to, global.main->program.context.set.important, controller_file_s, global.main->program.context.set.important);
-
- if (action->parameters.used && action->parameters.array[0].used > 1) {
- fl_print_format(" %Q", global.main->program.output.to, action->parameters.array[1], f_string_eol_s);
- }
-
- fl_print_format("%r", global.main->program.output.to, f_string_eol_s);
- }
-
- fl_print_format(" }%r", global.main->program.output.to, f_string_eol_s);
- } // for
-
- fl_print_format("}%r", global.main->program.output.to, f_string_eol_s);
- } // for
- }
-
- controller_unlock_print_flush(global.main->program.output.to, global.thread);
- }
-#endif // _di_controller_entry_setting_validate_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_entry_h
-#define _PRIVATE_entry_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Determine if the type code represents a Rule type.
- *
- * @param type
- * The type code to compare against.
- *
- * @return
- * TRUE if Rule type.
- * FALSE otherwise.
- */
-#ifndef _di_controller_entry_action_type_is_rule_
- extern f_status_t controller_entry_action_type_is_rule(uint8_t type) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_action_type_is_rule_
-
-/**
- * Convert the Entry Action type to Rule Action type.
- *
- * @param type
- * The Entry Action type.
- *
- * @return
- * TRUE if Rule type.
- * FALSE otherwise.
- */
-#ifndef _di_controller_entry_action_type_to_rule_action_type_
- extern uint8_t controller_entry_action_type_to_rule_action_type(uint8_t type) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_action_type_to_rule_action_type_
-
-/**
- * Read the entry list, extracting all items and values.
- *
- * @param global
- * The global data.
- * @param is_entry
- * If TRUE, then this loads as an entry.
- * If FALSE, then this loads as an exit.
- * @param content_range
- * The range in the list buffer representing the content.
- * @param cache
- * A structure for containing and caching relevant data.
- * @param actions
- * The processed actions.
- *
- * @return
- * F_okay on success.
- *
- * Errors (with error bit) from: controller_entry_actions_increase_by().
- * Errors (with error bit) from: f_fss_apply_delimit().
- * Errors (with error bit) from: f_fss_count_lines().
- * Errors (with error bit) from: f_memory_array_increase_by().
- * Errors (with error bit) from: f_rip_dynamic_partial_nulless().
- * Errors (with error bit) from: f_string_dynamic_partial_append_nulless().
- * Errors (with error bit) from: fll_fss_extended_read().
- *
- * @see controller_entry_actions_increase_by()
- * @see f_fss_apply_delimit()
- * @see f_fss_count_lines()
- * @see f_memory_array_increase_by()
- * @see f_rip_dynamic_partial_nulless()
- * @see f_string_dynamic_partial_append_nulless()
- * @see fll_fss_extended_read()
- */
-#ifndef _di_controller_entry_actions_read_
- extern f_status_t controller_entry_actions_read(const controller_global_t global, const bool is_entry, const f_range_t content_range, controller_cache_t * const cache, controller_entry_actions_t *actions) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_actions_read_
-
-/**
- * Pre-process all items for the loaded entry.
- *
- * @param global
- * The global data.
- * @param is_entry
- * If TRUE, then this operate as an entry.
- * If FALSE, then this operate as an exit.
- * @param cache
- * The main/global cache to use.
- *
- * @return
- * F_okay on success.
- * F_recurse (with error bit) on a recursion error.
- * F_valid_not (with error bit) on invalid entry item, entry item action, or entry item action value.
- *
- * Errors (with error bit) from: macro_f_number_unsigneds_t_increase_by().
- * Errors (with error bit) from: f_string_dynamic_append().
- *
- * This will detect and report all errors, but only the first error is returned.
- * Memory related errors return immediately.
-
- * @see macro_f_number_unsigneds_t_increase_by()
- * @see f_string_dynamic_append()
- */
-#ifndef _di_controller_entry_preprocess_
- extern f_status_t controller_entry_preprocess(const controller_global_t global, const bool is_entry, controller_cache_t * const cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_preprocess_
-
-/**
- * Process (execute) all Items for the loaded Entry or Exit.
- *
- * @param global
- * The global data.
- * @param cache
- * The main/global cache to use.
- * @param failsafe
- * If TRUE, operate in failsafe mode (starts at designated failsafe Item).
- * If FALSE, operate in normal mode (starts at "main" Item).
- * @param is_entry
- * If TRUE, then this operate as an entry.
- * If FALSE, then this operate as an exit.
- *
- * @return
- * F_okay on success.
- * F_execute on success and program exiting (scripts may result in this) or when execute would have been executed but is instead simulated.
- *
- * F_require (with error bit) if a required Item failed.
- * F_critical (with error bit) on any critical error.
- * F_execute (with error bit) if the "execute" Item Action failed.
- *
- * Errors (with error bit) from: f_string_dynamic_append_nulless().
- *
- * Errors (with error bit) from: macro_f_number_unsigneds_t_increase_by().
- * Errors (with error bit) from: controller_perform_ready().
- *
- * @see f_string_dynamic_append_nulless()
- *
- * @see macro_f_number_unsigneds_t_increase_by()
- * @see controller_perform_ready()
- */
-#ifndef _di_controller_entry_process_
- extern f_status_t controller_entry_process(const controller_global_t * const global, controller_cache_t * const cache, const bool failsafe, const bool is_entry) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_process_
-
-/**
- * Read the entry, extracting all lists.
- *
- * @param global
- * The global data.
- * @param is_entry
- * If TRUE, then this loads as an entry.
- * If FALSE, then this loads as an exit.
- * @param cache
- * The cache for the specific thread.
- * This should be the cache global.thread->asynchronouss.array[global.id].cache.
- *
- * @return
- * F_okay on success.
- * F_file_found_not on file not found for a an exit file (is_entry is FALSE).
- *
- * Errors (with error bit) from: controller_entry_actions_read().
- * Errors (with error bit) from: controller_entry_items_increase_by().
- * Errors (with error bit) from: controller_file_load().
- * Errors (with error bit) from: controller_status_simplify_error().
- *
- * Errors (with error bit) from: f_fss_count_lines().
- * Errors (with error bit) from: f_string_dynamic_append().
- * Errors (with error bit) from: f_string_dynamic_append_nulless().
- * Errors (with error bit) from: f_string_dynamic_partial_append().
- * Errors (with error bit) from: f_string_dynamic_partial_append_nulless().
- * Errors (with error bit) from: f_string_dynamic_terminate().
- * Errors (with error bit) from: f_fss_apply_delimit().
- * Errors (with error bit) from: fll_fss_basic_list_read().
- *
- * @see controller_entry_actions_read()
- * @see controller_entry_items_increase_by()
- * @see controller_file_load()
- * @see controller_status_simplify_error()
- *
- * @see f_fss_count_lines()
- * @see f_string_dynamic_append()
- * @see f_string_dynamic_append_nulless()
- * @see f_string_dynamic_partial_append()
- * @see f_string_dynamic_partial_append_nulless()
- * @see f_string_dynamic_terminate()
- * @see f_fss_apply_delimit()
- * @see fll_fss_basic_list_read()
- */
-#ifndef _di_controller_entry_read_
- extern f_status_t controller_entry_read(const controller_global_t global, const bool is_entry, controller_cache_t * const cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_read_
-
-/**
- * Read the entry settings, loading all settings.
- *
- * @param global
- * The global data.
- * @param is_entry
- * If TRUE, then this loads as an entry.
- * If FALSE, then this loads as an exit.
- * @param content_range
- * The range in the list buffer representing the content.
- * @param cache
- * A structure for containing and caching relevant data.
- *
- * Errors (with error bit) from: controller_entry_print_error_file().
- *
- * @see controller_entry_print_error_file()
- */
-#ifndef _di_controller_entry_settings_read_
- extern f_status_t controller_entry_settings_read(const controller_global_t global, const bool is_entry, const f_range_t content_range, controller_cache_t * const cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_settings_read_
-
-/**
- * Load the given ranges within the buffer into the provided map.
- *
- * @param buffer
- * The buffer the ranges are associated with.
- * @param ranges
- * The ranges to load from the buffer.
- * This expects the caller to already ensure the ranges.used = 2.
- * @param setting_maps
- * The map to load the settings into.
- *
- * @return
- * Errors (with error bit) from: f_memory_aray_increase().
- * Errors (with error bit) from: f_string_dynamic_partial_append_nulless().
- *
- * @see f_memory_aray_increase()
- * @see f_string_dynamic_partial_append_nulless()
- */
-#ifndef _di_controller_entry_settings_read_map_
- f_status_t controller_entry_settings_read_map(const f_string_static_t buffer, const f_ranges_t ranges, f_string_maps_t *setting_maps) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_settings_read_map_
-
-/**
- * Perform a simulated execution of the given entry.
- *
- * This simply prints information about the entry.
- *
- * @param global
- * The global data.
- * @param is_entry
- * If TRUE, then this is an entry.
- * If FALSE, then this is an exit.
- * @param cache
- * A structure for containing and caching relevant data.
- */
-#ifndef _di_controller_entry_setting_validate_
- extern void controller_entry_setting_validate(const controller_global_t global, const bool is_entry, controller_cache_t * const cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_setting_validate_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_entry_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "../entry/private-entry_print.h"
-#include "../lock/private-lock_print.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_entry_print_string_s_
- const f_string_static_t controller_entry_print_considering_s = macro_f_string_static_t_initialize_1(CONTROLLER_entry_print_considering_s, 0, CONTROLLER_entry_print_considering_s_length);
- const f_string_static_t controller_entry_print_failsafe_s = macro_f_string_static_t_initialize_1(CONTROLLER_entry_print_failsafe_s, 0, CONTROLLER_entry_print_failsafe_s_length);
- const f_string_static_t controller_entry_print_processing_s = macro_f_string_static_t_initialize_1(CONTROLLER_entry_print_processing_s, 0, CONTROLLER_entry_print_processing_s_length);
- const f_string_static_t controller_entry_print_suffix_megatime_s = macro_f_string_static_t_initialize_1(CONTROLLER_entry_print_suffix_megatime_s, 0, CONTROLLER_entry_print_suffix_megatime_s_length);
-#endif // _di_controller_entry_print_string_s_
-
-#ifndef _di_controller_entry_action_parameters_print_
- void controller_entry_action_parameters_print(fl_print_t * const print, const controller_entry_action_t action) {
-
- for (f_number_unsigned_t index = 0; ;) {
-
- f_print_dynamic_safely(action.parameters.array[index], print->to);
-
- ++index;
-
- if (index == action.parameters.used) break;
-
- f_print_dynamic_raw(f_string_space_s, print->to);
- } // for
- }
-#endif // _di_controller_entry_action_parameters_print_
-
-#ifndef _di_controller_entry_preprocess_print_simulate_setting_value_
- void controller_entry_preprocess_print_simulate_setting_value(const controller_global_t global, const bool is_entry, const f_string_static_t name, const f_string_static_t name_sub, const f_string_static_t value, const f_string_static_t suffix) {
-
- if (global.main->program.error.verbosity != f_console_verbosity_debug_e && !(global.main->program.error.verbosity == f_console_verbosity_verbose_e && global.main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e)) {
- return;
- }
-
- controller_lock_print(global.main->program.output.to, global.thread);
-
- fl_print_format("%rProcessing %r item action '", global.main->program.output.to, f_string_eol_s, is_entry ? controller_entry_s : controller_exit_s);
-
- fl_print_format("%[%Q%]' setting ", global.main->program.output.to, global.main->program.context.set.title, name, global.main->program.context.set.title);
-
- if (name_sub.used) {
- fl_print_format("'%[%Q%]'", global.main->program.output.to, global.main->program.context.set.notable, name_sub, global.main->program.context.set.notable);
- }
- else {
- fl_print_format("value", global.main->program.output.to);
- }
-
- fl_print_format(" to '%[%Q%]", global.main->program.output.to, global.main->program.context.set.important, value, global.main->program.context.set.important);
-
- fl_print_format("'%Q.%r", global.main->program.output.to, suffix, f_string_eol_s);
-
- controller_unlock_print_flush(global.main->program.output.to, global.thread);
- }
-#endif // _di_controller_entry_preprocess_print_simulate_setting_value_
-
-#ifndef _di_controller_entry_print_error_
- void controller_entry_print_error(const bool is_entry, fl_print_t * const print, const controller_cache_action_t cache, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) {
-
- if (print->verbosity == f_console_verbosity_quiet_e) return;
- if (status == F_interrupt) return;
-
- // fll_error_print() automatically locks, so manually handle only the mutex locking and flushing rather than calling controller_lock_print().
- f_thread_mutex_lock(&thread->lock.print);
-
- fll_error_print(print, status, function, fallback);
-
- f_file_stream_lock(print->to);
-
- controller_entry_print_error_cache(is_entry, print, cache);
-
- controller_unlock_print_flush(print->to, thread);
- }
-#endif // _di_controller_entry_print_error_
-
-#ifndef _di_controller_entry_print_error_cache_
- void controller_entry_print_error_cache(const bool is_entry, fl_print_t * const print, const controller_cache_action_t cache) {
-
- fl_print_format("%r%[%QWhile processing ", print->to, f_string_eol_s, print->context, print->prefix);
-
- if (cache.name_action.used) {
- fl_print_format("action '%]", print->to, print->context);
- fl_print_format(f_string_format_Q_single_s.string, print->to, print->notable, cache.name_action, print->notable);
- fl_print_format("%[' on line%] ", print->to, print->context, print->context);
- fl_print_format("%[%un%]", print->to, print->notable, cache.line_action, print->notable);
- fl_print_format("%[ for ", print->to, print->context);
- }
-
- if (cache.name_item.used) {
- fl_print_format("%r item '%]", print->to, is_entry ? controller_entry_s : controller_exit_s, print->context);
- fl_print_format(f_string_format_Q_single_s.string, print->to, print->notable, cache.name_item, print->notable);
- fl_print_format("%[' on line%] ", print->to, print->context, print->context);
- fl_print_format("%[%un%]", print->to, print->notable, cache.line_item, print->notable);
- fl_print_format("%[ for ", print->to, print->context);
- }
-
- if (cache.name_file.used) {
- fl_print_format("%r file '%]", print->to, is_entry ? controller_entry_s : controller_exit_s, print->context);
- fl_print_format("%[%Q%]%['", print->to, print->notable, cache.name_file, print->notable, print->context);
- }
-
- fl_print_format(".%]%r", print->to, print->context, f_string_eol_s);
- }
-#endif // _di_controller_entry_print_error_cache_
-
-#ifndef _di_controller_entry_print_error_file_
- void controller_entry_print_error_file(const bool is_entry, fl_print_t * const print, const controller_cache_action_t cache, const f_status_t status, const f_string_t function, const uint8_t flag, const f_string_static_t name, const f_string_static_t operation, const uint8_t type, controller_thread_t *thread) {
-
- if (print->verbosity == f_console_verbosity_quiet_e) return;
- if (status == F_interrupt) return;
-
- // fll_error_file_print() automatically locks, so manually handle only the mutex locking and flushing rather than calling controller_lock_print().
- f_thread_mutex_lock(&thread->lock.print);
-
- fll_error_file_print(print, status, function, flag, name, operation, type);
-
- f_file_stream_lock(print->to);
-
- controller_entry_print_error_cache(is_entry, print, cache);
-
- controller_unlock_print_flush(print->to, thread);
- }
-#endif // _di_controller_entry_print_error_file_
-
-#ifndef _di_controller_entry_setting_read_print_error_with_range_
- void controller_entry_setting_read_print_error_with_range(const bool is_entry, fl_print_t * const print, const f_string_t before, const f_range_t range, const f_string_t after, controller_thread_t * const thread, controller_cache_t * const cache) {
-
- if (print->verbosity == f_console_verbosity_quiet_e) return;
-
- controller_lock_print(print->to, thread);
-
- fl_print_format("%r%[%Q%r setting%S '%]", print->to, f_string_eol_s, print->context, print->prefix, is_entry ? controller_Entry_s : controller_Exit_s, before, print->context);
- fl_print_format(f_string_format_Q_range_single_s.string, print->to, print->notable, cache->buffer_file, range, print->notable);
- fl_print_format("%['%S.%]%r", print->to, print->context, after, print->context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, print, cache->action);
-
- controller_unlock_print_flush(print->to, thread);
- }
-#endif // _di_controller_entry_setting_read_print_error_with_range_
-
-#ifndef _di_controller_entry_settings_read_print_setting_ignored_
- void controller_entry_settings_read_print_setting_ignored(const controller_global_t global, const bool is_entry, const controller_cache_t cache, const f_number_unsigned_t index) {
-
- if (global.main->program.warning.verbosity != f_console_verbosity_debug_e) return;
-
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- fl_print_format("%r%[%QThe %Q item setting '%]", global.main->program.warning.to, f_string_eol_s, global.main->program.warning.context, global.main->program.warning.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.warning.to, global.main->program.warning.notable, cache.action.name_action, global.main->program.warning.notable);
- fl_print_format("%[' is being ignored.%]%r", global.main->program.warning.to, global.main->program.warning.context, global.main->program.warning.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.warning, cache.action);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
-#endif // _di_controller_entry_settings_read_print_setting_ignored_
-
-#ifndef _di_controller_entry_settings_read_print_setting_requires_between_
- void controller_entry_settings_read_print_setting_requires_between(const controller_global_t global, const bool is_entry, const controller_cache_t cache, const f_number_unsigned_t minimum, const f_number_unsigned_t maximum) {
-
- if (global.main->program.error.verbosity == f_console_verbosity_quiet_e) return;
-
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QThe %Q item setting '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache.action.name_action, global.main->program.error.notable);
- fl_print_format("%[' requires at least %]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%un%]", global.main->program.error.to, global.main->program.error.notable, minimum, global.main->program.error.notable);
- fl_print_format("%[ and at most %]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%un%]", global.main->program.error.to, global.main->program.error.notable, maximum, global.main->program.error.notable);
- fl_print_format("%[ Content.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.error, cache.action);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-#endif // _di_controller_entry_settings_read_print_setting_requires_between_
-
-#ifndef _di_controller_entry_settings_read_print_setting_requires_exactly_
- void controller_entry_settings_read_print_setting_requires_exactly(const controller_global_t global, const bool is_entry, const controller_cache_t cache, const f_number_unsigned_t total) {
-
- if (global.main->program.error.verbosity == f_console_verbosity_quiet_e) return;
-
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QThe %Q item setting '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache.action.name_action, global.main->program.error.notable);
- fl_print_format("%[' requires exactly %]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%un%]", global.main->program.error.to, global.main->program.error.notable, total, global.main->program.error.notable);
- fl_print_format("%[ Content.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.error, cache.action);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-#endif // _di_controller_entry_settings_read_print_setting_requires_exactly_
-
-#ifndef _di_controller_entry_settings_read_print_setting_unknown_action_
- void controller_entry_settings_read_print_setting_unknown_action(const controller_global_t global, const bool is_entry, const controller_cache_t cache) {
-
- if (global.main->program.warning.verbosity != f_console_verbosity_debug_e) return;
-
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- fl_print_format("%r%[%QUnknown %r item setting '%]", global.main->program.warning.to, f_string_eol_s, global.main->program.warning.context, global.main->program.warning.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.warning.to, global.main->program.warning.notable, cache.action.name_action, global.main->program.warning.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.warning.to, global.main->program.warning.context, global.main->program.warning.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.warning, cache.action);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
-#endif // _di_controller_entry_settings_read_print_setting_unknown_action_
-
-#ifndef _di_controller_entry_settings_read_print_setting_unknown_action_value_
- void controller_entry_settings_read_print_setting_unknown_action_value(const controller_global_t global, const bool is_entry, const controller_cache_t cache, const f_number_unsigned_t index) {
-
- if (global.main->program.warning.verbosity != f_console_verbosity_debug_e) return;
-
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- fl_print_format("%r%[%QThe %Q item setting '%]", global.main->program.warning.to, f_string_eol_s, global.main->program.warning.context, global.main->program.warning.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.warning.to, global.main->program.warning.notable, cache.action.name_action, global.main->program.warning.notable);
- fl_print_format("%[' has an unknown value '%]", global.main->program.warning.to, global.main->program.warning.context, global.main->program.warning.context);
- fl_print_format(f_string_format_Q_range_single_s.string, global.main->program.warning.to, global.main->program.warning.notable, cache.buffer_file, cache.content_actions.array[index].array[0], global.main->program.warning.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.warning.to, global.main->program.warning.context, global.main->program.warning.context, f_string_eol_s);
-
- controller_entry_print_error_cache(is_entry, &global.main->program.warning, cache.action);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
-#endif // _di_controller_entry_settings_read_print_setting_unknown_action_value_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_entry_print_h
-#define _PRIVATE_entry_print_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Special strings used for printing.
- */
-#ifndef _di_controller_entry_print_string_s_
- #define CONTROLLER_entry_print_considering_s "Considering"
- #define CONTROLLER_entry_print_failsafe_s "failsafe"
- #define CONTROLLER_entry_print_processing_s "Processing"
- #define CONTROLLER_entry_print_suffix_megatime_s " MegaTime (milliseconds)"
-
- #define CONTROLLER_entry_print_considering_s_length 11
- #define CONTROLLER_entry_print_failsafe_s_length 8
- #define CONTROLLER_entry_print_processing_s_length 10
- #define CONTROLLER_entry_print_suffix_megatime_s_length 24
-
- extern const f_string_static_t controller_entry_print_considering_s;
- extern const f_string_static_t controller_entry_print_failsafe_s;
- extern const f_string_static_t controller_entry_print_processing_s;
- extern const f_string_static_t controller_entry_print_suffix_megatime_s;
-#endif // _di_controller_entry_print_string_s_
-
-/**
- * Print all parameters for some action, separated by a space.
- *
- * @param print
- * The print to use.
- * @param action
- * The entry action whose parameters will be printed.
- */
-#ifndef _di_controller_entry_action_parameters_print_
- extern void controller_entry_action_parameters_print(fl_print_t * const print, const controller_entry_action_t action) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_action_parameters_print_
-
-/**
- * Print message regarding the population of a setting when in simulation or verbose mode.
- *
- * @param global
- * The global data.
- * @param is_entry
- * If TRUE, then this operate as an entry.
- * If FALSE, then this operate as an exit.
- * @param name
- * The Object name of the setting being populated.
- * @param name_sub
- * A sub-name associated with the setting being populated.
- * Set to a string with used set to 0 to not use.
- * @param value
- * The value being set.
- * @param suffix
- * An additional message to append at the end (before the final period).
- */
-#ifndef _di_controller_entry_preprocess_print_simulate_setting_value_
- extern void controller_entry_preprocess_print_simulate_setting_value(const controller_global_t global, const bool is_entry, const f_string_static_t name, const f_string_static_t name_sub, const f_string_static_t value, const f_string_static_t suffix) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_preprocess_print_simulate_setting_value_
-
-/**
- * Print the entry related error, locking the print mutex during the print.
- *
- * @param is_entry
- * If TRUE, then this loads as an entry.
- * If FALSE, then this loads as an exit.
- * @param print
- * Designates how printing is to be performed.
- * @param cache
- * The action cache.
- * @param status
- * The status code to process.
- * Make sure this has F_status_set_fine() called if the status code has any error or warning bits.
- * @param function
- * (optional) The name of the function where the error happened.
- *
- * Set to NULL to disable.
- * @param fallback
- * Set to F_true to print the fallback error message for unknown errors.
- * @param thread
- * The thread data.
- *
- * @see fll_error_print()
- * @see controller_entry_print_error_cache()
- */
-#ifndef _di_controller_entry_print_error_
- extern void controller_entry_print_error(const bool is_entry, fl_print_t * const print, const controller_cache_action_t cache, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_print_error_
-
-/**
- * Print additional error/warning information in addition to existing error that is found within the cache.
- *
- * This is explicitly intended to be used in addition to the error message.
- *
- * This neither locks the thread nor does it check to see if output is enabled or disabled.
- *
- * @param is_entry
- * If TRUE, then this loads as an entry.
- * If FALSE, then this loads as an exit.
- * @param print
- * Designates how printing is to be performed.
- * @param cache
- * The action cache.
- *
- * @see controller_entry_actions_read()
- * @see controller_entry_read()
- */
-#ifndef _di_controller_entry_print_error_cache_
- extern void controller_entry_print_error_cache(const bool is_entry, fl_print_t * const print, const controller_cache_action_t cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_print_error_cache_
-
-/**
- * Print the entry related file error, locking the print mutex during the print.
- *
- * @param is_entry
- * If TRUE, then this loads as an entry.
- * If FALSE, then this loads as an exit.
- * @param print
- * Designates how printing is to be performed.
- * @param cache
- * The action cache.
- * @param status
- * The status code to process.
- * Make sure this has F_status_set_fine() called if the status code has any error or warning bits.
- * @param function
- * (optional) The name of the function where the error happened.
- *
- * Set to NULL to disable.
- * @param flag
- * One of the fll_error_file_flag_*_e flags.
- * @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.
- * @param thread
- * The thread data.
- *
- * @see fll_error_file_print()
- * @see controller_entry_print_error_cache()
- */
-#ifndef _di_controller_entry_print_error_file_
- extern void controller_entry_print_error_file(const bool is_entry, fl_print_t * const print, const controller_cache_action_t cache, const f_status_t status, const f_string_t function, const uint8_t flag, const f_string_static_t name, const f_string_static_t operation, const uint8_t type, controller_thread_t *thread) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_print_error_file_
-
-/**
- * Print a message about an entry setting problem, with additional messages about the value.
- *
- * This is intended to be explicitly called by controller_entry_settings_read().
- * This is intended only to be used for simple messages.
- *
- * @param is_entry
- * If TRUE, then this loads as an entry.
- * If FALSE, then this loads as an exit.
- * @param print
- * The error or warning output structure.
- * @param before
- * The string to add to the message being printed (before the value).
- * @param range
- * The range within the cache item buffer representing the value.
- * @param after
- * The string to add to the message being printed (after the value).
- * @param thread
- * The thread data.
- * @param cache
- * A structure for containing and caching relevant data.
- *
- * @see controller_entry_settings_read()
- */
-#ifndef _di_controller_entry_setting_read_print_error_with_range_
- extern void controller_entry_setting_read_print_error_with_range(const bool is_entry, fl_print_t * const print, const f_string_t before, const f_range_t range, const f_string_t after, controller_thread_t * const thread, controller_cache_t * const cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_setting_read_print_error_with_range_
-
-/**
- * Print a message for when an entry setting is being ignored.
- *
- * @param global
- * The global data.
- * @param is_entry
- * If TRUE, then this loads as an entry.
- * If FALSE, then this loads as an exit.
- * @param cache
- * A structure for containing and caching relevant data.
- * @param total
- * The expected number of arguments.
- */
-#ifndef _di_controller_entry_settings_read_print_setting_ignored_
- extern void controller_entry_settings_read_print_setting_ignored(const controller_global_t global, const bool is_entry, const controller_cache_t cache, const f_number_unsigned_t index) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_settings_read_print_setting_ignored_
-
-/**
- * Print a message for when an entry setting action has the incorrect number of parameters when the required amount is between a range.
- *
- * @param global
- * The global data.
- * @param is_entry
- * If TRUE, then this loads as an entry.
- * If FALSE, then this loads as an exit.
- * @param cache
- * A structure for containing and caching relevant data.
- * @param minimum
- * The expected minimum number of arguments.
- * @param maximum
- * The expected maximum number of arguments.
- */
-#ifndef _di_controller_entry_settings_read_print_setting_requires_between_
- extern void controller_entry_settings_read_print_setting_requires_between(const controller_global_t global, const bool is_entry, const controller_cache_t cache, const f_number_unsigned_t minimum, const f_number_unsigned_t maximum) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_settings_read_print_setting_requires_between_
-
-/**
- * Print a message for when an entry setting action has the incorrect number of parameters when the required amount is fixed.
- *
- * @param global
- * The global data.
- * @param is_entry
- * If TRUE, then this loads as an entry.
- * If FALSE, then this loads as an exit.
- * @param cache
- * A structure for containing and caching relevant data.
- * @param total
- * The expected number of arguments.
- */
-#ifndef _di_controller_entry_settings_read_print_setting_requires_exactly_
- extern void controller_entry_settings_read_print_setting_requires_exactly(const controller_global_t global, const bool is_entry, const controller_cache_t cache, const f_number_unsigned_t total) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_settings_read_print_setting_requires_exactly_
-
-/**
- * Print a message for when an entry setting action is unknown.
- *
- * @param global
- * The global data.
- * @param is_entry
- * If TRUE, then this loads as an entry.
- * If FALSE, then this loads as an exit.
- * @param cache
- * A structure for containing and caching relevant data.
- */
-#ifndef _di_controller_entry_settings_read_print_setting_unknown_action_
- extern void controller_entry_settings_read_print_setting_unknown_action(const controller_global_t global, const bool is_entry, const controller_cache_t cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_settings_read_print_setting_unknown_action_
-
-/**
- * Print a message for when an entry setting action has an unknown value.
- *
- * @param global
- * The global data.
- * @param is_entry
- * If TRUE, then this loads as an entry.
- * If FALSE, then this loads as an exit.
- * @param cache
- * A structure for containing and caching relevant data.
- * @param total
- * The expected number of arguments.
- * @param index
- * The location in the content actions array representing the action value.
- */
-#ifndef _di_controller_entry_settings_read_print_setting_unknown_action_value_
- extern void controller_entry_settings_read_print_setting_unknown_action_value(const controller_global_t global, const bool is_entry, const controller_cache_t cache, const f_number_unsigned_t index) F_attribute_visibility_internal_d;
-#endif // _di_controller_entry_settings_read_print_setting_unknown_action_value_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_entry_print_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "../controller/private-controller.h"
-#include "../lock/private-lock.h"
-#include "../thread/private-thread.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_lock_create_
- f_status_t controller_lock_create(controller_lock_t *lock) {
-
- f_status_t status = f_thread_mutex_create(0, &lock->alert);
- if (F_status_is_error(status)) return status;
-
- status = f_thread_mutex_create(0, &lock->cancel);
- if (F_status_is_error(status)) return status;
-
- status = f_thread_mutex_create(0, &lock->print);
- if (F_status_is_error(status)) return status;
-
- status = f_thread_lock_create(0, &lock->process);
- if (F_status_is_error(status)) return status;
-
- status = f_thread_lock_create(0, &lock->rule);
- if (F_status_is_error(status)) return status;
-
- status = f_thread_mutex_create(0, &lock->alert);
- if (F_status_is_error(status)) return status;
-
- status = f_thread_condition_create(0, &lock->alert_condition);
- if (F_status_is_error(status)) return status;
-
- return F_okay;
- }
-#endif // _di_controller_lock_create_
-
-#ifndef _di_controller_lock_read_
- f_status_t controller_lock_read(const bool is_normal, controller_thread_t * const thread, f_thread_lock_t *lock) {
-
- f_time_spec_t time;
-
- f_status_t status = F_okay;
-
- for (;;) {
-
- controller_time(controller_thread_lock_read_timeout_seconds_d, controller_thread_lock_read_timeout_nanoseconds_d, &time);
-
- status = f_thread_lock_read_timed(&time, lock);
-
- if (status == F_time) {
- if (!controller_thread_is_enabled(is_normal, thread)) {
- return F_status_set_error(F_interrupt);
- }
- }
- else {
- break;
- }
- } // for
-
- return status;
- }
-#endif // _di_controller_lock_read_
-
-#ifndef _di_controller_lock_read_process_
- f_status_t controller_lock_read_process(controller_data_t * const process, controller_thread_t * const thread, f_thread_lock_t *lock) {
-
- return controller_lock_read_process_type(process->type, thread, lock);
- }
-#endif // _di_controller_lock_read_process_
-
-#ifndef _di_controller_lock_read_process_type_
- f_status_t controller_lock_read_process_type(const uint8_t type, controller_thread_t * const thread, f_thread_lock_t *lock) {
-
- return controller_lock_read(type != controller_data_type_exit_e, thread, lock);
- }
-#endif // _di_controller_lock_read_process_type_
-
-#ifndef _di_controller_lock_write_
- f_status_t controller_lock_write(const bool is_normal, controller_thread_t * const thread, f_thread_lock_t *lock) {
-
- f_time_spec_t time;
-
- f_status_t status = F_okay;
-
- for (;;) {
-
- controller_time(controller_thread_lock_write_timeout_seconds_d, controller_thread_lock_write_timeout_nanoseconds_d, &time);
-
- status = f_thread_lock_write_timed(&time, lock);
-
- if (status == F_time) {
- if (!controller_thread_is_enabled(is_normal, thread)) {
- return F_status_set_error(F_interrupt);
- }
- }
- else {
- break;
- }
- } // for
-
- return status;
- }
-#endif // _di_controller_lock_write_
-
-#ifndef _di_controller_lock_write_process_
- f_status_t controller_lock_write_process(controller_data_t * const process, controller_thread_t * const thread, f_thread_lock_t *lock) {
-
- return controller_lock_write_process_type(process->type, thread, lock);
- }
-#endif // _di_controller_lock_write_process_
-
-#ifndef _di_controller_lock_write_process_type_
- f_status_t controller_lock_write_process_type(const uint8_t type, controller_thread_t * const thread, f_thread_lock_t *lock) {
-
- return controller_lock_write(type != controller_data_type_exit_e, thread, lock);
- }
-#endif // _di_controller_lock_write_process_type_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_lock_h
-#define _PRIVATE_lock_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Perform the initial, required, allocation for the lock.
- *
- * @param lock
- * The lock to allocate.
- *
- * @return
- * F_okay on success.
- *
- * Errors (with error bit) from: f_thread_lock_delete().
- * Errors (with error bit) from: f_thread_mutex_delete().
- *
- * @see f_thread_lock_delete()
- * @see f_thread_mutex_delete()
- */
-#ifndef _di_controller_lock_create_
- extern f_status_t controller_lock_create(controller_lock_t *lock) F_attribute_visibility_internal_d;
-#endif // _di_controller_lock_create_
-
-/**
- * Wait to get a read lock.
- *
- * Given a r/w lock, periodically check to see if main thread is disabled while waiting.
- *
- * @param is_normal
- * If TRUE, then process as if this operates during a normal operation (entry and control).
- * If FALSE, then process as if this operates during a an exit operation.
- * @param thread
- * The thread data used to determine if the main thread is disabled or not.
- * @param lock
- * The r/w lock to obtain a read lock on.
- *
- * @return
- * F_okay on success.
- *
- * F_interrupt (with error bit set) on (exit) signal received, lock will not be set when this is returned.
- *
- * Status from: f_thread_lock_read_timed().
- *
- * Errors (with error bit) from: f_thread_lock_read_timed().
- *
- * @see f_thread_lock_read_timed()
- */
-#ifndef _di_controller_lock_read_
- extern f_status_t controller_lock_read(const bool is_normal, controller_thread_t * const thread, f_thread_lock_t *lock) F_attribute_visibility_internal_d;
-#endif // _di_controller_lock_read_
-
-/**
- * Wait to get a read lock for some process.
- *
- * Given a r/w lock, periodically check to see if main thread is disabled while waiting.
- *
- * @param process
- * The process to use when checking if thread is enabled.
- * @param thread
- * The thread data used to determine if the main thread is disabled or not.
- * @param lock
- * The r/w lock to obtain a read lock on.
- *
- * @return
- *
- * Status from: controller_lock_read().
- *
- * Errors (with error bit) from: controller_lock_read().
- *
- * @see controller_lock_read()
- */
-#ifndef _di_controller_lock_read_process_
- extern f_status_t controller_lock_read_process(controller_data_t * const process, controller_thread_t * const thread, f_thread_lock_t *lock) F_attribute_visibility_internal_d;
-#endif // _di_controller_lock_read_process_
-
-/**
- * Wait to get a read lock for some process type.
- *
- * Given a r/w lock, periodically check to see if main thread is disabled while waiting.
- *
- * @param type
- * The process type to use when checking if thread is enabled.
- * @param thread
- * The thread data used to determine if the main thread is disabled or not.
- * @param lock
- * The r/w lock to obtain a read lock on.
- *
- * @return
- *
- * Status from: controller_lock_read().
- *
- * Errors (with error bit) from: controller_lock_read().
- *
- * @see controller_lock_read()
- */
-#ifndef _di_controller_lock_read_process_type_
- extern f_status_t controller_lock_read_process_type(const uint8_t type, controller_thread_t * const thread, f_thread_lock_t *lock) F_attribute_visibility_internal_d;
-#endif // _di_controller_lock_read_process_type_
-
-/**
- * Wait to get a write lock.
- *
- * Given a r/w lock, periodically check to see if main thread is disabled while waiting.
- *
- * @param is_normal
- * If TRUE, then process as if this operates during a normal operation (entry and control).
- * If FALSE, then process as if this operates during a an exit operation.
- * @param thread
- * The thread data used to determine if the main thread is disabled or not.
- * @param lock
- * The r/w lock to obtain a write lock on.
- *
- * @return
- * F_okay on success.
- *
- * F_interrupt (with error bit set) on (exit) signal received, lock will not be set when this is returned.
- *
- * Status from: f_thread_lock_write_timed().
- *
- * Errors (with error bit) from: f_thread_lock_write_timed().
- *
- * @see f_thread_lock_write_timed()
- */
-#ifndef _di_controller_lock_write_
- extern f_status_t controller_lock_write(const bool is_normal, controller_thread_t * const thread, f_thread_lock_t *lock) F_attribute_visibility_internal_d;
-#endif // _di_controller_lock_write_
-
-/**
- * Wait to get a write lock for some process.
- *
- * Given a r/w lock, periodically check to see if main thread is disabled while waiting.
- *
- * @param process
- * The process to use when checking if thread is enabled.
- * @param thread
- * The thread data used to determine if the main thread is disabled or not.
- * @param lock
- * The r/w lock to obtain a write lock on.
- *
- * @return
- *
- * Status from: controller_lock_write_process_type().
- *
- * Errors (with error bit) from: controller_lock_write_process_type().
- *
- * @see controller_lock_write_process_type()
- */
-#ifndef _di_controller_lock_write_process_
- extern f_status_t controller_lock_write_process(controller_data_t * const process, controller_thread_t * const thread, f_thread_lock_t *lock) F_attribute_visibility_internal_d;
-#endif // _di_controller_lock_write_process_
-
-/**
- * Wait to get a write lock for some process type.
- *
- * Given a r/w lock, periodically check to see if main thread is disabled while waiting.
- *
- * @param type
- * The process type to use when checking if thread is enabled.
- * @param thread
- * The thread data used to determine if the main thread is disabled or not.
- * @param lock
- * The r/w lock to obtain a write lock on.
- *
- * @return
- *
- * Status from: controller_lock_write().
- *
- * Errors (with error bit) from: controller_lock_write().
- *
- * @see controller_lock_write()
- */
-#ifndef _di_controller_lock_write_process_type_
- extern f_status_t controller_lock_write_process_type(const uint8_t type, controller_thread_t * const thread, f_thread_lock_t *lock) F_attribute_visibility_internal_d;
-#endif // _di_controller_lock_write_process_type_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_lock_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "../lock/private-lock_print.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_lock_print_error_critical_
- void controller_lock_print_error_critical(fl_print_t * const print, const f_status_t status, const bool read, controller_thread_t *thread) {
-
- // A signal is not an error.
- if (status == F_interrupt) return;
-
- if (print->verbosity != f_console_verbosity_quiet_e) {
- controller_lock_print(print->to, thread);
-
- fl_print_format("%r%[%QThe pid file '%]", print->to, f_string_eol_s, print->context, print->prefix, print->context);
- fl_print_format("%['Critical failure while attempting to establish '%]", print->to, print->context, print->context);
- fl_print_format("%[%r lock%]", print->to, print->notable, read ? f_file_operation_read_s : f_file_operation_write_s, print->notable);
-
- if (status != F_failure) {
- fl_print_format(" %['due to%] ", print->to, print->context, print->context);
-
- if (status == F_parameter) {
- fl_print_format("%[Invalid Parameter%]", print->to, print->notable, print->notable);
- }
- else if (status == F_deadlock) {
- fl_print_format("%[Deadlock%]", print->to, print->notable, print->notable);
- }
- else if (status == F_resource_not) {
- fl_print_format("%[Too Many Locks%]", print->to, print->notable, print->notable);
- }
- else {
- fl_print_format("%[Unknown Error%]", print->to, print->notable, print->notable);
- }
- }
-
- fl_print_format(f_string_format_sentence_end_quote_s.string, print->to, print->context, print->context, f_string_eol_s);
-
- controller_unlock_print_flush(print->to, thread);
- }
- }
-#endif // _di_controller_lock_print_error_critical_
-
-#ifndef _di_controller_lock_print_
- void controller_lock_print(const f_file_t to, controller_thread_t * const thread) {
-
- if (thread) {
- f_thread_mutex_lock(&thread->lock.print);
- }
-
- f_file_stream_lock(to);
- }
-#endif // _di_controller_lock_print_
-
-#ifndef _di_controller_unlock_print_flush_
- void controller_unlock_print_flush(const f_file_t to, controller_thread_t * const thread) {
-
- f_file_stream_flush(to);
- f_file_stream_unlock(to);
-
- if (thread) {
- f_thread_mutex_unlock(&thread->lock.print);
- }
- }
-#endif // _di_controller_unlock_print_flush_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_lock_print_h
-#define _PRIVATE_lock_print_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Print a r/w lock related error message, locking the print mutex during the print.
- *
- * This will ignore F_interrupt and not print any messages, if passed.
- *
- * @param print
- * Designates how printing is to be performed.
- * @param status
- * The status code to process.
- * Make sure this has F_status_set_fine() called if the status code has any error or warning bits.
- * @param read
- * If TRUE, then this is for a read lock.
- * If FALSE, then this is for a write lock.
- * @param thread
- * The thread data.
- */
-#ifndef _di_controller_lock_print_error_critical_
- extern void controller_lock_print_error_critical(fl_print_t * const print, const f_status_t status, const bool read, controller_thread_t *thread) F_attribute_visibility_internal_d;
-#endif // _di_controller_lock_print_error_critical_
-
-/**
- * Lock the mutex and the stream.
- *
- * This is implemented as a compliment to controller_unlock_print_flush() for consistency reasons.
- *
- * @param to
- * The file stream to lock.
- * @param thread
- * The thread containing the print mutex to lock.
- *
- * @see f_file_stream_lock()
- * @see f_thread_mutex_unlock()
- */
-#ifndef _di_controller_lock_print_
- extern void controller_lock_print(const f_file_t to, controller_thread_t * const thread) F_attribute_visibility_internal_d;
-#endif // _di_controller_lock_print_
-
-/**
- * Flush the stream buffer and then unlock the mutex.
- *
- * This unlocks both the stream and the mutex locks.
- *
- * Weird behavior was observed when piping data from this program.
- * The behavior appears related to how this handles locks in addition to the file streams own locking mechanisms.
- *
- * As a work-around, this performs a flush immediately before unlocking the print mutex.
- *
- * @param to
- * The file stream to unlock and flush.
- * @param thread
- * The thread containing the print mutex to unlock.
- *
- * @see f_file_stream_unlock()
- *
- * @see f_thread_mutex_unlock()
- */
-#ifndef _di_controller_unlock_print_flush_
- void controller_unlock_print_flush(const f_file_t to, controller_thread_t * const thread) F_attribute_visibility_internal_d;
-#endif // _di_controller_unlock_print_flush_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_lock_print_h
+++ /dev/null
-#include "controller.h"
-#include "main-common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_program_name_
- const f_string_static_t controller_program_name_s = macro_f_string_static_t_initialize_1(CONTROLLER_program_name_s, 0, CONTROLLER_program_name_s_length);
- const f_string_static_t controller_program_name_long_s = macro_f_string_static_t_initialize_1(CONTROLLER_program_name_long_s, 0, CONTROLLER_program_name_long_s_length);
-#endif // _di_controller_program_name_
-
-#ifndef _di_controller_defines_
- const f_string_static_t controller_default_engine_s = macro_f_string_static_t_initialize_1(CONTROLLER_default_engine_s, 0, CONTROLLER_default_engine_s_length);
- const f_string_static_t controller_path_pid_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_pid_s, 0, CONTROLLER_path_pid_s_length);
- const f_string_static_t controller_path_pid_init_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_pid_init_s, 0, CONTROLLER_path_pid_init_s_length);
- const f_string_static_t controller_path_pid_prefix_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_pid_prefix_s, 0, CONTROLLER_path_pid_prefix_s_length);
- const f_string_static_t controller_path_pid_suffix_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_pid_suffix_s, 0, CONTROLLER_path_pid_suffix_s_length);
- const f_string_static_t controller_path_settings_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_settings_s, 0, CONTROLLER_path_settings_s_length);
- const f_string_static_t controller_path_settings_init_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_settings_init_s, 0, CONTROLLER_path_settings_init_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_init_s = macro_f_string_static_t_initialize_1(CONTROLLER_path_socket_init_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_defines_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- *
- * Provides the common data structures to be compiled into the main program rather than the library.
- *
- * This is auto-included and should not need to be explicitly included.
- */
-#ifndef _controller_main_common_h
-#define _controller_main_common_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * The program name.
- */
-#ifndef _di_controller_program_name_
- #ifdef _controller_as_init_
- #define CONTROLLER_program_name_s "init"
- #define CONTROLLER_program_name_long_s "Init Program"
-
- #define CONTROLLER_program_name_s_length 4
- #define CONTROLLER_program_name_long_s_length 12
- #else
- #define CONTROLLER_program_name_s "controller"
- #define CONTROLLER_program_name_long_s "Controller Program"
-
- #define CONTROLLER_program_name_s_length 10
- #define CONTROLLER_program_name_long_s_length 18
- #endif // _controller_as_init_
-
- extern const f_string_static_t controller_program_name_s;
- extern const f_string_static_t controller_program_name_long_s;
-#endif // _di_controller_program_name_
-
-/**
- * The program defines.
- */
-#ifndef _di_controller_defines_
-
- // The pid path is a system-specific path and needs to be more easily controlled at compile time.
- #if defined(_override_controller_path_pid_) && defined(_override_controller_path_pid_length_)
- #define CONTROLLER_path_pid_s _override_controller_path_pid_
- #define CONTROLLER_path_pid_s_length _override_controller_path_pid_length_
- #else
- #define CONTROLLER_path_pid_s "./run"
- #define CONTROLLER_path_pid_s_length 5
- #endif // defined(_override_controller_path_pid_) && defined(_override_controller_path_pid_length_)
-
- // The init pid path is a system-specific path and needs to be more easily controlled at compile time.
- #if defined(_override_controller_path_pid_init_) && defined(_override_controller_path_pid_init_length_)
- #define CONTROLLER_path_pid_init_s _override_controller_path_pid_init_
- #define CONTROLLER_path_pid_init_s_length _override_controller_path_pid_init_length_
- #elif defined(_controller_as_init_)
- #define CONTROLLER_path_pid_init_s "/var/run/init"
- #define CONTROLLER_path_pid_init_s_length 13
- #else
- #define CONTROLLER_path_pid_init_s "/var/run/controller"
- #define CONTROLLER_path_pid_init_s_length 19
- #endif // defined(_override_controller_path_pid_init_) && defined(_override_controller_path_pid_init_length_)
-
- // The pid prefix is a system-specific path part and needs to be more easily controlled at compile time.
- #if defined(_override_controller_path_pid_prefix_) && defined(_override_controller_path_pid_prefix_length_)
- #define CONTROLLER_path_pid_prefix_s _override_controller_path_pid_prefix_
-
- #define CONTROLLER_path_pid_prefix_s_length _override_controller_path_pid_prefix_length_
- #elif defined(_controller_as_init_)
- #define CONTROLLER_path_pid_prefix_s "init-"
- #define CONTROLLER_path_pid_prefix_s_length 5
- #else
- #define CONTROLLER_path_pid_prefix_s ""
- #define CONTROLLER_path_pid_prefix_s_length 0
- #endif // defined(_override_controller_name_pid_prefix_) && defined(_override_controller_name_pid_prefix_length_)
-
- // The socket suffix path is a system-specific path part and needs to be more easily controlled at compile time.
- #if defined(_override_controller_path_pid_suffix_) && defined(_override_controller_path_pid_suffix_length_)
- #define CONTROLLER_path_pid_suffix_s _override_controller_path_pid_suffix_
- #define CONTROLLER_path_pid_suffix_s_length _override_controller_path_pid_suffix_length_
- #else
- #define CONTROLLER_path_pid_suffix_s ".pid"
- #define CONTROLLER_path_pid_suffix_s_length 4
- #endif // defined(_override_controller_name_pid_suffix_) && defined(_override_controller_name_pid_suffix_length_)
-
- // The settings path is a system-specific path part and needs to be more easily controlled at compile time.
- #if defined(_override_controller_path_settings_) && defined(_override_controller_path_settings_length_)
- #define CONTROLLER_path_settings_s _override_controller_path_settings_
- #define CONTROLLER_path_settings_s_length _override_controller_path_settings_length_
- #else
- #define CONTROLLER_path_settings_s "./"
- #define CONTROLLER_path_settings_s_length 2
- #endif // defined(_override_controller_path_settings_) && defined(_override_controller_path_settings_length_)
-
- // The init settings path is a system-specific path part and needs to be more easily controlled at compile time.
- #if defined(_override_controller_path_settings_init_) && defined(_override_controller_path_settings_init_length_)
- #define CONTROLLER_path_settings_init_s _override_controller_path_settings_init_
- #define CONTROLLER_path_settings_init_s_length _override_controller_path_settings_init_length_
- #elif defined(_controller_as_init_)
- #define CONTROLLER_path_settings_init_s "/etc/init"
- #define CONTROLLER_path_settings_init_s_length 9
- #else
- #define CONTROLLER_path_settings_init_s "/etc/controller"
- #define CONTROLLER_path_settings_init_s_length 15
- #endif // defined(_override_controller_path_settings_init_) && defined(_override_controller_path_settings_init_length_)
-
- // The socket path is a system-specific path and needs to be more easily controlled at compile time.
- #if defined(_override_controller_path_socket_) && defined(_override_controller_path_socket_length_)
- #define CONTROLLER_path_socket_s _override_controller_path_socket_
- #define CONTROLLER_path_socket_s_length _override_controller_path_socket_length_
- #else
- #define CONTROLLER_path_socket_s "./run"
- #define CONTROLLER_path_socket_s_length 5
- #endif // defined(_override_controller_path_socket_) && defined(_override_controller_path_socket_length_)
-
- // The socket path is a system-specific path and needs to be more easily controlled at compile time.
- #if defined(_override_controller_path_socket_init_) && defined(_override_controller_path_socket_init_length_)
- #define CONTROLLER_path_socket_init_s _override_controller_path_socket_init_
- #define CONTROLLER_path_socket_init_s_length _override_controller_path_socket_init_length_
- #elif defined(_controller_as_init_)
- #define CONTROLLER_path_socket_init_s "/var/run/init"
- #define CONTROLLER_path_socket_init_s_length 13
- #else
- #define CONTROLLER_path_socket_init_s "/var/run/controller"
- #define CONTROLLER_path_socket_init_s_length 19
- #endif // defined(_override_controller_path_socket_init_) && defined(_override_controller_path_socket_init_length_)
-
- // The socket prefix path is a system-specific path part and needs to be more easily controlled at compile time.
- #if defined(_override_controller_path_socket_prefix_) && defined(_override_controller_path_socket_prefix_length_)
- #define CONTROLLER_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_path_socket_prefix_) && defined(_override_controller_path_socket_prefix_length_)
-
- // The socket suffix path is a system-specific path part and needs to be more easily controlled at compile time.
- #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_path_socket_suffix_) && defined(_override_controller_path_socket_suffix_length_)
-
- #if defined(_override_controller_default_program_script_) && defined(_override_controller_default_program_script_length_)
- #define CONTROLLER_default_engine_s _override_controller_default_engine_
- #define CONTROLLER_default_engine_s_length _override_controller_default_engine_length_
- #else
- #define CONTROLLER_default_engine_s "bash"
- #define CONTROLLER_default_engine_s_length 4
- #endif // defined(_override_controller_default_program_script_) && defined(_override_controller_default_program_script_length_)
-
- extern const f_string_static_t controller_default_engine_s;
- extern const f_string_static_t controller_path_pid_s;
- extern const f_string_static_t controller_path_pid_init_s;
- extern const f_string_static_t controller_path_pid_prefix_s;
- extern const f_string_static_t controller_path_pid_suffix_s;
- extern const f_string_static_t controller_path_settings_s;
- extern const f_string_static_t controller_path_settings_init_s;
- extern const f_string_static_t controller_path_socket_s;
- extern const f_string_static_t controller_path_socket_init_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_defines_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _controller_main_common_h
+++ /dev/null
-#include "controller.h"
-#include "main-common.h"
-
-int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
-
- controller_main_t data = controller_main_t_initialize;
-
- data.program.debug.flag |= controller_print_flag_debug_e | controller_print_flag_out_e;
- data.program.error.flag |= controller_print_flag_error_e | controller_print_flag_out_e;
- data.program.message.flag |= controller_print_flag_message_e | controller_print_flag_out_e;
- data.program.output.flag |= controller_print_flag_out_e;
- data.program.warning.flag |= controller_print_flag_warning_e | controller_print_flag_out_e;
-
- data.program.message.custom = (void *) &data;
- data.program.output.custom = (void *) &data;
- data.program.error.custom = (void *) &data;
- data.program.warning.custom = (void *) &data;
- data.program.debug.custom = (void *) &data;
-
- data.setting.state.data = (void *) &data;
-
- data.setting.default_engine = &controller_default_engine_s;
- data.setting.default_path_setting = &controller_path_settings_s;
- data.setting.default_path_setting_init = &controller_path_settings_init_s;
- data.setting.default_path_pid = &controller_path_pid_s;
- data.setting.default_path_pid_init = &controller_path_pid_init_s;
- data.setting.default_path_pid_prefix = &controller_path_pid_prefix_s;
- data.setting.default_path_pid_suffix = &controller_path_pid_suffix_s;
- data.setting.default_path_socket = &controller_path_socket_s;
- data.setting.default_path_socket_init = &controller_path_socket_init_s;
- data.setting.default_path_socket_prefix = &controller_path_socket_prefix_s;
- data.setting.default_path_socket_suffix = &controller_path_socket_suffix_s;
-
- data.setting.program_name = &controller_program_name_s;
- data.setting.program_name_long = &controller_program_name_long_s;
-
- // When run as "init" by default, provide the default system-level init path.
- #ifdef _controller_as_init_
- data.setting.flag |= controller_main_flag_init_e;
- #else
- data.setting.flag &= ~controller_main_flag_init_e;
- #endif // _controller_as_init_
-
- controller_process_t process = controller_process_t_initialize;
- data.process = &process;
-
- f_console_parameter_t parameters[] = controller_console_parameter_t_initialize;
- data.program.parameters.array = parameters;
- data.program.parameters.used = controller_parameter_total_d;
- data.program.environment = envp;
-
- data.program.pid = getpid();
-
- 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);
-
- controller_setting_load(arguments, &data);
- }
-
- controller_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, &controller_thread_signal, (void *) &data); // @fixme
-
- if (F_status_is_error(data.setting.state.status)) {
- //controller_print_error(thread, &data.program.error, macro_controller_f(f_thread_create)); // @fixme
- }
- else {
- {
- const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize_1(argc, argv, envp);
-
- controller_setting_load(arguments, &data);
- }
-
- if (!controller_signal_check(&data)) {
- controller_main(&data);
- }
-
- f_thread_cancel(id_signal);
- f_thread_join(id_signal, 0);
- }
- }
- #endif // _di_thread_support_
-
- controller_main_delete(&data);
-
- fll_program_standard_set_down(&data.program);
-
- // When the child process exits, it must return the code to the parent so the parent knows how to handle the exit.
- if (data.setting.state.status == F_child) {
- exit(data.program.child);
- }
-
- return F_status_is_error(data.setting.state.status) ? 1 : 0;
-}
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- *
- * This file is only ever included by main/main.c and should not normally be included anywhere else.
- * Anything that wants to include this should be providing the "controller" program functionality in some manner.
- */
-#ifndef _controller_main_h
-#define _controller_main_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Standard program entry point.
- *
- * @param argc
- * The number of arguments.
- * @param argv
- * The array of arguments.
- * @param envp
- * The array of all environment variables on program start.
- *
- * @return
- * 0 on success.
- * 1 on error.
- */
-extern int main(const int argc, const f_string_t *argv, const f_string_t *envp);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _controller_main_h
+++ /dev/null
-#include "controller.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_print_message_help_
- f_status_t controller_print_message_help(fl_print_t * const print) {
-
- if (!print || !print->custom) return F_status_set_error(F_output_not);
-
- controller_main_t * const main = (controller_main_t *) print->custom;
-
- f_file_stream_lock(print->to);
-
- fll_program_print_help_header(print, main->setting.program_name_long, controller_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, controller_short_cgroup_s, controller_long_cgroup_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Specify a custom control group file path, such as '" F_control_group_path_system_prefix_s F_control_group_path_system_default_s "'.");
- fll_program_print_help_option(print, controller_short_daemon_s, controller_long_daemon_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Run in daemon only mode (do not process the entry).");
- fll_program_print_help_option(print, controller_short_init_s, controller_long_init_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " The program will run as an init replacement.");
- fll_program_print_help_option(print, controller_short_interruptible_s, controller_long_interruptible_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Designate that this program can be interrupted by a signal.");
- fll_program_print_help_option(print, controller_short_pid_s, controller_long_pid_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Specify a custom pid file path, such as 'controller/run/default.pid'.");
- fll_program_print_help_option(print, controller_short_settings_s, controller_long_settings_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Specify a custom settings path, such as 'controller/'.");
- fll_program_print_help_option(print, controller_short_simulate_s, controller_long_simulate_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Run as a simulation.");
- fll_program_print_help_option(print, controller_short_socket_s, controller_long_socket_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Specify a custom socket file path, such as 'controller/run/default.socket'.");
- fll_program_print_help_option(print, controller_short_uninterruptible_s, controller_long_uninterruptible_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, "Designate that this program cannot be interrupted by a signal.");
- fll_program_print_help_option(print, controller_short_validate_s, controller_long_validate_s, f_console_symbol_short_normal_s, f_console_symbol_long_normal_s, " Validate the settings (entry and rules) without running (does not simulate).");
-
- f_print_dynamic_raw(f_string_eol_s, print->to);
-
- fll_program_print_help_usage(print, main->setting.program_name, f_string_empty_s);
-
- fl_print_format("%r When both the %[%r%r%] parameter and the", print->to, f_string_eol_s, print->set->notable, f_console_symbol_long_normal_s, controller_long_simulate_s, print->set->notable);
- fl_print_format(" %[%r%r%] parameter are specified, then additional information on each would be executed rule is printed but no simulation is performed.%r%r", print->to, print->set->notable, f_console_symbol_long_normal_s, controller_long_validate_s, print->set->notable, f_string_eol_s, f_string_eol_s);
-
- fl_print_format(" The default interrupt behavior is to operate as if the %[%r%r%] parameter is passed.%r%r", print->to, print->set->notable, f_console_symbol_long_normal_s, (main->setting.flag & controller_main_flag_init_e) ? controller_long_uninterruptible_s : controller_long_interruptible_s, print->set->notable, f_string_eol_s, f_string_eol_s);
-
- fl_print_format(" Specify an empty string for the %[%r%r%] parameter to disable pid file creation for this program.%r", print->to, print->set->notable, f_console_symbol_long_normal_s, controller_long_pid_s, print->set->notable, f_string_eol_s);
-
- f_file_stream_flush(print->to);
- f_file_stream_unlock(print->to);
-
- return F_okay;
- }
-#endif // _di_controller_print_message_help_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _controller_print_h
-#define _controller_print_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Print help.
- *
- * @param print
- * The output structure to print to.
- *
- * The print.custom is expected to be of type controller_main_t.
- *
- * This does not alter print.custom.setting.state.status.
- *
- * @return
- * F_okay on success.
- * F_output_not on success, but no printing is performed.
- *
- * F_output_not (with error bit) if a parameter is NULL.
- */
-#ifndef _di_controller_print_message_help_
- extern f_status_t controller_print_message_help(fl_print_t * const print);
-#endif // _di_controller_print_message_help_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _controller_print_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "../controller/private-controller.h"
-#include "../lock/private-lock.h"
-#include "../lock/private-lock_print.h"
-#include "../process/private-process.h"
-#include "../rule/private-rule.h"
-#include "../thread/private-thread.h"
-#include "../thread/private-thread_process.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_process_find_
- f_status_t controller_process_find(const f_number_unsigned_t action, const f_string_static_t alias, const controller_processs_t processs, f_number_unsigned_t *at) {
-
- if (!alias.used) return F_okay;
- if (!processs.used) return F_false;
-
- for (f_number_unsigned_t i = 0; i < processs.used; ++i) {
-
- if (processs.array[i] && processs.array[i]->action == action && f_compare_dynamic(alias, processs.array[i]->rule.alias) == F_equal_to) {
- if (at) *at = i;
-
- return F_true;
- }
- } // for
-
- return F_false;
- }
-#endif // _di_controller_process_find_
-
-#ifndef _di_controller_process_prepare_
- f_status_t controller_process_prepare(const controller_global_t global, const bool is_normal, const uint8_t action, const f_string_static_t alias, f_number_unsigned_t *id) {
-
- f_status_t status = F_okay;
-
- if (controller_process_find(action, alias, global.thread->processs, id) == F_false) {
- f_thread_unlock(&global.thread->lock.process);
-
- status = controller_lock_write(is_normal, global.thread, &global.thread->lock.process);
-
- if (F_status_is_error(status)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status), F_false, global.thread);
- }
- else {
- status = controller_processs_increase(&global.thread->processs);
- }
-
- if (F_status_is_error_not(status) && global.thread->processs.array[global.thread->processs.used]) {
-
- controller_data_t *process = global.thread->processs.array[global.thread->processs.used];
-
- status = controller_lock_write(is_normal, global.thread, &process->lock);
-
- if (F_status_is_error(status)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status), F_false, global.thread);
- }
- else {
- process->action = action;
- process->rule.alias.used = 0;
-
- status = f_string_dynamic_append(alias, &process->rule.alias);
-
- if (F_status_is_error_not(status)) {
- process->id = global.thread->processs.used++;
- status = F_okay;
-
- if (id) {
- *id = process->id;
- }
- }
-
- f_thread_unlock(&process->lock);
- }
- }
-
- f_thread_unlock(&global.thread->lock.process);
-
- // The read lock must be restored on return.
- const f_status_t status_lock = controller_lock_read(is_normal, global.thread, &global.thread->lock.process);
-
- if (F_status_is_error(status_lock)) {
- return F_status_set_error(F_lock);
- }
- }
- else {
- status = F_found;
- }
-
- return status;
- }
-#endif // _di_controller_process_prepare_
-
-#ifndef _di_controller_process_prepare_process_type_
- f_status_t controller_process_prepare_process_type(const controller_global_t global, const uint8_t type, const uint8_t action, const f_string_static_t alias, f_number_unsigned_t *id) {
-
- return controller_process_prepare(global, type != controller_data_type_exit_e, action, alias, id);
- }
-#endif // _di_controller_process_prepare_process_type_
-
-#ifndef _di_controller_process_wait_
- f_status_t controller_process_wait(const controller_global_t global, controller_data_t * const process) {
-
- if (!controller_thread_is_enabled_process(process, global.thread)) {
- return F_status_set_error(F_interrupt);
- }
-
- f_time_spec_t time;
-
- f_status_t status = F_okay;
- f_status_t status_lock = F_okay;
-
- uint8_t count = 0;
-
- do {
- f_thread_mutex_lock(&process->wait_lock);
-
- if (count < controller_thread_wait_timeout_1_before_d) {
- controller_time(controller_thread_wait_timeout_1_seconds_d, controller_thread_wait_timeout_1_nanoseconds_d, &time);
- }
- else if (count < controller_thread_wait_timeout_2_before_d) {
- controller_time(controller_thread_wait_timeout_2_seconds_d, controller_thread_wait_timeout_2_nanoseconds_d, &time);
- }
- else if (count < controller_thread_wait_timeout_3_before_d) {
- controller_time(controller_thread_wait_timeout_3_seconds_d, controller_thread_wait_timeout_3_nanoseconds_d, &time);
- }
- else {
- controller_time(controller_thread_wait_timeout_4_seconds_d, controller_thread_wait_timeout_4_nanoseconds_d, &time);
- }
-
- status = f_thread_condition_wait_timed(&time, &process->wait, &process->wait_lock);
-
- f_thread_mutex_unlock(&process->wait_lock);
-
- if (!controller_thread_is_enabled_process(process, global.thread)) {
- return F_status_set_error(F_interrupt);
- }
-
- if (F_status_is_error(status)) break;
-
- status_lock = controller_lock_read_process(process, global.thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- break;
- }
-
- if (!controller_rule_status_is_available(process->action, process->rule) && !(process->state == controller_process_state_active_e || process->state == controller_process_state_busy_e)) {
- f_thread_unlock(&process->lock);
-
- return F_okay;
- }
-
- if (status != F_time) {
-
- // move up the wait timer after a trigger was received.
- if (count < controller_thread_wait_timeout_2_before_d) {
- count = 0;
- }
- else if (count < controller_thread_wait_timeout_3_before_d) {
- count = controller_thread_wait_timeout_1_before_d;
- }
- else {
- count = controller_thread_wait_timeout_2_before_d;
- }
- }
-
- f_thread_unlock(&process->lock);
-
- if (count < controller_thread_wait_timeout_3_before_d) {
- ++count;
- }
-
- } while (status == F_time && controller_thread_is_enabled_process(process, global.thread));
-
- return status;
- }
-#endif // _di_controller_process_wait_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_process_h
-#define _PRIVATE_process_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Prepare the process.
- *
- * The process is initialized with the process id, the rule alias, and the rule action type.
- * These are the necessary parts for uniquely identifying the process.
- *
- * If a process by the given Rule alias and Rule Action already exists, then nothing is done.
- *
- * This requires that a global.thread->lock.process lock be set on process->lock before being called.
- *
- * @param global
- * The global data.
- * @param is_normal
- * If TRUE, then process as if this operates during a normal operation (entry and control).
- * If FALSE, then process as if this operates during a an exit operation.
- * @param action
- * The Rule Action to use.
- * @param alias
- * The Rule alias to use.
- * @param id
- * (optional) The process ID when found or created.
- *
- * Set to NULL to not use.
- *
- * @return
- * F_okay on success.
- * F_found on success, but nothing was done because an existing process was found.
- *
- * F_lock (with error bit) if failed to re-establish read lock on global.thread->lock.process while returning.
- *
- * Errors (with error bit) from: f_string_dynamic_append().
- *
- * Errors (with error bit) from: controller_lock_read().
- * Errors (with error bit) from: controller_lock_write().
- *
- * @see f_string_dynamic_append()
- * @see controller_lock_read()
- * @see controller_lock_write()
- */
-#ifndef _di_controller_process_prepare_
- extern f_status_t controller_process_prepare(const controller_global_t global, const bool is_normal, const uint8_t action, const f_string_static_t alias, f_number_unsigned_t *id) F_attribute_visibility_internal_d;
-#endif // _di_controller_process_prepare_
-
-/**
- * Prepare the process for some process type.
- *
- * The process is initialized with the process id, the rule alias, and the rule action type.
- * These are the necessary parts for uniquely identifying the process.
- *
- * If a process by the given Rule alias and Rule Action already exists, then nothing is done.
- *
- * This requires that a global.thread->lock.process lock be set on process->lock before being called.
- *
- * @param global
- * The global data.
- * @param type
- * The process type to use when checking if thread is enabled.
- * @param action
- * The Rule Action to use.
- * @param alias
- * The Rule alias to use.
- * @param id
- * (optional) The process ID when found or created.
- *
- * Set to NULL to not use.
- *
- * @return
- * Success from: controller_process_prepare()
- *
- * Errors (with error bit) from: controller_process_prepare().
- *
- * @see controller_process_prepare()
- */
-#ifndef _di_controller_process_prepare_process_type_
- extern f_status_t controller_process_prepare_process_type(const controller_global_t global, const uint8_t type, const uint8_t action, const f_string_static_t alias, f_number_unsigned_t *id) F_attribute_visibility_internal_d;
-#endif // _di_controller_process_prepare_process_type_
-
-/**
- * Find an existing process, for the given Rule Action.
- *
- * Do not confuse this with a process in the context of a PID.
- * This is a stucture for the current processing of some rule.
- *
- * This does not do any locking or unlocking for the processs data, be sure to lock appropriately before and after calling this.
- *
- * @param action
- * The Rule Action to find.
- * @param alias
- * The Rule alias to find.
- * @param processs
- * The array of processes to.
- * @param at
- * The location within processs the id was found.
- * (optional) Set to NULL to disable.
- *
- * @return
- * F_okay if not given a valid id to search.
- * F_false if there is no process found.
- * F_true if there is a process found (address is stored in "at").
- */
-#ifndef _di_controller_process_find_
- f_status_t controller_process_find(const f_number_unsigned_t action, const f_string_static_t alias, const controller_processs_t processs, f_number_unsigned_t *at) F_attribute_visibility_internal_d;
-#endif // _di_controller_process_find_
-
-/***
- * Safely wait for a process, periodically checking to see if process completed or check if exiting.
- *
- * @param global
- * The global data.
- * @param process
- * The process to wait on.
- *
- * @return
- * F_okay on success.
- *
- * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
- *
- * Success from: f_thread_condition_wait_timed().
- *
- * Errors (with error bit) from: f_thread_condition_wait_timed().
- *
- * @see f_thread_condition_wait_timed()
- */
-#ifndef _di_controller_process_wait_
- extern f_status_t controller_process_wait(const controller_global_t global, controller_data_t * const process) F_attribute_visibility_internal_d;
-#endif // _di_controller_process_wait_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_process_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "../controller/private-controller.h"
-#include "../controller/private-controller_print.h"
-#include "../lock/private-lock.h"
-#include "../lock/private-lock_print.h"
-#include "../process/private-process.h"
-#include "../rule/private-rule.h"
-#include "../rule/private-rule_print.h"
-#include "../thread/private-thread.h"
-#include "../thread/private-thread_process.h"
-#include "../thread/private-thread_signal.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_rule_string_s_
- const f_string_static_t controller_rule_needed_s = macro_f_string_static_t_initialize_1(CONTROLLER_rule_needed_s, 0, CONTROLLER_rule_needed_s_length);
- const f_string_static_t controller_rule_wanted_s = macro_f_string_static_t_initialize_1(CONTROLLER_rule_wanted_s, 0, CONTROLLER_rule_wanted_s_length);
- const f_string_static_t controller_rule_wished_s = macro_f_string_static_t_initialize_1(CONTROLLER_rule_wished_s, 0, CONTROLLER_rule_wished_s_length);
-#endif // _di_controller_rule_print_string_s_
-
-#ifndef _di_controller_rule_action_method_name_
- f_string_static_t controller_rule_action_method_name(const uint8_t type) {
-
- f_string_static_t buffer = f_string_static_t_initialize;
-
- switch (type) {
- case controller_rule_action_method_extended_e:
- buffer = controller_rule_action_method_string_extended_s;
- break;
-
- case controller_rule_action_method_extended_list_e:
- buffer = controller_rule_action_method_string_extended_list_s;
- break;
- }
-
- return buffer;
- }
-#endif // _di_controller_rule_action_method_name_
-
-#ifndef _di_controller_rule_find_
- f_status_t controller_rule_find(const f_string_static_t alias, const controller_rules_t rules, f_number_unsigned_t *at) {
-
- if (!alias.used) return F_okay;
- if (!rules.used) return F_false;
-
- for (f_number_unsigned_t i = 0; i < rules.used; ++i) {
-
- if (f_compare_dynamic(alias, rules.array[i].alias) == F_equal_to) {
- if (at) *at = i;
-
- return F_true;
- }
- } // for
-
- return F_false;
- }
-#endif // _di_controller_rule_find_
-
-#ifndef _di_controller_rule_parameters_read_
- f_status_t controller_rule_parameters_read(const controller_global_t global, const f_string_static_t buffer, f_range_t * const object, f_ranges_t * const content, controller_rule_action_t * const action, f_state_t * const state) {
-
- f_status_t status = F_okay;
-
- action->parameters.used = 0;
- action->ikis.used = 0;
-
- if (object && object->start <= object->stop) {
- if (content) {
- status = f_memory_array_increase_by(content->used + 1, sizeof(f_string_dynamic_t), (void **) &action->parameters.array, &action->parameters.used, &action->parameters.size);
- }
- else {
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_string_dynamic_t), (void **) &action->parameters.array, &action->parameters.used, &action->parameters.size);
- }
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), content ? "f_memory_array_increase_by" : "f_memory_array_increase", F_true);
-
- return status;
- }
-
- if (content) {
- status = f_memory_array_increase_by(content->used + 1, sizeof(f_iki_data_t), (void **) &action->ikis.array, &action->ikis.used, &action->ikis.size);
- }
- else {
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_iki_data_t), (void **) &action->ikis.array, &action->ikis.used, &action->ikis.size);
- }
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), content ? "f_memory_array_increase_by" : "f_memory_array_increase", F_true);
-
- return status;
- }
-
- action->parameters.array[action->parameters.used].used = 0;
- action->ikis.array[action->ikis.used].content.used = 0;
- action->ikis.array[action->ikis.used].delimits.used = 0;
- action->ikis.array[action->ikis.used].variable.used = 0;
- action->ikis.array[action->ikis.used].vocabulary.used = 0;
-
- status = f_string_dynamic_partial_append_nulless(buffer, *object, &action->parameters.array[0]);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true);
-
- return status;
- }
-
- ++action->parameters.used;
- ++action->ikis.used;
- }
-
- if (content && content->used) {
- status = f_memory_array_increase_by(content->used, sizeof(f_string_dynamic_t), (void **) &action->parameters.array, &action->parameters.used, &action->parameters.size);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_memory_array_increase_by", F_true);
-
- return status;
- }
-
- status = f_memory_array_increase_by(content->used, sizeof(f_iki_data_t), (void **) &action->ikis.array, &action->ikis.used, &action->ikis.size);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_memory_array_increase_by", F_true);
-
- return status;
- }
-
- f_range_t range = f_range_t_initialize;
-
- for (f_number_unsigned_t i = 0; i < content->used; ++i) {
-
- if (content->array[i].start > content->array[i].stop) continue;
-
- action->parameters.array[action->parameters.used].used = 0;
- action->ikis.array[action->ikis.used].content.used = 0;
- action->ikis.array[action->ikis.used].delimits.used = 0;
- action->ikis.array[action->ikis.used].variable.used = 0;
- action->ikis.array[action->ikis.used].vocabulary.used = 0;
-
- status = f_string_dynamic_partial_append_nulless(buffer, content->array[i], &action->parameters.array[action->parameters.used]);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true);
-
- return status;
- }
-
- if (action->parameters.array[action->parameters.used].used) {
- range.start = 0;
- range.stop = action->parameters.array[action->parameters.used].used - 1;
-
- fl_iki_read(&action->parameters.array[action->parameters.used], &range, &action->ikis.array[action->ikis.used], state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "fl_iki_read", F_true);
-
- action->parameters.array[action->parameters.used].used = 0;
-
- return status;
- }
- }
-
- ++action->parameters.used;
- ++action->ikis.used;
- } // for
- }
-
- return F_okay;
- }
-#endif // _di_controller_rule_parameters_read_
-
-#ifndef _di_controller_rule_action_type_to_action_execute_type_
- uint8_t controller_rule_action_type_to_action_execute_type(const uint8_t type) {
-
- if (type == controller_rule_action_type_freeze_e) {
- return controller_rule_action_execute_type_freeze_e;
- }
-
- if (type == controller_rule_action_type_kill_e) {
- return controller_rule_action_execute_type_kill_e;
- }
-
- if (type == controller_rule_action_type_pause_e) {
- return controller_rule_action_execute_type_pause_e;
- }
-
- if (type == controller_rule_action_type_reload_e) {
- return controller_rule_action_execute_type_reload_e;
- }
-
- if (type == controller_rule_action_type_restart_e) {
- return controller_rule_action_execute_type_restart_e;
- }
-
- if (type == controller_rule_action_type_resume_e) {
- return controller_rule_action_execute_type_resume_e;
- }
-
- if (type == controller_rule_action_type_start_e) {
- return controller_rule_action_execute_type_start_e;
- }
-
- if (type == controller_rule_action_type_stop_e) {
- return controller_rule_action_execute_type_stop_e;
- }
-
- if (type == controller_rule_action_type_thaw_e) {
- return controller_rule_action_execute_type_thaw_e;
- }
-
- return controller_rule_action_execute_type__enum_size_e;
- }
-#endif // _di_controller_rule_action_type_to_action_execute_type_
-
-#ifndef _di_controller_rule_action_read_
- f_status_t controller_rule_action_read(const controller_global_t global, const bool is_normal, const uint8_t type, const uint8_t method, controller_cache_t * const cache, controller_rule_item_t *item, controller_rule_actions_t *actions, f_range_t *range) {
-
- f_status_t status = F_okay;
-
- controller_state_interrupt_t custom = macro_controller_state_interrupt_t_initialize_1(is_normal, global.thread);
- f_state_t state = macro_f_state_t_initialize_1(controller_common_allocation_large_d, controller_common_allocation_small_d, F_okay, 0, 0, 0, &controller_thread_signal_state_fss, 0, (void *) &custom, 0);
-
- f_number_unsigned_t i = 0;
-
- for (; i < cache->comments.size; ++i) {
-
- cache->comments.array[i].start = 1;
- cache->comments.array[i].stop = 0;
- } // for
-
- for (i = 0; i < cache->delimits.size; ++i) {
- cache->delimits.array[i] = 0;
- } // for
-
- for (i = 0; i < cache->content_action.size; ++i) {
-
- cache->content_action.array[i].start = 1;
- cache->content_action.array[i].stop = 0;
- } // for
-
- cache->comments.used = 0;
- cache->delimits.used = 0;
- cache->content_action.used = 0;
-
- if (method == controller_rule_action_method_extended_list_e) {
- fl_fss_extended_list_content_read(cache->buffer_item, range, &cache->content_action, &cache->delimits, &cache->comments, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "fl_fss_extended_list_content_read", F_true);
-
- return status;
- }
-
- if (status == F_fss_found_content) {
- f_fss_apply_delimit(cache->delimits, &cache->buffer_item, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_fss_apply_delimit", F_true);
-
- return status;
- }
-
- // The "script" and "utility" types use the entire content and can be directly passed through at index 0.
- if (item->type == controller_rule_item_type_script_e || item->type == controller_rule_item_type_utility_e) {
- actions->array[actions->used].parameters.used = 0;
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_string_dynamic_t), (void **) &actions->array[actions->used].parameters.array, &actions->array[actions->used].parameters.used, &actions->array[actions->used].parameters.size);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_memory_array_increase", F_true);
-
- return status;
- }
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_iki_data_t), (void **) &actions->array[actions->used].ikis.array, &actions->array[actions->used].ikis.used, &actions->array[actions->used].ikis.size);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_memory_array_increase", F_true);
-
- return status;
- }
-
- actions->array[actions->used].type = type;
- actions->array[actions->used].line = cache->action.line_action;
- actions->array[actions->used].status = F_known_not;
-
- status = f_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_action.array[0], &actions->array[actions->used].parameters.array[0]);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true);
-
- actions->array[actions->used++].status = controller_status_simplify_error(F_status_set_fine(status));
-
- return status;
- }
-
- if (actions->array[actions->used].parameters.array[0].used) {
- state.step_large = controller_common_allocation_iki_large_d;
- state.step_small = controller_common_allocation_iki_small_d;
- state.interrupt = &controller_thread_signal_state_iki;
-
- f_range_t range_iki = macro_f_range_t_initialize_2(actions->array[actions->used].parameters.array[0].used);
-
- fl_iki_read(&actions->array[actions->used].parameters.array[0], &range_iki, &actions->array[actions->used].ikis.array[0], &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "fl_iki_read", F_true);
-
- actions->array[actions->used++].status = controller_status_simplify_error(F_status_set_fine(status));
-
- return status;
- }
- }
-
- actions->array[actions->used].ikis.used = 1;
- actions->array[actions->used++].parameters.used = 1;
-
- return status;
- }
-
- cache->delimits.used = 0;
-
- // The object_actions and content_actions caches are being used for the purposes of getting the parameters a given the action.
- fll_fss_extended_read(cache->buffer_item, &cache->content_action.array[0], &cache->object_actions, &cache->content_actions, 0, 0, &cache->delimits, 0, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "fll_fss_extended_read", F_true);
-
- return status;
- }
-
- f_fss_apply_delimit(cache->delimits, &cache->buffer_item, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_fss_apply_delimit", F_true);
-
- return status;
- }
-
- for (i = 0; i < cache->object_actions.used; ++i) {
-
- status = controller_rule_actions_increase_by(controller_common_allocation_small_d, actions);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "controller_rule_actions_increase_by", F_true);
-
- return status;
- }
-
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &actions->array[actions->used].line, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_fss_count_lines", F_true);
-
- return status;
- }
-
- actions->array[actions->used].type = type;
- actions->array[actions->used].line += ++item->line;
- actions->array[actions->used].status = F_known_not;
-
- status = controller_rule_parameters_read(global, cache->buffer_item, &cache->object_actions.array[i], &cache->content_actions.array[i], &actions->array[actions->used], &state);
-
- if (F_status_is_error(status)) {
- actions->array[actions->used++].status = controller_status_simplify_error(F_status_set_fine(status));
-
- return status;
- }
-
- actions->array[actions->used++].status = status;
- } // for
-
- range->start = cache->content_action.array[0].start;
- }
- else {
- status = F_data_not;
- }
- }
- else {
- fl_fss_extended_content_read(cache->buffer_item, range, &cache->content_action, 0, &cache->delimits, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "fll_fss_extended_content_read", F_true);
- }
- else if (status == F_fss_found_content) {
- f_fss_apply_delimit(cache->delimits, &cache->buffer_item, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_fss_apply_delimit", F_true);
- }
- else if (type == controller_rule_action_type_pid_file_e) {
- item->pid_file.used = 0;
-
- status = f_rip_dynamic_partial(cache->buffer_item, cache->content_action.array[0], &item->pid_file);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_rip_dynamic_partial", F_true);
- }
- }
- else if (type == controller_rule_action_type_rerun_e) {
- uint8_t type_rerun = 0;
-
- if (cache->content_action.used) {
- if (f_compare_dynamic_partial_string(controller_freeze_s.string, cache->buffer_item, controller_freeze_s.used, cache->content_action.array[0]) == F_equal_to) {
- type_rerun = controller_rule_action_execute_type_freeze_e;
- }
- if (f_compare_dynamic_partial_string(controller_kill_s.string, cache->buffer_item, controller_kill_s.used, cache->content_action.array[0]) == F_equal_to) {
- type_rerun = controller_rule_action_execute_type_kill_e;
- }
- else if (f_compare_dynamic_partial_string(controller_pause_s.string, cache->buffer_item, controller_pause_s.used, cache->content_action.array[0]) == F_equal_to) {
- type_rerun = controller_rule_action_execute_type_pause_e;
- }
- else if (f_compare_dynamic_partial_string(controller_reload_s.string, cache->buffer_item, controller_reload_s.used, cache->content_action.array[0]) == F_equal_to) {
- type_rerun = controller_rule_action_execute_type_reload_e;
- }
- else if (f_compare_dynamic_partial_string(controller_restart_s.string, cache->buffer_item, controller_restart_s.used, cache->content_action.array[0]) == F_equal_to) {
- type_rerun = controller_rule_action_execute_type_restart_e;
- }
- else if (f_compare_dynamic_partial_string(controller_resume_s.string, cache->buffer_item, controller_resume_s.used, cache->content_action.array[0]) == F_equal_to) {
- type_rerun = controller_rule_action_execute_type_resume_e;
- }
- else if (f_compare_dynamic_partial_string(controller_start_s.string, cache->buffer_item, controller_start_s.used, cache->content_action.array[0]) == F_equal_to) {
- type_rerun = controller_rule_action_execute_type_start_e;
- }
- else if (f_compare_dynamic_partial_string(controller_stop_s.string, cache->buffer_item, controller_stop_s.used, cache->content_action.array[0]) == F_equal_to) {
- type_rerun = controller_rule_action_execute_type_stop_e;
- }
- else if (f_compare_dynamic_partial_string(controller_thaw_s.string, cache->buffer_item, controller_thaw_s.used, cache->content_action.array[0]) == F_equal_to) {
- type_rerun = controller_rule_action_execute_type_thaw_e;
- }
- }
-
- if (!type_rerun) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QRule item action '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_rerun_s, global.main->program.error.notable);
- fl_print_format("%[' has '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_Q_range_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->buffer_item, cache->content_action.array[0], global.main->program.error.notable);
- fl_print_format("%[' as the first value, only the following are allowed: '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%r%]%[', '%]", global.main->program.error.to, global.main->program.error.notable, controller_freeze_s, global.main->program.error.notable, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%r%]%[', '%]", global.main->program.error.to, global.main->program.error.notable, controller_kill_s, global.main->program.error.notable, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%r%]%[', '%]", global.main->program.error.to, global.main->program.error.notable, controller_pause_s, global.main->program.error.notable, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%r%]%[', '%]", global.main->program.error.to, global.main->program.error.notable, controller_reload_s, global.main->program.error.notable, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%r%]%[', '%]", global.main->program.error.to, global.main->program.error.notable, controller_restart_s, global.main->program.error.notable, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%r%]%[', '%]", global.main->program.error.to, global.main->program.error.notable, controller_resume_s, global.main->program.error.notable, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%r%]%[', '%]", global.main->program.error.to, global.main->program.error.notable, controller_start_s, global.main->program.error.notable, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%r%]%[', or '%]", global.main->program.error.to, global.main->program.error.notable, controller_stop_s, global.main->program.error.notable, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_thaw_s, global.main->program.error.notable, global.main->program.error.context);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_true);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- return F_status_set_error(F_valid_not);
- }
-
- controller_rule_rerun_item_t *rerun_item = 0;
-
- if (cache->content_action.used > 1) {
- if (f_compare_dynamic_partial_string(controller_failure_s.string, cache->buffer_item, controller_failure_s.used, cache->content_action.array[1]) == F_equal_to) {
- rerun_item = &item->reruns[type_rerun].failure;
- item->reruns[type_rerun].is |= controller_rule_rerun_is_failure_d;
- }
- else if (f_compare_dynamic_partial_string(controller_success_s.string, cache->buffer_item, controller_success_s.used, cache->content_action.array[1]) == F_equal_to) {
- rerun_item = &item->reruns[type_rerun].success;
- item->reruns[type_rerun].is |= controller_rule_rerun_is_success_d;
- }
- }
- else {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QRule item action '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_rerun_s, global.main->program.error.notable);
- fl_print_format("%[' has '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_Q_range_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->buffer_item, cache->content_action.array[1], global.main->program.error.notable);
- fl_print_format("%[' as the second value, only the following are allowed: '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%r%]%[' or '%]", global.main->program.error.to, global.main->program.error.notable, controller_stop_s, global.main->program.error.notable, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_thaw_s, global.main->program.error.notable, global.main->program.error.context);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_true);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- return F_status_set_error(F_valid_not);
- }
-
- for (i = 2; i < cache->content_action.used; ++i) {
-
- if (f_compare_dynamic_partial_string(controller_delay_s.string, cache->buffer_item, controller_delay_s.used, cache->content_action.array[i]) == F_equal_to) {
- status = controller_rule_action_read_rerun_number(global, controller_delay_s.string, cache, &i, &rerun_item->delay);
- }
- else if (f_compare_dynamic_partial_string(controller_max_s.string, cache->buffer_item, controller_max_s.used, cache->content_action.array[i]) == F_equal_to) {
- status = controller_rule_action_read_rerun_number(global, controller_max_s.string, cache, &i, &rerun_item->max);
- }
- else if (f_compare_dynamic_partial_string(controller_reset_s.string, cache->buffer_item, controller_reset_s.used, cache->content_action.array[i]) == F_equal_to) {
- item->reruns[type_rerun].is |= rerun_item == &item->reruns[type_rerun].failure ? controller_rule_rerun_is_failure_reset_d : controller_rule_rerun_is_success_reset_d;
- }
- else {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QRule item action '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_rerun_s, global.main->program.error.notable);
- fl_print_format("%[' has an unknown value '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_Q_range_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->buffer_item, cache->content_action.array[i], global.main->program.error.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_true);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- return F_status_set_error(F_valid_not);
- }
- } // for
- }
- else if (type == controller_rule_action_type_with_e) {
- for (i = 0; i < cache->content_action.used; ++i) {
-
- if (f_compare_dynamic_partial_string(controller_full_path_s.string, cache->buffer_item, controller_full_path_s.used, cache->content_action.array[i]) == F_equal_to) {
- item->with |= controller_with_full_path_d;
- }
- else if (f_compare_dynamic_partial_string(controller_session_new_s.string, cache->buffer_item, controller_session_new_s.used, cache->content_action.array[i]) == F_equal_to) {
- item->with |= controller_with_session_new_d;
-
- // The "session_new" and "session_same" are mutually exclusive.
- item->with &= ~controller_with_session_same_d;
- }
- else if (f_compare_dynamic_partial_string(controller_session_same_s.string, cache->buffer_item, controller_session_same_s.used, cache->content_action.array[i]) == F_equal_to) {
- item->with |= controller_with_session_same_d;
-
- // The "session_new" and "session_same" are mutually exclusive.
- item->with &= ~controller_with_session_new_d;
- }
- else {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QUnknown value '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_range_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->buffer_item, cache->content_action.array[i], global.main->program.error.notable);
- fl_print_format("%[' for rule item action '%]%[%r%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, global.main->program.error.notable, controller_with_s, global.main->program.error.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_true);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- status = F_status_set_error(F_valid_not);
-
- break;
- }
- } // for
- }
- else if (item->type == controller_rule_item_type_script_e || item->type == controller_rule_item_type_utility_e) {
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_string_dynamic_t), (void **) &actions->array[actions->used].parameters.array, &actions->array[actions->used].parameters.used, &actions->array[actions->used].parameters.size);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_memory_array_increase", F_true);
-
- return status;
- }
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_iki_data_t), (void **) &actions->array[actions->used].ikis.array, &actions->array[actions->used].ikis.used, &actions->array[actions->used].ikis.size);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_memory_array_increase", F_true);
-
- return status;
- }
-
- // The "script" types use the entire content as a single string piped to the script, so merge all arguments together.
- actions->array[actions->used].type = type;
- actions->array[actions->used].line = cache->action.line_action;
- actions->array[actions->used].status = F_known_not;
-
- for (i = 0; i < cache->content_action.used; ++i) {
-
- status = f_string_dynamic_partial_mash_nulless(f_string_space_s, cache->buffer_item, cache->content_action.array[i], &actions->array[actions->used].parameters.array[0]);
- if (F_status_is_error(status)) break;
- } // for
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_partial_mash_nulless", F_true);
-
- actions->array[actions->used++].status = controller_status_simplify_error(F_status_set_fine(status));
-
- return status;
- }
-
- if (actions->array[actions->used].parameters.array[0].used) {
- state.step_large = controller_common_allocation_iki_large_d;
- state.step_small = controller_common_allocation_iki_small_d;
- state.interrupt = &controller_thread_signal_state_iki;
-
- f_range_t range_iki = macro_f_range_t_initialize_2(actions->array[actions->used].parameters.array[0].used);
-
- fl_iki_read(&actions->array[actions->used].parameters.array[0], &range_iki, &actions->array[actions->used].ikis.array[0], &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "fl_iki_read", F_true);
-
- actions->array[actions->used++].status = controller_status_simplify_error(F_status_set_fine(status));
-
- return status;
- }
- }
-
- actions->array[actions->used].ikis.used = 1;
- actions->array[actions->used++].parameters.used = 1;
- }
- else {
- f_fss_count_lines(cache->buffer_item, range->start, &actions->array[actions->used].line, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_fss_count_lines", F_true);
-
- return status;
- }
-
- actions->array[actions->used].type = type;
- actions->array[actions->used].line += ++item->line;
- actions->array[actions->used].status = F_known_not;
-
- status = controller_rule_parameters_read(global, cache->buffer_item, 0, &cache->content_action, &actions->array[actions->used], &state);
-
- if (F_status_is_error(status)) {
- actions->array[actions->used++].status = controller_status_simplify_error(F_status_set_fine(status));
-
- return status;
- }
-
- actions->array[actions->used++].status = status;
- }
- }
- else {
- status = F_data_not;
- }
- }
-
- if (F_status_is_error_not(status) && status == F_data_not) {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- fl_print_format("%r%[%QAction is empty, nothing to do.%]%r", global.main->program.warning.to, f_string_eol_s, global.main->program.warning.context, global.main->program.warning.prefix, global.main->program.warning.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.warning, cache->action, F_true);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
- }
-
- return status;
- }
-#endif // _di_controller_rule_action_read_
-
-#ifndef _di_controller_rule_action_read_rerun_number_
- f_status_t controller_rule_action_read_rerun_number(const controller_global_t global, const f_string_t name, controller_cache_t * const cache, f_number_unsigned_t * const index, f_number_unsigned_t * const number) {
-
- f_status_t status = F_okay;
- f_number_signed_t parsed = 0;
-
- if (*index + 1 == cache->content_action.used) {
- status = F_status_set_error(F_valid_not);
- }
- else {
- status = fl_conversion_dynamic_partial_to_signed_detect(fl_conversion_data_base_10_c, cache->buffer_item, cache->content_action.array[++(*index)], &parsed);
-
- if (F_status_set_fine(status) == F_number_positive) {
- status = fl_conversion_dynamic_partial_to_signed_detect(fl_conversion_data_base_10_c, cache->buffer_item, controller_range_after_number_sign(cache->buffer_item, cache->content_action.array[*index]), &parsed);
- }
-
- if (status == F_data_not) {
- status = F_status_set_error(F_valid_not);
- }
- }
-
- if (F_status_is_error(status)) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- status = F_status_set_fine(status);
-
- if (status != F_valid_not && status != F_number && status != F_number_decimal && status != F_number_overflow && status != F_number_underflow && status != F_number_negative) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "fl_conversion_dynamic_partial_to_signed_detect", F_true);
- }
- else {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QRule item action '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_rerun_s, global.main->program.error.notable);
- fl_print_format("%[' requires a positive whole number or 0 for the '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%S%]", global.main->program.error.to, global.main->program.error.notable, name, global.main->program.error.notable);
- fl_print_format("%[' value", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
-
- if (*index + 1 == cache->content_action.used) {
- fl_print_format(", but none were given.%]%r", global.main->program.error.to, global.main->program.error.context, f_string_eol_s);
- }
- else {
- fl_print_format(", but '%]%[%/Q%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.notable, cache->buffer_item, cache->content_action.array[*index], global.main->program.error.notable);
-
- if (status == F_number || status == F_number_decimal) {
- fl_print_format("%[' was given.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
- }
- else if (status == F_number_overflow) {
- fl_print_format("%[' is too large.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
- }
- else {
- fl_print_format("%[' is negative.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
- }
- }
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_true);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
- }
-
- return status;
- }
-
- *number = (f_number_unsigned_t) parsed;
-
- return F_okay;
- }
-#endif // _di_controller_rule_action_read_rerun_number_
-
-#ifndef _di_controller_rule_copy_
- f_status_t controller_rule_copy(const controller_rule_t source, controller_rule_t *destination) {
-
- // Delete the third party structures.
- f_memory_array_resize(0, sizeof(f_char_t), (void **) &destination->cgroup.path.string, &destination->cgroup.path.used, &destination->cgroup.path.size);
- f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &destination->cgroup.groups.array, &destination->cgroup.groups.used, &destination->cgroup.groups.size, &f_string_dynamics_delete_callback);
-
- f_capability_delete(&destination->capability);
-
- f_number_unsigned_t i = 0;
-
- for (; i < controller_rule_action_type__enum_size_e; ++i) {
- destination->status[i] = source.status[i];
- } // for
-
- destination->timeout_kill = source.timeout_kill;
- destination->timeout_start = source.timeout_start;
- destination->timeout_stop = source.timeout_stop;
-
- destination->has = source.has;
- destination->nice = source.nice;
- destination->user = source.user;
- destination->group = source.group;
-
- destination->timestamp.seconds = source.timestamp.seconds;
- destination->timestamp.seconds_nano = source.timestamp.seconds_nano;
-
- destination->alias.used = 0;
- destination->engine.used = 0;
- destination->engine_arguments.used = 0;
- destination->name.used = 0;
- destination->path.used = 0;
-
- destination->define.used = 0;
- destination->parameter.used = 0;
- destination->environment.used = 0;
-
- destination->affinity.used = 0;
- destination->groups.used = 0;
- destination->limits.used = 0;
- destination->scheduler.policy = source.scheduler.policy;
- destination->scheduler.priority = source.scheduler.priority;
-
- for (i = 0; i < destination->ons.size; ++i) {
-
- destination->ons.array[i].action = 0;
- destination->ons.array[i].need.used = 0;
- destination->ons.array[i].want.used = 0;
- destination->ons.array[i].wish.used = 0;
- } // for
-
- for (i = 0; i < destination->engine_arguments.size; ++i) {
- destination->engine_arguments.array[i].used = 0;
- } // for
-
- destination->ons.used = 0;
- destination->items.used = 0;
-
- f_status_t status = F_okay;
-
- status = f_string_dynamic_append(source.alias, &destination->alias);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_append(source.engine, &destination->engine);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_append(source.name, &destination->name);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_append(source.path, &destination->path);
- if (F_status_is_error(status)) return status;
-
- status = f_string_maps_append_all(source.define, &destination->define);
- if (F_status_is_error(status)) return status;
-
- status = f_string_maps_append_all(source.parameter, &destination->parameter);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamics_append_all(source.engine_arguments, &destination->engine_arguments);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamics_append_all(source.environment, &destination->environment);
- if (F_status_is_error(status)) return status;
-
- if (source.ons.used) {
- if (destination->ons.used < source.ons.used) {
- status = controller_rule_ons_resize(source.ons.used, &destination->ons);
- if (F_status_is_error(status)) return status;
- }
-
- for (i = 0; i < source.ons.used; ++i) {
-
- destination->ons.array[i].action = source.ons.array[i].action;
-
- if (source.ons.array[i].need.used) {
- destination->ons.array[i].need.used = 0;
-
- status = f_string_dynamics_append_all(source.ons.array[i].need, &destination->ons.array[i].need);
- if (F_status_is_error(status)) return status;
- }
-
- if (source.ons.array[i].want.used) {
- destination->ons.array[i].want.used = 0;
-
- status = f_string_dynamics_append_all(source.ons.array[i].want, &destination->ons.array[i].want);
- if (F_status_is_error(status)) return status;
- }
-
- if (source.ons.array[i].wish.used) {
- destination->ons.array[i].wish.used = 0;
-
- status = f_string_dynamics_append_all(source.ons.array[i].wish, &destination->ons.array[i].wish);
- if (F_status_is_error(status)) return status;
- }
- } // for
-
- destination->ons.used = source.ons.used;
- }
-
- status = f_memory_array_append_all(source.affinity.array, source.affinity.used, sizeof(int32_t), (void **) &destination->affinity.array, &destination->affinity.used, &destination->affinity.size);
- if (F_status_is_error(status)) return status;
-
- if (source.capability) {
- status = f_capability_copy(source.capability, &destination->capability);
- if (F_status_is_error(status)) return status;
- }
-
- status = f_control_group_copy(source.cgroup, &destination->cgroup);
- if (F_status_is_error(status)) return status;
-
- status = f_memory_array_append_all(source.groups.array, source.groups.used, sizeof(int32_t), (void **) &destination->groups.array, &destination->groups.used, &destination->groups.size);
- if (F_status_is_error(status)) return status;
-
- destination->limits.used = 0;
- status = f_memory_array_append_all(source.limits.array, source.limits.used, sizeof(f_limit_set_t), (void **) &destination->limits.array, &destination->limits.used, &destination->limits.size);
- if (F_status_is_error(status)) return status;
-
- if (source.items.used) {
- controller_rule_item_t *item_source = 0;
- controller_rule_item_t *item_destination = 0;
-
- controller_rule_action_t *action_source = 0;
- controller_rule_action_t *action_destination = 0;
-
- if (source.items.used > destination->items.size) {
- status = controller_rule_items_increase_by(source.items.used - destination->items.size, &destination->items);
- if (F_status_is_error(status)) return status;
- }
-
- f_number_unsigned_t j = 0;
-
- for (i = 0; i < source.items.used; ++i) {
-
- item_source = &source.items.array[i];
- item_destination = &destination->items.array[i];
-
- if (item_source->actions.used > item_destination->actions.size) {
- status = controller_rule_actions_increase_by(item_source->actions.used - item_destination->actions.size, &item_destination->actions);
- if (F_status_is_error(status)) return status;
- }
-
- item_destination->type = item_source->type;
- item_destination->with = item_source->with;
- item_destination->line = item_source->line;
- item_destination->pid_file.used = 0;
-
- status = f_string_dynamic_append(item_source->pid_file, &item_destination->pid_file);
- if (F_status_is_error(status)) return status;
-
- for (j = 0; j < controller_rule_action_execute_type__enum_size_e; ++j) {
-
- item_destination->reruns[j].is = item_source->reruns[j].is;
- item_destination->reruns[j].failure.count = item_source->reruns[j].failure.count;
- item_destination->reruns[j].failure.delay = item_source->reruns[j].failure.delay;
- item_destination->reruns[j].failure.max = item_source->reruns[j].failure.max;
- item_destination->reruns[j].success.count = item_source->reruns[j].success.count;
- item_destination->reruns[j].success.delay = item_source->reruns[j].success.delay;
- item_destination->reruns[j].success.max = item_source->reruns[j].success.max;
- } // for
-
- for (j = 0; j < item_source->actions.used; ++j) {
-
- action_source = &item_source->actions.array[j];
- action_destination = &item_destination->actions.array[j];
-
- action_destination->type = action_source->type;
- action_destination->line = action_source->line;
- action_destination->status = action_source->status;
-
- action_destination->parameters.used = 0;
- action_destination->ikis.used = 0;
-
- status = f_string_dynamics_append_all(action_source->parameters, &action_destination->parameters);
- if (F_status_is_error(status)) return status;
-
- status = f_iki_datas_append_all(action_source->ikis, &action_destination->ikis);
- if (F_status_is_error(status)) return status;
- } // for
-
- item_destination->actions.used = item_source->actions.used;
- } // for
-
- destination->items.used = source.items.used;
- }
-
- return status;
- }
-#endif // _di_controller_rule_copy_
-
-#ifndef _di_controller_rule_execute_
- f_status_t controller_rule_execute(const controller_global_t global, const uint8_t action, const uint8_t options, controller_data_t * const process) {
-
- f_status_t status = F_okay;
- f_status_t success = F_false;
-
- f_number_unsigned_t i = 0;
- f_number_unsigned_t j = 0;
- f_number_unsigned_t k = 0;
-
- // Child processes should receive all signals and handle the signals as they see fit.
- f_signal_how_t signals = f_signal_how_t_initialize;
- f_signal_set_empty(&signals.block);
- f_signal_set_fill(&signals.block_not);
-
- f_string_maps_t environment = f_string_maps_t_initialize;
-
- controller_execute_set_t execute_set = macro_controller_execute_set_t_initialize_1(0, 0, &environment, &signals, 0, fl_execute_as_t_initialize);
-
- if (process->rule.affinity.used) {
- execute_set.as.affinity = &process->rule.affinity;
- }
-
- if (process->rule.capability) {
- execute_set.as.capability = process->rule.capability;
- }
-
- if (process->rule.has & controller_rule_has_cgroup_d) {
- execute_set.as.control_group = &process->rule.cgroup;
-
- // Make sure all required cgroup directories exist.
- if (controller_rule_status_is_available(action, process->rule)) {
- status = fll_control_group_prepare(process->rule.cgroup);
-
- if (F_status_is_error(status)) {
- controller_print_error_file(global.thread, &global.main->program.error, F_status_set_fine(status), "fll_control_group_prepare", F_true, process->rule.cgroup.path, controller_rule_print_control_groups_prepare_s, fll_error_file_type_directory_e);
-
- return status;
- }
- }
- }
-
- if (process->rule.has & controller_rule_has_group_d) {
- execute_set.as.id_group = &process->rule.group;
-
- if (process->rule.groups.used) {
- execute_set.as.id_groups = &process->rule.groups;
- }
- }
-
- if (process->rule.limits.used) {
- execute_set.as.limits = &process->rule.limits;
- }
-
- if (process->rule.has & controller_rule_has_scheduler_d) {
- execute_set.as.scheduler = &process->rule.scheduler;
- }
-
- if (process->rule.has & controller_rule_has_nice_d) {
- execute_set.as.nice = &process->rule.nice;
- }
-
- if (process->rule.has & controller_rule_has_user_d) {
- execute_set.as.id_user = &process->rule.user;
- }
-
- if (process->rule.has & controller_rule_has_environment_d) {
- status = fl_environment_load_names(process->rule.environment, &environment);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "fl_environment_load_names", F_true);
-
- return status;
- }
-
- // When a "define" from the entry/exit is in the "environment", add it to the exported environments (and overwrite any existing environment variable of the same name).
- controller_entry_t *entry = 0;
-
- if (process->type == controller_data_type_entry_e) {
- entry = &global.setting->entry;
- }
- else if (process->type == controller_data_type_exit_e) {
- entry = &global.setting->exit;
- }
-
- if (entry) {
- for (i = 0; i < entry->define.used; ++i) {
-
- for (j = 0; j < process->rule.environment.used; ++j) {
-
- if (f_compare_dynamic(entry->define.array[i].key, process->rule.environment.array[j]) == F_equal_to) {
-
- for (k = 0; k < environment.used; ++k) {
-
- if (f_compare_dynamic(entry->define.array[i].key, environment.array[k].key) == F_equal_to) {
-
- environment.array[k].value.used = 0;
-
- status = f_string_dynamic_append(entry->define.array[i].value, &environment.array[k].value);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_append", F_true);
-
- return status;
- }
-
- break;
- }
- } // for
-
- if (k == environment.used) {
- status = f_string_maps_append(entry->define.array[i], &environment);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_maps_append", F_true);
-
- return status;
- }
- }
-
- break;
- }
- } // for
- } // for
- }
-
- // When a "define" is in the "environment", add it to the exported environments (and overwrite any existing environment variable of the same name).
- for (i = 0; i < process->rule.define.used; ++i) {
-
- for (j = 0; j < process->rule.environment.used; ++j) {
-
- if (f_compare_dynamic(process->rule.define.array[i].key, process->rule.environment.array[j]) == F_equal_to) {
-
- for (k = 0; k < environment.used; ++k) {
-
- if (f_compare_dynamic(process->rule.define.array[i].key, environment.array[k].key) == F_equal_to) {
-
- environment.array[k].value.used = 0;
-
- status = f_string_dynamic_append(process->rule.define.array[i].value, &environment.array[k].value);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_append", F_true);
-
- return status;
- }
-
- break;
- }
- } // for
-
- if (k == environment.used) {
- status = f_string_maps_append(process->rule.define.array[i], &environment);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_maps_append", F_true);
-
- return status;
- }
- }
-
- break;
- }
- } // for
- } // for
- }
- else {
- controller_entry_t *entry = 0;
-
- if (process->type == controller_data_type_entry_e) {
- entry = &global.setting->entry;
- }
- else if (process->type == controller_data_type_exit_e) {
- entry = &global.setting->exit;
- }
-
- // When a custom define is specified, it needs to be exported into the environment.
- if (entry->define.used || process->rule.define.used) {
-
- // Copy all environment variables over when a custom define is used.
- status = f_environment_get_all(&environment);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_environment_get_all", F_true);
-
- return status;
- }
-
- for (i = 0; i < entry->define.used; ++i) {
-
- status = f_string_maps_append(entry->define.array[i], &environment);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_maps_append", F_true);
-
- return status;
- }
- } // for
-
- for (i = 0; i < process->rule.define.used; ++i) {
-
- status = f_string_maps_append(process->rule.define.array[i], &environment);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_maps_append", F_true);
-
- return status;
- }
- } // for
- }
- else {
-
- // When no custom environment variables are defined, just let the original environment pass through.
- execute_set.parameter.environment = 0;
- }
- }
-
- for (i = 0; i < process->rule.items.used && controller_thread_is_enabled_process(process, global.thread); ++i) {
-
- if (process->rule.items.array[i].type == controller_rule_item_type_settings_e) continue;
-
- for (j = 0; j < process->rule.items.array[i].actions.used; ++j) {
-
- if (!controller_thread_is_enabled_process(process, global.thread)) {
- status = F_status_set_error(F_interrupt);
-
- break;
- }
-
- if (process->rule.items.array[i].actions.array[j].type != action) continue;
-
- execute_set.parameter.data = 0;
- execute_set.parameter.option = FL_execute_parameter_option_threadsafe_d | FL_execute_parameter_option_return_d;
-
- if (process->rule.items.array[i].with & controller_with_full_path_d) {
- execute_set.parameter.option |= FL_execute_parameter_option_path_d;
- }
-
- if (process->rule.items.array[i].with & controller_with_session_new_d) {
- execute_set.parameter.option |= FL_execute_parameter_option_session_d;
- }
-
- if (process->rule.items.array[i].type == controller_rule_item_type_command_e) {
- status = controller_rule_expand(global, process->rule.items.array[i].actions.array[j], process);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, process->cache.action, F_status_set_fine(status), "controller_rule_expand", F_true, F_false);
-
- break;
- }
-
- do {
- status = controller_rule_execute_foreground(process->rule.items.array[i].type, f_string_empty_s, process->cache.expanded, options, &execute_set, process);
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break;
- if (F_status_is_error(status) && F_status_set_fine(status) != F_failure) break;
-
- } while (controller_rule_execute_rerun(controller_rule_action_type_to_action_execute_type(action), process, &process->rule.items.array[i]) > 0);
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break;
-
- if (F_status_is_error(status)) {
- process->rule.items.array[i].actions.array[j].status = F_status_set_error(F_failure);
-
- if (!(options & controller_process_option_simulate_d)) break;
-
- success = F_status_set_error(F_failure);
- }
- else if (success == F_false || success == F_ignore) {
- success = F_true;
- }
- }
- else if (process->rule.items.array[i].type == controller_rule_item_type_script_e) {
- status = controller_rule_expand(global, process->rule.items.array[i].actions.array[j], process);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, process->cache.action, F_status_set_fine(status), "controller_rule_expand", F_true, F_false);
-
- break;
- }
-
- if (process->cache.expanded.used) {
- execute_set.parameter.data = &process->cache.expanded.array[0];
- }
- else {
- execute_set.parameter.data = 0;
- }
-
- do {
- if (process->rule.engine.used) {
- status = controller_rule_execute_foreground(process->rule.items.array[i].type, process->rule.engine, process->rule.engine_arguments, options, &execute_set, process);
- }
- else {
- status = controller_rule_execute_foreground(process->rule.items.array[i].type, *global.main->setting.default_engine, process->rule.engine_arguments, options, &execute_set, process);
- }
-
- if (status == F_child || F_status_set_fine(status) == F_lock) break;
- if (F_status_is_error(status) && F_status_set_fine(status) != F_failure) break;
-
- } while (controller_rule_execute_rerun(controller_rule_action_type_to_action_execute_type(action), process, &process->rule.items.array[i]) > 0);
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break;
-
- if (F_status_is_error(status)) {
- process->rule.items.array[i].actions.array[j].status = F_status_set_error(F_failure);
-
- if (!(options & controller_process_option_simulate_d)) break;
-
- success = F_status_set_error(F_failure);
- }
- else if (success == F_false || success == F_ignore) {
- success = F_true;
- }
- }
- else if (process->rule.items.array[i].type == controller_rule_item_type_service_e) {
- status = controller_rule_expand(global, process->rule.items.array[i].actions.array[j], process);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, process->cache.action, F_status_set_fine(status), "controller_rule_expand", F_true, F_false);
-
- break;
- }
-
- if (process->rule.items.array[i].pid_file.used) {
- do {
- status = controller_rule_execute_pid_with(process->rule.items.array[i].pid_file, process->rule.items.array[i].type, f_string_empty_s, process->cache.expanded, options, process->rule.items.array[i].with, &execute_set, process);
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break;
- if (F_status_is_error(status) && F_status_set_fine(status) != F_failure) break;
-
- } while (controller_rule_execute_rerun(controller_rule_action_type_to_action_execute_type(action), process, &process->rule.items.array[i]) > 0);
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break;
-
- if (F_status_is_error(status)) {
- process->rule.items.array[i].actions.array[j].status = F_status_set_error(F_failure);
-
- if (!(options & controller_process_option_simulate_d)) break;
-
- success = F_status_set_error(F_failure);
- }
- else if (success == F_false || success == F_ignore) {
- success = F_true;
- }
- }
- else {
- success = F_status_set_error(F_failure);
-
- controller_rule_action_print_error_missing_pid(&global.main->program.error, process->rule.alias);
- }
- }
- else if (process->rule.items.array[i].type == controller_rule_item_type_utility_e) {
- if (process->rule.items.array[i].pid_file.used) {
- status = controller_rule_expand(global, process->rule.items.array[i].actions.array[j], process);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, process->cache.action, F_status_set_fine(status), "controller_rule_expand", F_true, F_false);
-
- break;
- }
-
- if (process->cache.expanded.used) {
- execute_set.parameter.data = &process->cache.expanded.array[0];
- }
- else {
- execute_set.parameter.data = 0;
- }
-
- do {
- status = controller_rule_execute_pid_with(process->rule.items.array[i].pid_file, process->rule.items.array[i].type, process->rule.engine.used ? process->rule.engine : *global.main->setting.default_engine, process->rule.engine_arguments, options, process->rule.items.array[i].with, &execute_set, process);
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break;
- if (F_status_is_error(status) && F_status_set_fine(status) != F_failure) break;
-
- } while (controller_rule_execute_rerun(controller_rule_action_type_to_action_execute_type(action), process, &process->rule.items.array[i]) > 0);
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) break;
-
- if (F_status_is_error(status)) {
- process->rule.items.array[i].actions.array[j].status = F_status_set_error(F_failure);
-
- if (!(options & controller_process_option_simulate_d)) break;
-
- success = F_status_set_error(F_failure);
- }
- else if (success == F_false || success == F_ignore) {
- success = F_true;
- }
- }
- else {
- success = F_status_set_error(F_failure);
-
- controller_rule_action_print_error_missing_pid(&global.main->program.error, process->rule.alias);
- }
- }
- else {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- fl_print_format("%r%[%QAction type is unknown, ignoring.%]%r", global.main->program.warning.to, f_string_eol_s, global.main->program.warning.context, global.main->program.warning.prefix, global.main->program.warning.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.warning, process->cache.action, F_true);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
-
- if (success == F_false) {
- success = F_ignore;
- }
-
- continue;
- }
- } // for
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_is_error(status) && !(options & controller_process_option_simulate_d)) {
- break;
- }
- } // for
-
- f_memory_arrays_resize(0, sizeof(f_string_map_t), (void **) &environment.array, &environment.used, &environment.size, &f_string_maps_delete_callback);
-
- // Lock failed, attempt to re-establish lock before returning.
- if (F_status_set_fine(status) == F_lock) {
- status = controller_lock_read(process, global.thread, &process->lock);
- if (F_status_is_error(status)) return F_status_set_error(F_lock);
-
- success = F_false;
- }
-
- if (!controller_thread_is_enabled_process(process, global.thread)) {
- return F_status_set_error(F_interrupt);
- }
-
- if (status == F_child || F_status_is_error(status)) {
- return status;
- }
-
- if (success == F_false || success == F_failure) {
- return F_status_set_error(F_failure);
- }
-
- if (success == F_ignore) {
- return F_ignore;
- }
-
- return F_okay;
- }
-#endif // _di_controller_rule_execute_
-
-#ifndef _di_controller_rule_execute_foreground_
- f_status_t controller_rule_execute_foreground(const uint8_t type, const f_string_static_t program, const f_string_statics_t arguments, const uint8_t options, controller_execute_set_t * const execute_set, controller_data_t * const process) {
-
- f_status_t status = F_okay;
- f_status_t status_lock = F_okay;
-
- controller_main_t * const main = (controller_main_t *) process->main_data;
- controller_thread_t * const thread = (controller_thread_t *) process->main_thread;
-
- f_execute_result_t result = f_execute_result_t_initialize;
-
- status = controller_pids_increase(&process->childs);
-
- if (F_status_is_error(status)) {
- controller_print_error(thread, &main->program.error, F_status_set_fine(status), "controller_pids_increase", F_true);
-
- return status;
- }
-
- pid_t *child = 0;
-
- {
- f_number_unsigned_t i = 0;
-
- while (i < process->childs.used && process->childs.array[i]) {
- ++i;
- } // while
-
- child = &process->childs.array[i];
-
- if (i == process->childs.used) {
- ++process->childs.used;
- }
- }
-
- if (options & controller_process_option_simulate_d) {
- if (main->program.output.verbosity != f_console_verbosity_quiet_e) {
- controller_lock_print(main->program.output.to, thread);
-
- fl_print_format("%rSimulating execution of '%[", main->program.output.to, f_string_eol_s, main->program.context.set.title);
-
- if (program.used) {
- f_print_dynamic_safely(program, main->program.output.to);
- }
- else {
- f_print_dynamic_safely(arguments.array[0], main->program.output.to);
- }
-
- fl_print_format("%]' with the arguments: '%[", main->program.output.to, main->program.context.set.title, main->program.context.set.important);
-
- for (f_number_unsigned_t i = program.used ? 0 : 1; i < arguments.used; ++i) {
-
- if (program.used && i || !program.used && i > 1) {
- f_print_dynamic_raw(f_string_space_s, main->program.output.to);
- }
-
- f_print_dynamic_safely(arguments.array[i], main->program.output.to);
- } // for
-
- fl_print_format("%]' from '", main->program.output.to, main->program.context.set.important);
- fl_print_format("%[%Q%]'.%r", main->program.output.to, main->program.context.set.notable, process->rule.name, main->program.context.set.notable, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.output.to, thread);
- }
-
- // Sleep for less than a second to better show simulation of synchronous vs asynchronous.
- {
- const f_time_spec_t delay = controller_time_milliseconds(controller_thread_simulation_timeout_d);
-
- if (controller_time_sleep_nanoseconds(main, (controller_process_t *) process->main_setting, delay) == -1) {
- status = F_status_set_error(F_interrupt);
- }
- }
-
- if (F_status_set_fine(status) != F_interrupt) {
- fl_execute_parameter_t simulated_parameter = macro_fl_execute_parameter_t_initialize_1(execute_set->parameter.option, execute_set->parameter.wait, process->rule.has & controller_rule_has_environment_d ? execute_set->parameter.environment : 0, execute_set->parameter.signals, &f_string_empty_s);
-
- status = fll_execute_program(*main->setting.default_engine, process->rule.engine_arguments, &simulated_parameter, &execute_set->as, (void *) &result);
- }
- }
- else {
- status = fll_execute_program(program, arguments, &execute_set->parameter, &execute_set->as, (void *) &result);
- }
-
- if (status == F_parent) {
- const pid_t id_child = result.pid;
- result.status = 0;
-
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_write_process(process, thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&main->program.error, F_status_set_fine(status_lock), F_false, thread);
-
- if (F_status_set_fine(status_lock) != F_interrupt) {
- status = controller_lock_read_process(process, thread, &process->lock);
-
- if (status == F_okay) {
- return status_lock;
- }
- }
-
- return F_status_set_error(F_lock);
- }
-
- // Assign the child process id to allow for the cancel process to send appropriate termination signals to the child process.
- *child = id_child;
-
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_read_process(process, thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&main->program.error, F_status_set_fine(status_lock), F_true, thread);
- }
-
- if (F_status_set_fine(status_lock) != F_interrupt) {
-
- // Have the parent wait for the child process to finish.
- waitpid(id_child, &result.status, 0);
- }
-
- if (F_status_set_fine(status_lock) == F_interrupt || !controller_thread_is_enabled_process(process, thread)) {
- if (status_lock == F_okay) {
- return F_status_set_error(F_interrupt);
- }
-
- return F_status_set_error(F_lock);
- }
-
- if (status_lock == F_okay) {
- f_thread_unlock(&process->lock);
- }
-
- status_lock = controller_lock_write_process(process, thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&main->program.error, F_status_set_fine(status_lock), F_false, thread);
-
- if (F_status_set_fine(status_lock) != F_interrupt) {
- status = controller_lock_read_process(process, thread, &process->lock);
-
- if (status == F_okay) {
- return status_lock;
- }
- }
-
- return F_status_set_error(F_lock);
- }
-
- process->result = result.status;
-
- // Remove the pid now that waidpid() has returned.
- *child = 0;
-
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_read_process(process, thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&main->program.error, F_status_set_fine(status_lock), F_true, thread);
-
- return F_status_set_error(F_lock);
- }
-
- if (WIFEXITED(result.status) ? WEXITSTATUS(result.status) : 0) {
- status = F_status_set_error(F_failure);
- }
- else {
- status = F_okay;
- }
- }
- else {
- main->program.child = result.status;
-
- if (!controller_thread_is_enabled_process(process, thread)) {
- return F_status_set_error(F_interrupt);
- }
- }
-
- if (F_status_is_error(status)) {
- status = F_status_set_fine(status);
-
- if (status == F_child || status == F_capability || status == F_group || status == F_nice || status == F_user) {
- status = F_child;
- }
- else {
- status = F_status_set_error(status);
- }
- }
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt) {
- return status;
- }
-
- if (F_status_is_error(status)) {
- status = F_status_set_fine(status);
-
- if ((WIFEXITED(process->result) && WEXITSTATUS(process->result)) || status == F_control_group || status == F_failure || status == F_limit || status == F_processor || status == F_schedule) {
- controller_rule_item_print_error_execute(type == controller_rule_item_type_script_e, program.used ? program : arguments.array[0], status, process);
- }
- else {
- controller_print_error(thread, &main->program.error, F_status_set_fine(status), "fll_execute_program", F_true);
- }
-
- status = F_status_set_error(status);
- }
-
- return status;
- }
-#endif // _di_controller_rule_execute_foreground_
-
-#ifndef _di_controller_rule_execute_pid_with_
- f_status_t controller_rule_execute_pid_with(const f_string_dynamic_t pid_file, const uint8_t type, const f_string_static_t program, const f_string_statics_t arguments, const uint8_t options, const uint8_t with, controller_execute_set_t * const execute_set, controller_data_t * const process) {
-
- f_status_t status = F_okay;
- f_status_t status_lock = F_okay;
-
- controller_main_t * const main = (controller_main_t *) process->main_data;
- controller_thread_t * const thread = (controller_thread_t *) process->main_thread;
-
- f_execute_result_t result = f_execute_result_t_initialize;
-
- status = controller_pids_increase(&process->childs);
-
- if (F_status_is_error(status)) {
- controller_print_error(thread, &main->program.error, F_status_set_fine(status), "controller_pids_increase", F_true);
-
- return status;
- }
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_string_dynamic_t), (void **) &process->path_pids.array, &process->path_pids.used, &process->path_pids.size);
-
- if (F_status_is_error(status)) {
- controller_print_error(thread, &main->program.error, F_status_set_fine(status), "f_memory_array_increase", F_true);
-
- return status;
- }
-
- pid_t *child = 0;
- f_string_dynamic_t *child_pid_file = 0;
-
- {
- f_number_unsigned_t i = 0;
-
- while (i < process->childs.used && process->childs.array[i]) {
- ++i;
- } // while
-
- child = &process->childs.array[i];
-
- if (i == process->childs.used) {
- ++process->childs.used;
- }
-
- i = 0;
-
- while (i < process->path_pids.used && process->path_pids.array[i].used) {
- ++i;
- } // while
-
- child_pid_file = &process->path_pids.array[i];
-
- if (i == process->path_pids.used) {
- ++process->path_pids.used;
- }
- }
-
- status = f_file_exists(pid_file, F_true);
-
- if (F_status_is_error(status)) {
- controller_print_error_file(thread, &main->program.error, F_status_set_fine(status), "f_file_exists", F_true, pid_file, f_file_operation_find_s, fll_error_file_type_file_e);
-
- return status;
- }
-
- if (status == F_true) {
- controller_print_error_file(thread, &main->program.error, F_file_found, "f_file_exists", F_true, pid_file, f_file_operation_find_s, fll_error_file_type_file_e);
-
- return F_status_set_error(F_file_found);
- }
-
- status = f_string_dynamic_append_nulless(pid_file, child_pid_file);
-
- if (F_status_is_error(status)) {
- controller_print_error(thread, &main->program.error, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true);
-
- return status;
- }
-
- if (options & controller_process_option_simulate_d) {
- if (main->program.error.verbosity > f_console_verbosity_error_e) {
- controller_lock_print(main->program.error.to, thread);
-
- fl_print_format("%rSimulating execution of '%[", main->program.error.to, f_string_eol_s, main->program.context.set.title);
-
- if (program.used) {
- f_print_dynamic_safely(program, main->program.error.to);
- }
- else {
- f_print_dynamic_safely(arguments.array[0], main->program.error.to);
- }
-
- fl_print_format("%]' with the arguments: '%[", main->program.error.to, main->program.context.set.title, main->program.context.set.important);
-
- for (f_number_unsigned_t i = program.used ? 0 : 1; i < arguments.used; ++i) {
-
- if (program.used && i || !program.used && i > 1) {
- f_print_dynamic_raw(f_string_space_s, main->program.error.to);
- }
-
- f_print_dynamic_safely(arguments.array[i], main->program.error.to);
- } // for
-
- fl_print_format("%]' from '", main->program.error.to, main->program.context.set.important);
- fl_print_format("%[%Q%]'.%r", main->program.error.to, main->program.context.set.notable, process->rule.name, main->program.context.set.notable, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.error.to, thread);
- }
-
- // Sleep for less than a second to better show simulation of synchronous vs asynchronous.
- {
- const f_time_spec_t delay = controller_time_milliseconds(controller_thread_simulation_timeout_d);
-
- if (controller_time_sleep_nanoseconds(main, (controller_process_t *) process->main_setting, delay) == -1) {
- status = F_status_set_error(F_interrupt);
- }
- }
-
- if (F_status_set_fine(status) != F_interrupt) {
- const f_string_statics_t simulated_arguments = f_string_statics_t_initialize;
- fl_execute_parameter_t simulated_parameter = macro_fl_execute_parameter_t_initialize_1(execute_set->parameter.option, execute_set->parameter.wait, process->rule.has & controller_rule_has_environment_d ? execute_set->parameter.environment : 0, execute_set->parameter.signals, &f_string_empty_s);
-
- status = fll_execute_program(*main->setting.default_engine, simulated_arguments, &simulated_parameter, &execute_set->as, (void *) &result);
- }
- }
- else {
- status = fll_execute_program(program, arguments, &execute_set->parameter, &execute_set->as, (void *) &result);
- }
-
- if (status == F_parent) {
- const pid_t id_child = result.pid;
- result.status = 0;
-
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_write_process(process, thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&main->program.error, F_status_set_fine(status_lock), F_false, thread);
-
- if (F_status_set_fine(status_lock) != F_interrupt) {
- status = controller_lock_read_process(process, thread, &process->lock);
-
- if (status == F_okay) {
- return status_lock;
- }
- }
-
- return F_status_set_error(F_lock);
- }
-
- // Assign the child process id to allow for the cancel process to send appropriate termination signals to the child process.
- *child = id_child;
-
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_read_process(process, thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&main->program.error, F_status_set_fine(status_lock), F_true, thread);
- }
-
- if (F_status_set_fine(status_lock) != F_interrupt) {
-
- // The child process should perform the change into background, therefore it is safe to wait for the child to exit (another process is spawned).
- waitpid(id_child, &result.status, 0);
- }
-
- if (!controller_thread_is_enabled_process(process, thread)) {
- if (status_lock == F_okay) {
- return F_status_set_error(F_interrupt);
- }
-
- return F_status_set_error(F_lock);
- }
-
- if (status_lock == F_okay) {
- f_thread_unlock(&process->lock);
- }
-
- status_lock = controller_lock_write_process(process, thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&main->program.error, F_status_set_fine(status_lock), F_false, thread);
-
- if (F_status_set_fine(status_lock) != F_interrupt) {
- status = controller_lock_read_process(process, thread, &process->lock);
-
- if (status == F_okay) {
- return status_lock;
- }
- }
-
- return F_status_set_error(F_lock);
- }
-
- process->result = result.status;
-
- // Remove the pid now that waidpid() has returned.
- *child = 0;
-
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_read_process(process, thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&main->program.error, F_status_set_fine(status_lock), F_true, thread);
-
- return F_status_set_error(F_lock);
- }
-
- if (WIFEXITED(result.status) ? WEXITSTATUS(result.status) : 0) {
- status = F_status_set_error(F_failure);
- }
- else {
- status = F_okay;
- }
- }
- else {
- main->program.child = result.status;
-
- if (!controller_thread_is_enabled_process(process, thread)) {
- return F_status_set_error(F_interrupt);
- }
- }
-
- if (F_status_is_error(status)) {
- status = F_status_set_fine(status);
-
- if (status == F_child || status == F_capability || status == F_group || status == F_nice || status == F_user) {
- status = F_child;
- }
- else {
- status = F_status_set_error(status);
- }
- }
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt) {
- return status;
- }
-
- if (F_status_is_error(status)) {
- status = F_status_set_fine(status);
-
- if ((WIFEXITED(process->result) && WEXITSTATUS(process->result)) || status == F_control_group || status == F_failure || status == F_limit || status == F_processor || status == F_schedule) {
- controller_rule_item_print_error_execute(type == controller_rule_item_type_utility_e, program.used ? program : arguments.array[0], status, process);
- }
- else {
- controller_print_error(thread, &main->program.error, F_status_set_fine(status), "fll_execute_program", F_true);
- }
-
- return F_status_set_error(status);
- }
-
- return status;
- }
-#endif // _di_controller_rule_execute_pid_with_
-
-#ifndef _di_controller_rule_execute_rerun_
- int8_t controller_rule_execute_rerun(const uint8_t action, controller_data_t * const process, controller_rule_item_t * const item) {
-
- const int result = WIFEXITED(process->result) ? WEXITSTATUS(process->result) : 0;
-
- if (item->reruns[action].is & (result ? controller_rule_rerun_is_failure_d : controller_rule_rerun_is_success_d)) {
- controller_main_t * const main = (controller_main_t *) process->main_data;
- controller_thread_t * const thread = (controller_thread_t *) process->main_thread;
- controller_rule_rerun_item_t *rerun_item = result ? &item->reruns[action].failure : &item->reruns[action].success;
-
- if (!controller_thread_is_enabled_process(process, thread)) return -2;
-
- if (!rerun_item->max || rerun_item->count < rerun_item->max) {
- if (main->program.error.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(main->program.output.to, thread);
-
- fl_print_format("%rRe-running '", main->program.output.to, f_string_eol_s);
- fl_print_format("%[%r%]' '", main->program.output.to, main->program.context.set.title, process->rule.alias, main->program.context.set.title);
- fl_print_format("%[%r%]' with a ", main->program.output.to, main->program.context.set.notable, controller_rule_action_execute_type_name(action), main->program.context.set.notable);
- fl_print_format("%[%r%] of ", main->program.output.to, main->program.context.set.notable, controller_delay_s, main->program.context.set.notable);
- fl_print_format("%[%ul%] MegaTime", main->program.output.to, main->program.context.set.notable, rerun_item->delay, main->program.context.set.notable);
-
- if (rerun_item->max) {
- fl_print_format(" for %[%ul%]", main->program.output.to, main->program.context.set.notable, rerun_item->count, main->program.context.set.notable);
- fl_print_format(" of %[%r%] ", main->program.output.to, main->program.context.set.notable, controller_max_s, main->program.context.set.notable);
- fl_print_format(f_string_format_un_single_s.string, main->program.output.to, main->program.context.set.notable, rerun_item->max, main->program.context.set.notable);
- fl_print_format(".%r", main->program.output.to, f_string_eol_s);
- }
- else {
- fl_print_format(" with no %[%r%].%r", main->program.output.to, main->program.context.set.notable, controller_max_s, main->program.context.set.notable, f_string_eol_s);
- }
-
- controller_unlock_print_flush(main->program.output.to, thread);
- }
-
- if (rerun_item->delay) {
- const f_time_spec_t delay = controller_time_milliseconds(rerun_item->delay);
-
- if (controller_time_sleep_nanoseconds(main, (controller_process_t *) process->main_setting, delay) == -1) {
- return -1;
- }
-
- if (!controller_thread_is_enabled_process(process, thread)) return -2;
- }
-
- if (item->reruns[action].is & (result ? controller_rule_rerun_is_failure_reset_d : controller_rule_rerun_is_success_reset_d)) {
- if (result) {
- item->reruns[action].success.count = 0;
- }
- else {
- item->reruns[action].failure.count = 0;
- }
- }
-
- if (rerun_item->max) {
- ++rerun_item->count;
- }
-
- return F_true;
- }
- }
-
- return F_false;
- }
-#endif // _di_controller_rule_execute_rerun_
-
-#ifndef _di_controller_rule_expand_
- f_status_t controller_rule_expand(const controller_global_t global, const controller_rule_action_t action, controller_data_t * const process) {
-
- process->cache.expanded.used = 0;
-
- if (!action.parameters.used) {
- return F_okay;
- }
-
- f_status_t status = f_memory_array_increase_by(action.parameters.used, sizeof(f_string_dynamic_t), (void **) &process->cache.expanded.array, &process->cache.expanded.used, &process->cache.expanded.size);
- if (F_status_is_error(status)) return status;
-
- f_number_unsigned_t i = 0;
- f_number_unsigned_t first = 0;
- f_range_t range = f_range_t_initialize;
-
- f_iki_data_t *iki_data = 0;
- f_string_dynamic_t *buffer = 0;
-
- for (; process->cache.expanded.used < action.parameters.used; ++process->cache.expanded.used) {
-
- buffer = &process->cache.expanded.array[process->cache.expanded.used];
- buffer->used = 0;
-
- if (action.ikis.array[process->cache.expanded.used].variable.used) {
- iki_data = &action.ikis.array[process->cache.expanded.used];
-
- // Allocate enough room plus an extra buffer to help reduce reallocations.
- status = f_memory_array_increase_by(action.parameters.array[process->cache.expanded.used].used + controller_common_allocation_large_d, sizeof(f_char_t), (void **) &buffer->string, &buffer->used, &buffer->size);
-
- // Apply the IKI delimits.
- for (i = 0; i < iki_data->delimits.used; ++i) {
- action.parameters.array[process->cache.expanded.used].string[iki_data->delimits.array[i]] = f_iki_syntax_placeholder_s.string[0];
- } // for
-
- if (iki_data->variable.used) {
- for (i = 0, first = 0; i < iki_data->variable.used; ++i) {
-
- // Copy everything up to the start of the IKI variable.
- if (first < iki_data->variable.array[i].start) {
- range.start = first;
- range.stop = iki_data->variable.array[i].start - 1;
-
- status = f_string_dynamic_partial_append_nulless(action.parameters.array[process->cache.expanded.used], range, buffer);
- if (F_status_is_error(status)) break;
- }
-
- status = controller_rule_expand_iki(process, action.parameters.array[process->cache.expanded.used], iki_data->vocabulary.array[i], iki_data->content.array[i], buffer);
- if (F_status_is_error(status)) break;
-
- first = iki_data->variable.array[i].stop + 1;
- } // for
-
- if (F_status_is_error(status)) break;
-
- // Copy everything after the last IKI variable to the end of the content.
- if (first < action.parameters.array[process->cache.expanded.used].used) {
- range.start = first;
- range.stop = action.parameters.array[process->cache.expanded.used].used - 1;
-
- status = f_string_dynamic_partial_append(action.parameters.array[process->cache.expanded.used], range, buffer);
- }
- }
- else {
- status = f_string_dynamic_append_nulless(action.parameters.array[process->cache.expanded.used], buffer);
- }
-
- // Unapply the IKI delimits.
- for (i = 0; i < iki_data->delimits.used; ++i) {
- action.parameters.array[process->cache.expanded.used].string[iki_data->delimits.array[i]] = f_iki_syntax_slash_s.string[0];
- } // for
- }
- else {
- status = f_string_dynamic_append(action.parameters.array[process->cache.expanded.used], buffer);
- }
-
- if (F_status_is_error(status)) return status;
- } // for
-
- return F_okay;
- }
-#endif // _di_controller_rule_expand_
-
-#ifndef _di_controller_rule_expand_iki_
- f_status_t controller_rule_expand_iki(controller_data_t * const process, const f_string_static_t source, const f_range_t vocabulary, const f_range_t content, f_string_dynamic_t * const destination) {
-
- if (vocabulary.start > vocabulary.stop) return F_okay;
- if (content.start > content.stop) return F_okay;
-
- f_status_t status = F_okay;
-
- if (f_compare_dynamic_partial_string(controller_define_s.string, source, controller_define_s.used, vocabulary) == F_equal_to) {
- f_number_unsigned_t i = 0;
-
- // First check to see if the environment variable is overwritten by a "define".
- for (; i < process->rule.define.used; ++i) {
-
- if (f_compare_dynamic_partial_string(process->rule.define.array[i].key.string, source, process->rule.define.array[i].key.used, content) == F_equal_to) {
- status = f_string_dynamic_append(process->rule.define.array[i].value, destination);
- if (F_status_is_error(status)) return status;
-
- break;
- }
- } // for
-
- if (i == process->rule.define.used) {
- controller_entry_t * const entry = process->type == controller_data_type_entry_e ? &((controller_process_t *) process->main_setting)->entry : &((controller_process_t *) process->main_setting)->exit;
-
- for (i = 0; i < entry->define.used; ++i) {
-
- if (f_compare_dynamic_partial_string(entry->define.array[i].key.string, source, entry->define.array[i].key.used, content) == F_equal_to) {
- status = f_string_dynamic_append(entry->define.array[i].value, destination);
- if (F_status_is_error(status)) return status;
-
- break;
- }
- } // for
-
- if (i == entry->define.used) {
- i = process->rule.define.used;
- }
- }
-
- if (i == process->rule.define.used) {
- f_string_static_t buffer = f_string_static_t_initialize;
- buffer.used = (content.stop - content.start) + 1;
-
- f_char_t buffer_string[buffer.used + 1];
-
- memcpy(buffer_string, source.string + content.start, sizeof(f_char_t) * buffer.used);
- buffer_string[buffer.used] = 0;
- buffer.string = buffer_string;
- process->cache.action.generic.used = 0;
-
- status = f_environment_get(buffer, &process->cache.action.generic);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_append(process->cache.action.generic, destination);
- if (F_status_is_error(status)) return status;
- }
- }
- else if (f_compare_dynamic_partial_string(controller_parameter_s.string, source, controller_parameter_s.used, vocabulary) == F_equal_to) {
- f_number_unsigned_t i = 0;
-
- for (; i < process->rule.parameter.used; ++i) {
-
- if (f_compare_dynamic_partial_string(process->rule.parameter.array[i].key.string, source, process->rule.parameter.array[i].key.used, content) == F_equal_to) {
- status = f_string_dynamic_append(process->rule.parameter.array[i].value, destination);
- if (F_status_is_error(status)) return status;
-
- break;
- }
- } // for
-
- if (i == process->rule.parameter.used) {
- controller_entry_t * const entry = process->type == controller_data_type_entry_e ? &((controller_process_t *) process->main_setting)->entry : &((controller_process_t *) process->main_setting)->exit;
-
- for (i = 0; i < entry->parameter.used; ++i) {
-
- if (f_compare_dynamic_partial_string(entry->parameter.array[i].key.string, source, entry->parameter.array[i].key.used, content) == F_equal_to) {
- status = f_string_dynamic_append(entry->parameter.array[i].value, destination);
- if (F_status_is_error(status)) return status;
-
- break;
- }
- } // for
- }
- }
- else if (f_compare_dynamic_partial_string(controller_program_s.string, source, controller_program_s.used, vocabulary) == F_equal_to) {
- f_string_static_t * const argv = ((controller_main_t *) process->main_data)->program.parameters.arguments.array;
- f_console_parameters_t * const parameters = &((controller_main_t *) process->main_data)->program.parameters;
-
- const f_string_static_t options[] = {
- f_console_standard_long_light_s,
- f_console_standard_long_dark_s,
- f_console_standard_long_no_color_s,
- f_console_standard_long_quiet_s,
- f_console_standard_long_normal_s,
- f_console_standard_long_verbose_s,
- f_console_standard_long_debug_s,
- controller_long_init_s,
- controller_long_interruptible_s,
- controller_long_daemon_s,
- controller_long_simulate_s,
- controller_long_uninterruptible_s,
- controller_long_validate_s,
-
- // Option and Value.
- controller_long_cgroup_s,
- controller_long_pid_s,
- controller_long_settings_s,
- controller_long_socket_s,
- };
-
- const f_string_static_t symbols[] = {
- f_console_symbol_short_inverse_s, // light.
- f_console_symbol_short_inverse_s, // dark.
- f_console_symbol_short_inverse_s, // no_color.
- f_console_symbol_short_inverse_s, // quiet.
- f_console_symbol_short_inverse_s, // normal.
- f_console_symbol_short_inverse_s, // verbose.
- f_console_symbol_short_inverse_s, // debug.
- f_console_symbol_short_normal_s, // daemon.
- f_console_symbol_short_normal_s, // init.
- f_console_symbol_short_normal_s, // interruptible.
- f_console_symbol_short_normal_s, // simulate.
- f_console_symbol_short_normal_s, // uninterruptible.
- f_console_symbol_short_normal_s, // validate.
-
- // Option and Value.
- f_console_symbol_short_normal_s, // cgroup.
- f_console_symbol_short_normal_s, // pid.
- f_console_symbol_short_normal_s, // settings.
- f_console_symbol_short_normal_s, // socket.
- };
-
- const f_string_static_t expands[] = {
- f_console_standard_short_light_s,
- f_console_standard_short_dark_s,
- f_console_standard_short_no_color_s,
- f_console_standard_short_quiet_s,
- f_console_standard_short_normal_s,
- f_console_standard_short_verbose_s,
- f_console_standard_short_debug_s,
- controller_short_init_s,
- controller_short_interruptible_s,
- controller_short_daemon_s,
- controller_short_simulate_s,
- controller_short_uninterruptible_s,
- controller_short_validate_s,
-
- // Option and Value.
- controller_short_cgroup_s,
- controller_short_pid_s,
- controller_short_settings_s,
- controller_short_socket_s,
- };
-
- const uint8_t codes[] = {
- f_console_standard_parameter_help_e,
- f_console_standard_parameter_dark_e,
- f_console_standard_parameter_no_color_e,
- f_console_standard_parameter_verbosity_quiet_e,
- f_console_standard_parameter_verbosity_normal_e,
- f_console_standard_parameter_verbosity_verbose_e,
- f_console_standard_parameter_verbosity_debug_e,
- controller_parameter_init_e,
- controller_parameter_interruptible_e,
- controller_parameter_daemon_e,
- controller_parameter_simulate_e,
- controller_parameter_uninterruptible_e,
- controller_parameter_validate_e,
-
- // Option and Value.
- controller_parameter_cgroup_e,
- controller_parameter_pid_e,
- controller_parameter_settings_e,
- controller_parameter_socket_e,
- };
-
- // F_false = only with option, F_true with option and value.
- const bool values[] = {
- F_false, // light.
- F_false, // dark.
- F_false, // no_color.
- F_false, // quiet.
- F_false, // normal.
- F_false, // verbose.
- F_false, // debug.
- F_false, // daemon.
- F_false, // init.
- F_false, // interruptible.
- F_false, // simulate.
- F_false, // uninterruptible.
- F_false, // validate.
-
- // Option and Value.
- F_true, // cgroup.
- F_true, // pid.
- F_true, // settings.
- F_true, // socket.
- };
-
- for (f_number_unsigned_t i = 0; i < 17; ++i) {
-
- if (f_compare_dynamic_partial_string(options[i].string, source, options[i].used, content) == F_equal_to) {
- if (values[i]) {
- if (parameters->array[codes[i]].result & f_console_result_value_e) {
- const f_number_unsigned_t index = parameters->array[codes[i]].values.array[parameters->array[codes[i]].values.used - 1];
-
- status = f_memory_array_increase_by(symbols[i].used + expands[i].used + f_string_ascii_space_s.used + argv[index].used + 1, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_append(symbols[i], destination);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_append(expands[i], destination);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_append(f_string_ascii_space_s, destination);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_append(argv[index], destination);
- if (F_status_is_error(status)) return status;
- }
- }
- else {
- if (parameters->array[codes[i]].result & f_console_result_found_e) {
- status = f_memory_array_increase_by(symbols[i].used + expands[i].used + 1, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_append(symbols[i], destination);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_append(expands[i], destination);
- if (F_status_is_error(status)) return status;
- }
- }
-
- break;
- }
-
- {
- f_string_static_t buffer = f_string_static_t_initialize;
- buffer.used = options[i].used + controller_parameter_map_option_s.used;
-
- f_char_t buffer_string[buffer.used];
- buffer.string = buffer_string;
-
- memcpy(buffer_string, options[i].string, sizeof(f_char_t) * options[i].used);
- memcpy(buffer_string + options[i].used, controller_parameter_map_option_s.string, sizeof(f_char_t) * controller_parameter_map_option_s.used);
-
- if (f_compare_dynamic_partial_string(buffer.string, source, buffer.used, content) == F_equal_to) {
- if (values[i] && parameters->array[codes[i]].result & f_console_result_value_e || !values[i] && (parameters->array[codes[i]].result & f_console_result_found_e)) {
- status = f_memory_array_increase_by(symbols[i].used + expands[i].used + 1, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_append(symbols[i], destination);
- if (F_status_is_error(status)) return status;
-
- status = f_string_dynamic_append(expands[i], destination);
- if (F_status_is_error(status)) return status;
- }
-
- break;
- }
- }
-
- if (values[i]) {
- f_string_static_t buffer = f_string_static_t_initialize;
- buffer.used = options[i].used + controller_parameter_map_value_s.used;
-
- f_char_t buffer_string[buffer.used];
- buffer.string = buffer_string;
-
- memcpy(buffer_string, options[i].string, sizeof(f_char_t) * options[i].used);
- memcpy(buffer_string + options[i].used, controller_parameter_map_value_s.string, sizeof(f_char_t) * controller_parameter_map_value_s.used);
-
- if (f_compare_dynamic_partial_string(buffer.string, source, buffer.used, content) == F_equal_to) {
- if (parameters->array[codes[i]].result & f_console_result_value_e) {
- const f_number_unsigned_t index = parameters->array[codes[i]].values.array[parameters->array[codes[i]].values.used - 1];
-
- status = f_string_dynamic_append(argv[index], destination);
- if (F_status_is_error(status)) return status;
- }
-
- break;
- }
- }
- } // for
- }
-
- return F_okay;
- }
-#endif // _di_controller_rule_expand_iki_
-
-#ifndef _di_controller_rule_id_construct_
- f_status_t controller_rule_id_construct(const controller_global_t global, const f_string_static_t source, const f_range_t directory, const f_range_t basename, f_string_dynamic_t * const alias) {
-
- f_status_t status = F_okay;
-
- alias->used = 0;
-
- status = f_string_dynamic_partial_append_nulless(source, directory, alias);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true);
-
- return status;
- }
-
- status = f_string_dynamic_append(f_path_separator_s, alias);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_append", F_true);
-
- return status;
- }
-
- status = f_string_dynamic_partial_append_nulless(source, basename, alias);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true);
-
- return status;
- }
-
- return status;
- }
-#endif // _di_controller_rule_id_construct_
-
-#ifndef _di_controller_rule_status_is_available_
- f_status_t controller_rule_status_is_available(const uint8_t action, const controller_rule_t rule) {
-
- return F_status_is_error_not(rule.status[0]) && rule.status[action] == F_known_not;
- }
-#endif // _di_controller_rule_status_is_available_
-
-#ifndef _di_controller_rule_status_is_error_
- f_status_t controller_rule_status_is_error(const uint8_t action, const controller_rule_t rule) {
-
- return F_status_is_error(rule.status[0]) || F_status_is_error(rule.status[action]);
- }
-#endif // _di_controller_rule_status_is_error_
-
-#ifndef _di_controller_rule_item_read_
- f_status_t controller_rule_item_read(const controller_global_t global, const bool is_normal, controller_cache_t * const cache, controller_rule_item_t * const item) {
-
- f_status_t status = F_okay;
- controller_state_interrupt_t custom = macro_controller_state_interrupt_t_initialize_1(is_normal, global.thread);
- f_state_t state = macro_f_state_t_initialize_1(controller_common_allocation_large_d, controller_common_allocation_small_d, F_okay, 0, 0, 0, &controller_thread_signal_state_fss, 0, (void *) &custom, 0);
- f_range_t range = macro_f_range_t_initialize_2(cache->buffer_item.used);
- f_number_unsigned_t last = 0;
-
- uint8_t type = 0;
- uint8_t method = 0;
- bool multiple = F_false;
-
- item->actions.used = 0;
-
- for (; range.start < cache->buffer_item.used && range.start <= range.stop; last = range.start, cache->delimits.used = 0, cache->comments.used = 0) {
-
- fl_fss_extended_list_object_read(cache->buffer_item, &range, &cache->range_action, &cache->delimits, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "fl_fss_extended_list_object_read", F_true);
-
- break;
- }
-
- if (status == F_fss_found_object) {
- multiple = F_true;
- }
- else {
- range.start = last;
- multiple = F_false;
- cache->delimits.used = 0;
-
- // The current line is not an Extended List object, so the next possibility is a Basic List (and Extended List, both use the same Object structure).
- fl_fss_extended_object_read(cache->buffer_item, &range, &cache->range_action, 0, &cache->delimits, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "fl_fss_extended_object_read", F_true);
-
- break;
- }
-
- // Nothing of importance here, so continue onto the next line.
- if (status != F_fss_found_object) continue;
- }
-
- f_fss_apply_delimit(cache->delimits, &cache->buffer_item, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_fss_apply_delimit", F_true);
-
- break;
- }
-
- f_fss_count_lines(cache->buffer_item, cache->range_action.start, &cache->action.line_action, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_fss_count_lines", F_true);
-
- break;
- }
-
- cache->action.line_action += ++item->line;
- cache->action.name_action.used = 0;
-
- status = f_rip_dynamic_partial_nulless(cache->buffer_item, cache->range_action, &cache->action.name_action);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_rip_dynamic_partial_nulless", F_true);
-
- break;
- }
-
- if (f_compare_dynamic(controller_freeze_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_freeze_e;
- }
- else if (f_compare_dynamic(controller_group_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_group_e;
- }
- else if (f_compare_dynamic(controller_kill_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_kill_e;
- }
- else if (f_compare_dynamic(controller_pause_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_pause_e;
- }
- else if (f_compare_dynamic(controller_pid_file_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_pid_file_e;
- }
- else if (f_compare_dynamic(controller_reload_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_reload_e;
- }
- else if (f_compare_dynamic(controller_rerun_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_rerun_e;
- }
- else if (f_compare_dynamic(controller_restart_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_restart_e;
- }
- else if (f_compare_dynamic(controller_resume_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_resume_e;
- }
- else if (f_compare_dynamic(controller_start_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_start_e;
- }
- else if (f_compare_dynamic(controller_stop_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_stop_e;
- }
- else if (f_compare_dynamic(controller_thaw_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_thaw_e;
- }
- else if (f_compare_dynamic(controller_user_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_user_e;
- }
- else if (f_compare_dynamic(controller_with_s, cache->action.name_action) == F_equal_to) {
- type = controller_rule_action_type_with_e;
- }
- else {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- fl_print_format("%r%[%QUnknown rule item action '%]", global.main->program.warning.to, f_string_eol_s, global.main->program.warning.context, global.main->program.warning.prefix, global.main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.warning.to, global.main->program.warning.notable, cache->action.name_action, global.main->program.warning.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.warning.to, global.main->program.warning.context, global.main->program.warning.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.warning, cache->action, F_true);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
-
- continue;
- }
-
- if (multiple) {
- if (type == controller_rule_action_type_group_e || type == controller_rule_action_type_pid_file_e || type == controller_rule_action_type_user_e) {
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QFSS Extended List is not allowed for the rule item action '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->action.name_action, global.main->program.error.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- status = F_status_set_error(F_support_not);
- break;
- }
-
- method = controller_rule_action_method_extended_list_e;
- }
- else {
- method = controller_rule_action_method_extended_e;
- }
-
- status = controller_rule_actions_increase_by(controller_common_allocation_small_d, &item->actions);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "controller_rule_actions_increase_by", F_true);
-
- break;
- }
-
- status = controller_rule_action_read(global, is_normal, type, method, cache, item, &item->actions, &range);
- if (F_status_is_error(status)) break;
- } // for
-
- return status;
- }
-#endif // _di_controller_rule_item_read_
-
-#ifndef _di_controller_rule_items_increase_by_
- f_status_t controller_rule_items_increase_by(const f_number_unsigned_t amount, controller_rule_items_t * const items) {
-
- if (amount) {
- if (items->used >= F_number_t_size_unsigned_d) return F_status_set_error(F_array_too_large);
-
- const f_number_unsigned_t length = items->used + amount;
-
- if (length > items->size) {
- const f_status_t status = f_memory_resize(items->size, length, sizeof(controller_rule_item_t), (void **) & items->array);
-
- if (F_status_is_error_not(status)) {
- items->size = items->used + amount;
- }
-
- return status;
- }
- }
-
- return F_data_not;
- }
-#endif // _di_controller_rule_items_increase_by_
-
-#ifndef _di_controller_rule_process_
- f_status_t controller_rule_process(const controller_global_t global, controller_data_t * const process) {
-
- switch (process->action) {
- case controller_rule_action_type_freeze_e:
- case controller_rule_action_type_kill_e:
- case controller_rule_action_type_pause_e:
- case controller_rule_action_type_reload_e:
- case controller_rule_action_type_restart_e:
- case controller_rule_action_type_resume_e:
- case controller_rule_action_type_start_e:
- case controller_rule_action_type_stop_e:
- case controller_rule_action_type_thaw_e:
- break;
-
- default:
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QUnsupported action type '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_rule_action_type_name(process->action), global.main->program.error.notable);
- fl_print_format("%[' while attempting to execute rule.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, process->cache.action, F_true);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- return F_status_set_error(F_parameter);
- }
-
- f_status_t status = F_okay;
- f_status_t status_lock = F_okay;
-
- process->cache.action.name_action.used = 0;
- process->cache.action.name_item.used = 0;
- process->cache.action.name_file.used = 0;
-
- status = f_string_dynamic_append(controller_rules_s, &process->cache.action.name_file);
-
- if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(f_path_separator_s, &process->cache.action.name_file);
- }
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, process->cache.action, F_status_set_fine(status), "f_string_dynamic_append", F_true, F_true);
-
- return status;
- }
-
- status = f_string_dynamic_append(process->rule.alias, &process->cache.action.name_file);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, process->cache.action, F_status_set_fine(status), "f_string_dynamic_append", F_true, F_true);
-
- return status;
- }
-
- status = f_string_dynamic_append(f_path_extension_separator_s, &process->cache.action.name_file);
-
- if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(controller_rule_s, &process->cache.action.name_file);
- }
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, process->cache.action, F_status_set_fine(status), "f_string_dynamic_append", F_true, F_true);
-
- return status;
- }
-
- if ((process->options & controller_process_option_simulate_d) && (process->options & controller_process_option_validate_d)) {
- controller_rule_validate(global, process->rule, process->action, process->options, &process->cache);
- }
-
- f_number_unsigned_t i = 0;
-
- {
- f_number_unsigned_t j = 0;
- f_number_unsigned_t id_rule = 0;
- f_number_unsigned_t id_dependency = 0;
-
- bool found = F_false;
-
- controller_data_t *dependency = 0;
-
- uint8_t options_process = 0;
-
- const f_string_static_t strings[3] = {
- controller_rule_needed_s,
- controller_rule_wanted_s,
- controller_rule_wished_s,
- };
-
- f_string_dynamics_t empty = f_string_dynamics_t_initialize;
- f_string_dynamics_t *dynamics[3] = { &empty, &empty, &empty };
-
- if (process->action) {
-
- for (i = 0; i < process->rule.ons.used; ++i) {
-
- if (process->rule.ons.array[i].action == process->action) {
- dynamics[0] = &process->rule.ons.array[i].need;
- dynamics[1] = &process->rule.ons.array[i].want;
- dynamics[2] = &process->rule.ons.array[i].wish;
-
- break;
- }
- } // for
- }
-
- // i==0 is need, i==1 is want, i==2 is wish.
- // Loop through all dependencies: wait for depedency, execute dependency, fail due to missing required dependency, or skip unrequired missing dependencies.
- for (i = 0; i < 3 && controller_thread_is_enabled_process(process, global.thread); ++i) {
-
- for (j = 0; j < dynamics[i]->used && controller_thread_is_enabled_process(process, global.thread); ++j) {
-
- id_dependency = 0;
- dependency = 0;
- found = F_false;
-
- status_lock = controller_lock_read_process(process, global.thread, &global.thread->lock.process);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
- }
- else {
- status = controller_process_prepare_process_type(global, process->type, process->action, dynamics[i]->array[j], &id_dependency);
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) == F_lock) {
- if (!controller_thread_is_enabled_process_type(process->type, global.thread)) {
- return F_status_set_error(F_interrupt);
- }
- }
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- controller_rule_item_print_error_rule_not_loaded(&global.main->program.error, dynamics[i]->array[j]);
- controller_rule_print_error_cache(&global.main->program.error, process->cache.action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- return status;
- }
-
- status = F_true;
- }
-
- if (status == F_true) {
- found = F_true;
-
- dependency = global.thread->processs.array[id_dependency];
-
- status_lock = controller_lock_read_process(process, global.thread, &dependency->active);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- status = F_false;
- dependency = 0;
-
- f_thread_unlock(&global.thread->lock.process);
- }
- else {
- f_thread_unlock(&global.thread->lock.process);
-
- status_lock = controller_lock_read_process(process, global.thread, &global.thread->lock.rule);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- status = F_false;
- }
- else {
- status = controller_rule_find(dynamics[i]->array[j], global.setting->rules, &id_rule);
-
- f_thread_unlock(&global.thread->lock.rule);
- }
- }
- }
- else {
- f_thread_unlock(&global.thread->lock.process);
- }
-
- if (status != F_true) {
- found = F_false;
- id_rule = 0;
-
- if (i == 0) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- controller_rule_item_print_error_need_want_wish(&global.main->program.error, strings[i], dynamics[i]->array[j], "is not found");
- controller_rule_print_error_cache(&global.main->program.error, process->cache.action, F_true);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
-
- status = F_status_set_error(F_found_not);
-
- if (!(process->options & controller_process_option_simulate_d)) {
- if (dependency) {
- f_thread_unlock(&dependency->active);
- }
-
- break;
- }
- }
- else {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- controller_rule_item_print_error_need_want_wish(&global.main->program.warning, strings[i], dynamics[i]->array[j], "is not found");
-
- controller_rule_print_error_cache(&global.main->program.warning, process->cache.action, F_true);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
- }
- }
- else if (found) {
- status_lock = controller_lock_read_process(process, global.thread, &global.thread->lock.rule);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- found = F_false;
- status = status_lock;
- }
- }
-
- if (found) {
-
- // The dependency may have write locks, which needs to be avoided, so copy the alias from the rule.
- f_string_static_t alias_other_buffer = f_string_static_t_initialize;
- alias_other_buffer.used = global.setting->rules.array[id_rule].alias.used;
-
- f_char_t alias_other_buffer_string[alias_other_buffer.used + 1];
- alias_other_buffer.string = alias_other_buffer_string;
-
- memcpy(alias_other_buffer_string, global.setting->rules.array[id_rule].alias.string, sizeof(f_char_t) * alias_other_buffer.used);
- alias_other_buffer_string[alias_other_buffer.used] = 0;
-
- f_thread_unlock(&global.thread->lock.rule);
-
- status_lock = controller_lock_read_process(process, global.thread, &dependency->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- status = status_lock;
- }
- else if (dependency->state == controller_process_state_active_e || dependency->state == controller_process_state_busy_e) {
- f_thread_unlock(&dependency->lock);
-
- status = controller_process_wait(global, dependency);
-
- if (F_status_is_error(status) && !(process->options & controller_process_option_simulate_d)) break;
-
- status = dependency->rule.status[process->action];
- }
- else {
- status_lock = controller_lock_read_process(process, global.thread, &global.thread->lock.rule);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- f_thread_unlock(&dependency->lock);
-
- status = status_lock;
- }
- else if (controller_rule_status_is_available(process->action, global.setting->rules.array[id_rule])) {
- f_thread_unlock(&global.thread->lock.rule);
- f_thread_unlock(&dependency->lock);
-
- options_process = 0;
-
- if (global.main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) {
- options_process |= controller_process_option_simulate_d;
- }
-
- if (process->options & controller_process_option_validate_d) {
- options_process |= controller_process_option_validate_d;
- }
-
- // Synchronously execute dependency.
- status = controller_rule_process_begin(global, 0, alias_other_buffer, process->action, options_process, process->type, process->stack, dependency->cache);
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt) {
- f_thread_unlock(&dependency->active);
-
- break;
- }
-
- if (F_status_is_error(status)) {
- if (i == 0 || i == 1 || F_status_set_fine(status) == F_memory_not) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- controller_rule_item_print_error_need_want_wish(&global.main->program.error, strings[i], alias_other_buffer, "failed during execution");
- controller_rule_print_error_cache(&global.main->program.error, process->cache.action, F_true);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
-
- if (!(dependency->options & controller_process_option_simulate_d) || F_status_set_fine(status) == F_memory_not) {
- f_thread_unlock(&dependency->active);
-
- break;
- }
- }
- else {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- controller_rule_item_print_error_need_want_wish(&global.main->program.warning, strings[i], alias_other_buffer, "failed during execution");
-
- controller_rule_print_error_cache(&global.main->program.warning, process->cache.action, F_true);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
- }
- }
- }
- else {
- status = global.setting->rules.array[id_rule].status[process->action];
-
- f_thread_unlock(&global.thread->lock.rule);
- f_thread_unlock(&dependency->lock);
- }
- }
-
- if (!controller_thread_is_enabled_process(process, global.thread)) {
- f_thread_unlock(&dependency->active);
-
- break;
- }
-
- if (F_status_is_error_not(status_lock)) {
- status_lock = controller_lock_read_process(process, global.thread, &global.thread->lock.rule);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_false, global.thread);
- }
- }
-
- if (F_status_is_error(status_lock)) {
- if (F_status_is_error(status_lock)) {
- controller_rule_item_print_error_need_want_wish(&global.main->program.error, strings[i], alias_other_buffer, "due to lock failure");
- }
-
- status = status_lock;
- }
- else if (controller_rule_status_is_error(process->action, global.setting->rules.array[id_rule])) {
- f_thread_unlock(&global.thread->lock.rule);
-
- if (i == 0 || i == 1) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- controller_rule_item_print_error_need_want_wish(&global.main->program.error, strings[i], alias_other_buffer, "is in a failed state");
-
- controller_rule_print_error_cache(&global.main->program.error, process->cache.action, F_true);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
-
- status = F_status_set_error(F_found_not);
-
- if (!(dependency->options & controller_process_option_simulate_d)) {
- f_thread_unlock(&dependency->active);
-
- break;
- }
- }
- else {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- controller_rule_item_print_error_need_want_wish(&global.main->program.warning, strings[i], alias_other_buffer, "is in a failed state");
-
- controller_rule_print_error_cache(&global.main->program.warning, process->cache.action, F_true);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
- }
- }
- else {
- f_thread_unlock(&global.thread->lock.rule);
- }
- }
-
- if (dependency) {
- f_thread_unlock(&dependency->active);
- }
- } // for
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt) break;
-
- if (F_status_is_error(status) && !(process->options & controller_process_option_simulate_d)) break;
- } // for
- }
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt) {
- return status;
- }
-
- if (!controller_thread_is_enabled_process(process, global.thread)) {
- return F_status_set_error(F_interrupt);
- }
-
- if ((process->options & controller_process_option_wait_d) && F_status_is_error_not(status) && (process->options & controller_process_option_validate_d)) {
- status_lock = controller_rule_wait_all_process_type(global, process->type, F_false);
-
- if (F_status_set_fine(status_lock) == F_interrupt) {
- return status_lock;
- }
- }
-
- if (!(process->options & controller_process_option_validate_d) && F_status_is_error_not(status)) {
-
- // Find at least one of the requested action when the rule is required.
- if (process->options & controller_process_option_require_d) {
- bool missing = F_true;
-
- f_number_unsigned_t j = 0;
-
- for (i = 0; i < process->rule.items.used; ++i) {
-
- for (j = 0; j < process->rule.items.array[i].actions.used; ++j) {
-
- if (process->rule.items.array[i].actions.array[j].type == process->action) {
- missing = F_false;
-
- break;
- }
- } // for
- } // for
-
- if (missing) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- if (process->rule.items.used) {
- fl_print_format("%r%[%QThe rule '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, process->rule.name, global.main->program.error.notable);
- fl_print_format("%[' has no '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_rule_action_type_name(process->action), global.main->program.error.notable);
- fl_print_format("%[' action to execute.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
- }
- else {
- fl_print_format("%r%[%QThe rule '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, process->rule.name, global.main->program.error.notable);
- fl_print_format("%[ has no known '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[%r %r%]", global.main->program.error.to, global.main->program.error.notable, controller_rule_s, controller_type_s, global.main->program.error.notable);
- fl_print_format("%[' (such as '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_command_s, global.main->program.error.notable);
- fl_print_format("%[', '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_service_s, global.main->program.error.notable);
- fl_print_format("%[', '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_script_s, global.main->program.error.notable);
- fl_print_format("%[', or '%]", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, global.main->program.error.to, global.main->program.error.notable, controller_utility_s, global.main->program.error.notable);
- fl_print_format("%[') to execute.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
- }
-
- controller_rule_print_error_cache(&global.main->program.error, process->cache.action, F_true);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- status = F_status_set_error(F_parameter);
- }
- }
-
- if (F_status_is_error_not(status)) {
- status = controller_rule_execute(global, process->action, process->options, process);
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock) {
- return status;
- }
-
- if (F_status_is_error(status)) {
- controller_rule_item_print_error(global.thread, &global.main->program.error, process->cache.action, F_true, F_status_set_fine(status));
- }
- }
- }
-
- f_number_unsigned_t id_rule = 0;
-
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_write_process(process, global.thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_false, global.thread);
-
- if (F_status_set_fine(status) != F_interrupt) {
- status = controller_lock_read_process(process, global.thread, &process->lock);
- if (F_status_is_error_not(status)) return status_lock;
- }
-
- return F_status_set_error(F_lock);
- }
-
- if (F_status_is_error(status)) {
- process->rule.status[process->action] = controller_status_simplify_error(F_status_set_fine(status));
- }
- else {
- process->rule.status[process->action] = status;
- }
-
- status_lock = controller_lock_write_process(process, global.thread, &global.thread->lock.rule);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_false, global.thread);
-
- f_thread_unlock(&process->lock);
-
- status = controller_lock_read_process(process, global.thread, &process->lock);
- if (F_status_is_error_not(status)) return status_lock;
-
- return F_status_set_error(F_lock);
- }
-
- // Update the global rule status, which is stored separately from the rule status for this process.
- if (controller_rule_find(process->rule.alias, global.setting->rules, &id_rule) == F_true) {
- controller_rule_t *rule = &global.setting->rules.array[id_rule];
-
- rule->status[process->action] = process->rule.status[process->action];
-
- f_number_unsigned_t j = 0;
-
- controller_rule_item_t *rule_item = 0;
-
- // Copy all rule item action statuses from the rule process to the rule.
- for (i = 0; i < rule->items.used; ++i) {
-
- rule_item = &rule->items.array[i];
-
- for (j = 0; j < rule_item->actions.used; ++j) {
- rule_item->actions.array[j].status = process->rule.items.array[i].actions.array[j].status;
- } // for
- } // for
- }
-
- f_thread_unlock(&global.thread->lock.rule);
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_read_process(process, global.thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- return F_status_set_error(F_lock);
- }
-
- return process->rule.status[process->action];
- }
-#endif // _di_controller_rule_process_
-
-#ifndef _di_controller_rule_process_begin_
- f_status_t controller_rule_process_begin(const controller_global_t global, const uint8_t options_force, const f_string_static_t alias_rule, const uint8_t action, const uint8_t options, const uint8_t type, const f_number_unsigneds_t stack, const controller_cache_t cache) {
-
- if (!controller_thread_is_enabled_process_type(type, global.thread)) {
- return F_status_set_error(F_interrupt);
- }
-
- f_status_t status = F_okay;
- f_status_t status_lock = F_okay;
-
- controller_data_t *process = 0;
-
- status = controller_lock_read_process_type(type, global.thread, &global.thread->lock.process);
-
- if (F_status_is_error(status)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status), F_true, global.thread);
-
- return status;
- }
-
- {
- f_number_unsigned_t at = 0;
-
- status = controller_process_prepare(global, type != controller_data_type_exit_e, action, alias_rule, &at);
-
- if (F_status_is_error(status)) {
- f_thread_unlock(&global.thread->lock.process);
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- controller_rule_item_print_error_rule_not_loaded(&global.main->program.error, alias_rule);
- controller_rule_print_error_cache(&global.main->program.error, cache.action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- return status;
- }
-
- process = global.thread->processs.array[at];
-
- status = controller_lock_read_process_type(type, global.thread, &process->active);
-
- if (F_status_is_error(status)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status), F_true, global.thread);
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache.action, F_false, F_status_set_fine(status));
-
- f_thread_unlock(&global.thread->lock.process);
-
- return status;
- }
-
- status_lock = controller_lock_write_process(process, global.thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_false, global.thread);
-
- f_thread_unlock(&process->active);
- f_thread_unlock(&global.thread->lock.process);
-
- return status_lock;
- }
-
- // Once a write lock on the process is achieved, it is safe to unlock the global process read lock.
- f_thread_unlock(&global.thread->lock.process);
-
- // If the process is already running, then there is nothing to do.
- if (process->state == controller_process_state_active_e || process->state == controller_process_state_busy_e) {
- f_thread_unlock(&process->lock);
- f_thread_unlock(&process->active);
-
- return F_busy;
- }
-
- // The thread is done, so close the thread.
- if (process->state == controller_process_state_done_e) {
- controller_thread_join(&process->id_thread);
-
- f_thread_mutex_lock(&process->wait_lock);
- f_thread_condition_signal_all(&process->wait);
- f_thread_mutex_unlock(&process->wait_lock);
- }
-
- process->id = at;
- }
-
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_write_process(process, global.thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_false, global.thread);
-
- f_thread_unlock(&process->active);
-
- return status_lock;
- }
-
- process->state = controller_process_state_active_e;
- process->action = action;
- process->options = options;
- process->type = type;
-
- macro_f_time_simple_t_clear(process->cache.timestamp)
-
- process->cache.ats.used = 0;
- process->cache.stack.used = 0;
- process->cache.comments.used = 0;
- process->cache.delimits.used = 0;
- process->cache.content_action.used = 0;
- process->cache.content_actions.used = 0;
- process->cache.content_items.used = 0;
- process->cache.object_actions.used = 0;
- process->cache.object_items.used = 0;
- process->cache.buffer_file.used = 0;
- process->cache.buffer_item.used = 0;
- process->cache.buffer_path.used = 0;
- process->cache.expanded.used = 0;
- process->cache.action.line_action = cache.action.line_action;
- process->cache.action.line_item = cache.action.line_item;
- process->cache.action.name_action.used = 0;
- process->cache.action.name_file.used = 0;
- process->cache.action.name_item.used = 0;
- process->cache.action.generic.used = 0;
- process->cache.range_action.start = 1;
- process->cache.range_action.stop = 0;
-
- process->stack.used = 0;
-
- process->main_data = (void *) global.main;
- process->main_setting = (void *) global.setting;
- process->main_thread = (void *) global.thread;
-
- if (F_status_is_error_not(status) && stack.used) {
- if (process->stack.size < stack.used) {
- status = f_memory_array_resize(stack.used, sizeof(f_number_unsigned_t), (void **) &process->stack.array, &process->stack.used, &process->stack.size);
- }
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_memory_array_resize", F_true);
- }
- else {
- for (f_number_unsigned_t i = 0; i < stack.used; ++i) {
- process->stack.array[i] = stack.array[i];
- } // for
-
- process->stack.used = stack.used;
- }
- }
-
- if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(cache.action.name_action, &process->cache.action.name_action);
-
- if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(cache.action.name_file, &process->cache.action.name_file);
- }
-
- if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(cache.action.name_item, &process->cache.action.name_item);
- }
- else {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_append", F_true);
- }
- }
-
- f_thread_unlock(&process->lock);
-
- if (F_status_is_error_not(status)) {
- if (process->action && (options_force & controller_process_option_asynchronous_d)) {
- if (process->type == controller_data_type_exit_e) {
- status = f_thread_create(0, &process->id_thread, controller_thread_process_other, (void *) process);
- }
- else {
- status = f_thread_create(0, &process->id_thread, controller_thread_process_normal, (void *) process);
- }
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_thread_create", F_true);
- }
- }
- else {
- status = controller_rule_process_do(options_force, process);
-
- if (status == F_child || F_status_set_fine(status) == F_interrupt) {
- f_thread_unlock(&process->active);
-
- return status;
- }
- }
- }
-
- if (!action || F_status_is_error(status) && (process->state == controller_process_state_active_e || process->state == controller_process_state_busy_e)) {
- {
- status_lock = controller_lock_write_process(process, global.thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_false, global.thread);
-
- f_thread_unlock(&process->active);
-
- return status_lock;
- }
- }
-
- if (!action || (options_force & controller_process_option_asynchronous_d)) {
- process->state = controller_process_state_done_e;
- }
- else {
- process->state = controller_process_state_idle_e;
- }
-
- f_thread_mutex_lock(&process->wait_lock);
- f_thread_condition_signal_all(&process->wait);
- f_thread_mutex_unlock(&process->wait_lock);
-
- f_thread_unlock(&process->lock);
- }
-
- f_thread_unlock(&process->active);
-
- if (F_status_is_error(status)) {
- return status;
- }
-
- return F_okay;
- }
-#endif // _di_controller_rule_process_begin_
-
-#ifndef _di_controller_rule_process_do_
- f_status_t controller_rule_process_do(const uint8_t options_force, controller_data_t * const process) {
-
- f_status_t status_lock = F_okay;
-
- controller_global_t global = macro_controller_global_t_initialize_1((controller_main_t *) process->main_data, (controller_process_t *) process->main_setting, (controller_thread_t *) process->main_thread);
-
- // The process and active locks shall be held for the duration of this processing (aside from switching between read to/from write).
- if (options_force & controller_process_option_asynchronous_d) {
- status_lock = controller_lock_read_process(process, global.thread, &process->active);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- return status_lock;
- }
- }
-
- status_lock = controller_lock_read_process(process, global.thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- return status_lock;
- }
-
- f_status_t status = F_okay;
-
- f_number_unsigned_t id_rule = 0;
-
- const f_number_unsigned_t used_original_stack = process->stack.used;
-
- status_lock = controller_lock_read_process(process, global.thread, &global.thread->lock.rule);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- f_thread_unlock(&process->lock);
-
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- return status_lock;
- }
-
- if (controller_rule_find(process->rule.alias, global.setting->rules, &id_rule) == F_true) {
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_write_process(process, global.thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_false, global.thread);
-
- f_thread_unlock(&global.thread->lock.rule);
-
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- return status_lock;
- }
-
- controller_rule_delete(&process->rule);
-
- status = controller_rule_copy(global.setting->rules.array[id_rule], &process->rule);
-
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_read_process(process, global.thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- f_thread_unlock(&global.thread->lock.rule);
-
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- return status_lock;
- }
-
- f_thread_unlock(&global.thread->lock.rule);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "controller_rule_copy", F_true);
- }
- else if (!process->action) {
-
- // This is a "consider" Action, so do not actually execute the rule.
- f_thread_unlock(&process->lock);
-
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- return F_process_not;
- }
- else {
- for (f_number_unsigned_t i = 0; i < process->stack.used && controller_thread_is_enabled_process(process, global.thread); ++i) {
-
- if (process->stack.array[i] == id_rule) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QThe rule '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, process->rule.alias, global.main->program.error.notable);
- fl_print_format("%[' is already on the execution dependency stack, this recursion is prohibited.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, process->cache.action, F_true);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- // Never continue on circular recursion errors even in simulate mode.
- status = F_status_set_error(F_recurse);
-
- break;
- }
- } // for
-
- if (!controller_thread_is_enabled_process(process, global.thread)) {
- f_thread_unlock(&process->lock);
-
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- return F_status_set_error(F_interrupt);
- }
-
- if (F_status_is_error_not(status)) {
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_number_unsigned_t), (void **) &process->stack.array, &process->stack.used, &process->stack.size);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_memory_array_increase", F_true);
- }
- else {
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_write_process(process, global.thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_false, global.thread);
-
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- return status_lock;
- }
-
- process->stack.array[process->stack.used++] = id_rule;
-
- f_thread_unlock(&process->lock);
-
- status_lock = controller_lock_read_process(process, global.thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- return status_lock;
- }
- }
- }
- }
-
- if (F_status_is_error_not(status)) {
- status = controller_rule_process(global, process);
- }
- }
- else {
- f_thread_unlock(&global.thread->lock.rule);
-
- status = F_status_set_error(F_found_not);
-
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- controller_rule_item_print_error_rule_not_loaded(&global.main->program.error, process->rule.alias);
- controller_rule_print_error_cache(&global.main->program.error, process->cache.action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
- }
-
- if (status == F_child) {
- f_thread_unlock(&process->lock);
-
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- return status;
- }
-
- status_lock = controller_lock_write_process(process, global.thread, &global.thread->lock.rule);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_false, global.thread);
-
- if (F_status_set_fine(status) != F_lock) {
- f_thread_unlock(&process->lock);
- }
-
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- return status_lock;
- }
-
- if (F_status_set_fine(status) == F_lock) {
- if (controller_rule_find(process->rule.alias, global.setting->rules, &id_rule) == F_true) {
- global.setting->rules.array[id_rule].status[process->action] = status;
- }
- }
-
- f_thread_unlock(&global.thread->lock.rule);
-
- if (F_status_set_fine(status) != F_lock) {
- f_thread_unlock(&process->lock);
- }
-
- if (F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_lock && !controller_thread_is_enabled_process(process, global.thread)) {
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- return F_status_set_error(F_interrupt);
- }
-
- status_lock = controller_lock_write_process(process, global.thread, &process->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_false, global.thread);
-
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- return status_lock;
- }
-
- if (options_force & controller_process_option_asynchronous_d) {
- process->state = controller_process_state_done_e;
- }
- else {
- process->state = controller_process_state_idle_e;
- }
-
- process->stack.used = used_original_stack;
-
- // inform all things waiting that the process has finished running.
- f_thread_mutex_lock(&process->wait_lock);
- f_thread_condition_signal_all(&process->wait);
- f_thread_mutex_unlock(&process->wait_lock);
-
- f_thread_unlock(&process->lock);
-
- if (options_force & controller_process_option_asynchronous_d) {
- f_thread_unlock(&process->active);
- }
-
- if (controller_thread_is_enabled_process(process, global.thread)) {
- return status;
- }
-
- return F_status_set_error(F_interrupt);
- }
-#endif // _di_controller_rule_process_do_
-
-#ifndef _di_controller_rule_read_
- f_status_t controller_rule_read(const controller_global_t global, const bool is_normal, const f_string_static_t alias, controller_cache_t * const cache, controller_entry_t * const entry, controller_rule_t * const rule) {
-
- f_status_t status = F_okay;
-
- bool for_item = F_true;
-
- rule->timeout_kill = entry->timeout_kill ? entry->timeout_kill : 0;
- rule->timeout_start = entry->timeout_start ? entry->timeout_start : 0;
- rule->timeout_stop = entry->timeout_stop ? entry->timeout_stop : 0;
-
- rule->has = 0;
- rule->group = 0;
- rule->user = 0;
- rule->nice = 0;
-
- macro_f_time_simple_t_clear(rule->timestamp);
-
- rule->alias.used = 0;
- rule->engine.used = 0;
- rule->engine_arguments.used = 0;
- rule->name.used = 0;
- rule->path.used = 0;
-
- rule->define.used = 0;
- rule->parameter.used = 0;
- rule->environment.used = 0;
-
- rule->affinity.used = 0;
-
- if (rule->capability) {
- f_capability_delete(&rule->capability);
- rule->capability = 0;
- }
-
- rule->cgroup.as_new = F_false;
- rule->cgroup.path.used = 0;
- rule->cgroup.groups.used = 0;
-
- macro_f_control_group_t_clear(rule->cgroup);
-
- rule->groups.used = 0;
- rule->limits.used = 0;
-
- rule->scheduler.policy = 0;
- rule->scheduler.priority = 0;
-
- rule->ons.used = 0;
- rule->items.used = 0;
-
- cache->action.line_item = 0;
- cache->action.line_action = 0;
-
- cache->range_action.start = 1;
- cache->range_action.stop = 0;
-
- cache->comments.used = 0;
- cache->delimits.used = 0;
-
- cache->buffer_file.used = 0;
- cache->buffer_item.used = 0;
- cache->buffer_path.used = 0;
-
- cache->content_items.used = 0;
- cache->object_items.used = 0;
-
- cache->action.name_action.used = 0;
- cache->action.name_file.used = 0;
- cache->action.name_item.used = 0;
-
- {
- f_number_unsigned_t i = 0;
- f_number_unsigned_t j = 0;
- f_number_unsigned_t k = 0;
- f_number_unsigned_t l = 0;
-
- for (i = 0; i < rule->cgroup.groups.size; ++i) {
- rule->cgroup.groups.array[i].used = 0;
- } // for
-
- for (; i < controller_rule_action_type__enum_size_e; ++i) {
- rule->status[i] = F_known_not;
- } // for
-
- for (i = 0; i < cache->content_items.size; ++i) {
- cache->content_items.array[i].used = 0;
- } // for
-
- for (i = 0; i < rule->engine_arguments.size; ++i) {
- rule->engine_arguments.array[i].used = 0;
- } // for
-
- for (i = 0; i < rule->ons.size; ++i) {
- rule->ons.array[i].need.used = 0;
- rule->ons.array[i].want.used = 0;
- rule->ons.array[i].wish.used = 0;
- } // for
-
- for (i = 0; i < rule->items.size; ++i) {
-
- rule->items.array[i].type = 0;
- rule->items.array[i].with = 0;
- rule->items.array[i].line = 0;
- rule->items.array[i].pid_file.used = 0;
- rule->items.array[i].actions.used = 0;
-
- for (j = 0; j < controller_rule_action_execute_type__enum_size_e; ++j) {
-
- rule->items.array[i].reruns[j].is = 0;
-
- macro_controller_rule_rerun_item_initialize(rule->items.array[i].reruns[j].failure);
- macro_controller_rule_rerun_item_initialize(rule->items.array[i].reruns[j].success);
- } // for
-
- for (j = 0; j < rule->items.array[i].actions.size; ++j) {
-
- rule->items.array[i].actions.array[j].type = 0;
- rule->items.array[i].actions.array[j].line = 0;
- rule->items.array[i].actions.array[j].status = F_okay;
- rule->items.array[i].actions.array[j].parameters.used = 0;
- rule->items.array[i].actions.array[j].ikis.used = 0;
-
- for (k = 0; k < rule->items.array[i].actions.array[j].parameters.size; ++k) {
- rule->items.array[i].actions.array[j].parameters.array[k].used = 0;
- } // for
-
- for (k = 0; k < rule->items.array[i].actions.array[j].ikis.size; ++k) {
-
- rule->items.array[i].actions.array[j].ikis.array[k].content.used = 0;
- rule->items.array[i].actions.array[j].ikis.array[k].delimits.used = 0;
- rule->items.array[i].actions.array[j].ikis.array[k].variable.used = 0;
- rule->items.array[i].actions.array[j].ikis.array[k].vocabulary.used = 0;
-
- for (l = 0; l < rule->items.array[i].actions.array[j].ikis.array[k].content.size; ++l) {
-
- rule->items.array[i].actions.array[j].ikis.array[k].content.array[l].start = 1;
- rule->items.array[i].actions.array[j].ikis.array[k].content.array[l].stop = 0;
- } // for
-
- for (l = 0; l < rule->items.array[i].actions.array[j].ikis.array[k].delimits.size; ++l) {
- rule->items.array[i].actions.array[j].ikis.array[k].delimits.array[l] = 0;
- } // for
-
- for (l = 0; l < rule->items.array[i].actions.array[j].ikis.array[k].variable.size; ++l) {
-
- rule->items.array[i].actions.array[j].ikis.array[k].variable.array[l].start = 1;
- rule->items.array[i].actions.array[j].ikis.array[k].variable.array[l].stop = 0;
- } // for
-
- for (l = 0; l < rule->items.array[i].actions.array[j].ikis.array[k].vocabulary.size; ++l) {
-
- rule->items.array[i].actions.array[j].ikis.array[k].vocabulary.array[l].start = 1;
- rule->items.array[i].actions.array[j].ikis.array[k].vocabulary.array[l].stop = 0;
- } // for
- } // for
- } // for
- } // for
- }
-
- status = f_string_dynamic_append_nulless(alias, &rule->alias);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true);
- }
- else {
- status = controller_file_load(global, F_true, controller_rules_s, rule->alias, controller_rule_s, cache);
- }
-
- if (F_status_is_error_not(status)) {
- rule->timestamp = cache->timestamp;
-
- if (cache->buffer_file.used) {
- controller_state_interrupt_t custom = macro_controller_state_interrupt_t_initialize_1(is_normal, global.thread);
- f_state_t state = macro_f_state_t_initialize_1(controller_common_allocation_large_d, controller_common_allocation_small_d, F_okay, 0, 0, 0, &controller_thread_signal_state_fss, 0, (void *) &custom, 0);
- f_range_t range = macro_f_range_t_initialize_2(cache->buffer_file.used);
-
- fll_fss_basic_list_read(cache->buffer_file, &range, &cache->object_items, &cache->content_items, &cache->delimits, 0, &cache->comments, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true);
- }
- else {
- f_fss_apply_delimit(cache->delimits, &cache->buffer_file, &state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_fss_apply_delimit", F_true);
- }
- }
- }
- }
-
- if (F_status_is_error_not(status) && cache->object_items.used) {
- status = controller_rule_items_increase_by(cache->object_items.used, &rule->items);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "controller_rule_items_increase_by", F_true);
- }
- else {
- f_number_unsigned_t i = 0;
- f_number_unsigned_t j = 0;
- f_state_t state = f_state_t_initialize;
-
- for (; i < cache->object_items.used; ++i) {
-
- cache->action.line_item = 0;
- cache->action.line_action = 0;
-
- cache->range_action.start = 1;
- cache->range_action.stop = 0;
-
- cache->comments.used = 0;
- cache->delimits.used = 0;
-
- cache->content_action.used = 0;
-
- for (j = 0; j < cache->content_actions.used; ++j) {
- cache->content_actions.array[j].used = 0;
- } // for
-
- cache->content_actions.used = 0;
- cache->object_actions.used = 0;
-
- cache->buffer_item.used = 0;
- cache->buffer_path.used = 0;
-
- cache->action.name_action.used = 0;
- cache->action.name_item.used = 0;
-
- for_item = F_true;
-
- f_fss_count_lines(cache->buffer_file, cache->object_items.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_fss_count_lines", F_true);
-
- break;
- }
-
- rule->items.array[rule->items.used].line = ++cache->action.line_item;
-
- status = f_rip_dynamic_partial_nulless(cache->buffer_file, cache->object_items.array[i], &cache->action.name_item);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_rip_dynamic_partial_nulless", F_true);
-
- break;
- }
-
- if (f_compare_dynamic(controller_settings_s, cache->action.name_item) == F_equal_to) {
- rule->items.array[rule->items.used].type = 0;
- }
- else if (f_compare_dynamic(controller_command_s, cache->action.name_item) == F_equal_to) {
- rule->items.array[rule->items.used].type = controller_rule_item_type_command_e;
- }
- else if (f_compare_dynamic(controller_script_s, cache->action.name_item) == F_equal_to) {
- rule->items.array[rule->items.used].type = controller_rule_item_type_script_e;
- }
- else if (f_compare_dynamic(controller_service_s, cache->action.name_item) == F_equal_to) {
- rule->items.array[rule->items.used].type = controller_rule_item_type_service_e;
- }
- else if (f_compare_dynamic(controller_utility_s, cache->action.name_item) == F_equal_to) {
- rule->items.array[rule->items.used].type = controller_rule_item_type_utility_e;
- }
- else {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- fl_print_format("%r%[%QUnknown rule item '%]", global.main->program.warning.to, f_string_eol_s, global.main->program.warning.context, global.main->program.warning.prefix, global.main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.warning.to, global.main->program.warning.notable, cache->action.name_item, global.main->program.warning.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.warning.to, global.main->program.warning.context, global.main->program.warning.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.warning, cache->action, F_true);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
-
- continue;
- }
-
- status = f_string_dynamic_partial_append(cache->buffer_file, cache->content_items.array[i].array[0], &cache->buffer_item);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_string_dynamic_partial_append", F_true);
-
- break;
- }
-
- if (rule->items.array[rule->items.used].type) {
-
- // Initialize the item with settings.
- rule->items.array[rule->items.used].with = 0;
-
- if (entry->session == controller_entry_session_new_e) {
- rule->items.array[rule->items.used].with |= controller_with_session_new_d;
- }
- else {
- rule->items.array[rule->items.used].with |= controller_with_session_same_d;
- }
-
- status = controller_rule_item_read(global, is_normal, cache, &rule->items.array[rule->items.used]);
- if (F_status_is_error(status)) break;
-
- ++rule->items.used;
- }
- else {
- for_item = F_false;
-
- status = controller_rule_setting_read(global, is_normal, *global.setting, cache, rule);
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) == F_memory_not) break;
- }
- }
- } // for
- }
- }
-
- if (F_status_is_error(status)) {
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, for_item, F_status_set_fine(status));
-
- rule->status[0] = controller_status_simplify_error(F_status_set_fine(status));
-
- return rule->status[0];
- }
-
- return F_okay;
- }
-#endif // _di_controller_rule_read_
-
-#ifndef _di_controller_rule_setting_read_
- f_status_t controller_rule_setting_read(const controller_global_t global, const bool is_normal, const controller_process_t setting, controller_cache_t * const cache, controller_rule_t * const rule) {
-
- f_status_t status = F_okay;
- f_status_t status_return = F_okay;
-
- f_range_t range = macro_f_range_t_initialize_2(cache->buffer_item.used);
- f_range_t range2 = f_range_t_initialize;
-
- controller_state_interrupt_t custom = macro_controller_state_interrupt_t_initialize_1(is_normal, global.thread);
- f_state_t state = macro_f_state_t_initialize_1(controller_common_allocation_large_d, controller_common_allocation_small_d, F_okay, 0, 0, 0, &controller_thread_signal_state_fss, 0, (void *) &custom, 0);
-
- fll_fss_extended_read(cache->buffer_item, &range, &cache->object_actions, &cache->content_actions, 0, 0, &cache->delimits, 0, &state);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "fll_fss_extended_read", F_true, F_false);
-
- return status;
- }
-
- f_string_dynamic_t *setting_value = 0;
- f_string_dynamics_t *setting_values = 0;
- f_string_maps_t *setting_maps = 0;
-
- f_number_unsigned_t i = 0;
- f_number_unsigned_t j = 0;
- uint8_t type = 0;
- uint8_t action = 0;
- bool empty_disallow = F_true;
-
- // Save the current name item and line number to restore on return.
- const f_number_unsigned_t line_item = cache->action.line_item;
- const f_number_unsigned_t length_name_item = cache->action.name_item.used;
-
- f_char_t name_item[length_name_item];
- name_item[length_name_item] = 0;
-
- memcpy(name_item, cache->action.name_item.string, sizeof(f_char_t) * length_name_item);
-
- for (; i < cache->content_actions.used; ++i, type = 0) {
-
- // The name_action is used to store all setting values for a single setting.
- cache->action.name_action.used = 0;
-
- // The name_item is used to store the setting name.
- cache->action.name_item.used = 0;
-
- status = f_string_dynamic_partial_append_nulless(cache->buffer_item, cache->object_actions.array[i], &cache->action.name_item);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true, F_false);
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- empty_disallow = F_true;
-
- if (f_compare_dynamic(controller_affinity_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_affinity_e;
- }
- else if (f_compare_dynamic(controller_capability_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_capability_e;
- }
- else if (f_compare_dynamic(controller_cgroup_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_cgroup_e;
- }
- else if (f_compare_dynamic(controller_define_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_define_e;
- }
- else if (f_compare_dynamic(controller_engine_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_engine_e;
- }
- else if (f_compare_dynamic(controller_environment_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_environment_e;
- empty_disallow = F_false;
- }
- else if (f_compare_dynamic(controller_group_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_group_e;
- }
- else if (f_compare_dynamic(controller_limit_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_limit_e;
- }
- else if (f_compare_dynamic(controller_name_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_name_e;
- }
- else if (f_compare_dynamic(controller_nice_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_nice_e;
- }
- else if (f_compare_dynamic(controller_on_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_on_e;
- }
- else if (f_compare_dynamic(controller_parameter_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_parameter_e;
- }
- else if (f_compare_dynamic(controller_path_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_path_e;
- }
- else if (f_compare_dynamic(controller_scheduler_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_scheduler_e;
- }
- else if (f_compare_dynamic(controller_timeout_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_timeout_e;
- }
- else if (f_compare_dynamic(controller_user_s, cache->action.name_item) == F_equal_to) {
- type = controller_rule_setting_type_user_e;
- }
- else {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- fl_print_format("%r%[%QUnknown rule setting '%]", global.main->program.warning.to, f_string_eol_s, global.main->program.warning.context, global.main->program.warning.prefix, global.main->program.warning.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.warning.to, global.main->program.warning.notable, cache->action.name_item, global.main->program.warning.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.warning.to, global.main->program.warning.context, global.main->program.warning.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.warning, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
-
- continue;
- }
-
- if (cache->content_actions.array[i].used) {
- range2.start = cache->content_actions.array[i].array[0].start;
- range2.stop = cache->content_actions.array[i].array[cache->content_actions.array[i].used - 1].stop;
-
- status = f_string_dynamic_partial_append_nulless(cache->buffer_item, range2, &cache->action.name_action);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true, F_false);
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- continue;
- }
- }
- else {
- if (empty_disallow) {
- if (global.main->program.warning.verbosity == f_console_verbosity_debug_e) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(global.main->program.warning.to, global.thread);
-
- fl_print_format("%r%[%QEmpty rule setting.%]%r", global.main->program.warning.to, f_string_eol_s, global.main->program.warning.context, global.main->program.warning.prefix, global.main->program.warning.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.warning, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.warning.to, global.thread);
- }
-
- continue;
- }
- }
-
- if (type == controller_rule_setting_type_affinity_e) {
- if (!cache->content_actions.array[i].used) {
- controller_rule_setting_read_print_error(&global.main->program.error, "requires one or more Content", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- rule->affinity.used = 0;
-
- f_number_signed_t number = 0;
-
- for (j = 0; j < cache->content_actions.array[i].used; ++j, number = 0) {
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(int32_t), (void **) &rule->affinity.array, &rule->affinity.used, &rule->affinity.size);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_memory_array_increase", F_true, F_false);
-
- break;
- }
-
- status = fl_conversion_dynamic_partial_to_signed_detect(fl_conversion_data_base_10_c, cache->buffer_item, cache->content_actions.array[i].array[j], &number);
-
- if (F_status_set_fine(status) == F_number_positive) {
- status = fl_conversion_dynamic_partial_to_signed_detect(fl_conversion_data_base_10_c, cache->buffer_item, controller_range_after_number_sign(cache->buffer_item, cache->content_actions.array[i].array[j]), &number);
-
- // Restore error on parameter problem.
- if (F_status_set_fine(status) == F_parameter) {
- status = F_status_set_error(F_number_positive);
- }
- }
-
- if (F_status_is_error(status)) {
- status = F_status_set_fine(status);
-
- if (status == F_data_not || status == F_number || status == F_number_overflow || status == F_number_underflow || status == F_number_negative || status == F_number_decimal) {
- if (status == F_number_underflow) {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an unsupported number", cache->content_actions.array[i].array[j], ", the number is too small for this system", i, line_item, global.thread, cache);
- }
- else if (status == F_number_overflow || status == F_number_positive) {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an unsupported number", cache->content_actions.array[i].array[j], ", the number is too large for this system", i, line_item, global.thread, cache);
- }
- else {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an invalid number", cache->content_actions.array[i].array[j], ", only whole numbers are allowed for an affinity value", i, line_item, global.thread, cache);
- }
-
- status = F_status_set_error(F_valid_not);
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
- }
- else {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "fl_conversion_dynamic_partial_to_signed_detect", F_true, F_false);
-
- status = F_status_set_error(status);
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
- }
-
- continue;
- }
-
- rule->affinity.array[rule->affinity.used++] = number;
- } // for
-
- controller_rule_setting_read_print_values(global, controller_affinity_s, i, cache);
-
- continue;
- }
-
- if (type == controller_rule_setting_type_define_e || type == controller_rule_setting_type_parameter_e) {
- if (cache->content_actions.array[i].used != 2) {
- controller_rule_setting_read_print_error(&global.main->program.error, "requires exactly two Content", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- if (type == controller_rule_setting_type_define_e) {
- setting_maps = &rule->define;
- }
- else if (type == controller_rule_setting_type_parameter_e) {
- setting_maps = &rule->parameter;
- }
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_string_map_t), (void **) &setting_maps->array, &setting_maps->used, &setting_maps->size);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_memory_array_increase", F_true, F_false);
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- setting_maps->array[setting_maps->used].key.used = 0;
- setting_maps->array[setting_maps->used].value.used = 0;
-
- status = f_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[0], &setting_maps->array[setting_maps->used].key);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true, F_false);
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- status = f_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[1], &setting_maps->array[setting_maps->used].value);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true, F_false);
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- controller_rule_setting_read_print_mapping(global, type == controller_rule_setting_type_define_e ? controller_define_s : controller_parameter_s, setting_maps->array[setting_maps->used]);
-
- ++setting_maps->used;
-
- continue;
- }
-
- if (type == controller_rule_setting_type_cgroup_e) {
- if (cache->content_actions.array[i].used < 2 || rule->has & controller_rule_has_cgroup_d) {
- controller_rule_setting_read_print_error(&global.main->program.error, "requires two or more Content", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- if (f_compare_dynamic_partial_string(controller_existing_s.string, cache->buffer_item, controller_existing_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- rule->cgroup.as_new = F_false;
- }
- else if (f_compare_dynamic_partial_string(controller_new_s.string, cache->buffer_item, controller_new_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- rule->cgroup.as_new = F_true;
- }
- else {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an unknown option", cache->content_actions.array[i].array[0], "", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- rule->cgroup.path.used = 0;
-
- status = f_string_dynamic_append(global.setting->path_cgroup, &rule->cgroup.path);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_append", F_true, F_false);
- }
- else {
- rule->cgroup.groups.used = 0;
-
- for (j = 1; j < cache->content_actions.array[i].used; ++j) {
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_string_dynamic_t), (void **) &rule->cgroup.groups.array, &rule->cgroup.groups.used, &rule->cgroup.groups.size);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_memory_array_increase", F_true, F_false);
-
- break;
- }
-
- rule->cgroup.groups.array[rule->cgroup.groups.used].used = 0;
-
- status = f_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[j], &rule->cgroup.groups.array[rule->cgroup.groups.used]);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true, F_false);
- break;
- }
-
- ++rule->cgroup.groups.used;
- } // for
- }
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- rule->cgroup.path.used = 0;
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- rule->has |= controller_rule_has_cgroup_d;
-
- controller_rule_setting_read_print_values(global, controller_cgroup_s, i, cache);
-
- continue;
- }
-
- if (type == controller_rule_setting_type_limit_e) {
- if (cache->content_actions.array[i].used != 3) {
- controller_rule_setting_read_print_error(&global.main->program.error, "requires three Content", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- if (f_compare_dynamic_partial_string(controller_as_s.string, cache->buffer_item, controller_as_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_as_e;
- }
- else if (f_compare_dynamic_partial_string(controller_core_s.string, cache->buffer_item, controller_core_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_core_e;
- }
- else if (f_compare_dynamic_partial_string(controller_cpu_s.string, cache->buffer_item, controller_cpu_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_cpu_e;
- }
- else if (f_compare_dynamic_partial_string(controller_data_s.string, cache->buffer_item, controller_data_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_data_e;
- }
- else if (f_compare_dynamic_partial_string(controller_fsize_s.string, cache->buffer_item, controller_fsize_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_fsize_e;
- }
- else if (f_compare_dynamic_partial_string(controller_locks_s.string, cache->buffer_item, controller_locks_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_locks_e;
- }
- else if (f_compare_dynamic_partial_string(controller_memlock_s.string, cache->buffer_item, controller_memlock_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_memlock_e;
- }
- else if (f_compare_dynamic_partial_string(controller_msgqueue_s.string, cache->buffer_item, controller_msgqueue_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_msgqueue_e;
- }
- else if (f_compare_dynamic_partial_string(controller_nice_s.string, cache->buffer_item, controller_nice_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_nice_e;
- }
- else if (f_compare_dynamic_partial_string(controller_nofile_s.string, cache->buffer_item, controller_nofile_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_nofile_e;
- }
- else if (f_compare_dynamic_partial_string(controller_nproc_s.string, cache->buffer_item, controller_nproc_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_nproc_e;
- }
- else if (f_compare_dynamic_partial_string(controller_rss_s.string, cache->buffer_item, controller_rss_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_rss_e;
- }
- else if (f_compare_dynamic_partial_string(controller_rtprio_s.string, cache->buffer_item, controller_rtprio_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_rtprio_e;
- }
- else if (f_compare_dynamic_partial_string(controller_rttime_s.string, cache->buffer_item, controller_rttime_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_rttime_e;
- }
- else if (f_compare_dynamic_partial_string(controller_sigpending_s.string, cache->buffer_item, controller_sigpending_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_sigpending_e;
- }
- else if (f_compare_dynamic_partial_string(controller_stack_s.string, cache->buffer_item, controller_stack_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- type = controller_resource_limit_type_stack_e;
- }
- else {
- if (global.main->program.error.verbosity == f_console_verbosity_debug_e) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QUnknown resource limit type '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->action.name_action, global.main->program.error.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_true);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- for (j = 0; j < rule->limits.used; ++j) {
-
- if (type == rule->limits.array[j].type) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QThe resource limit type is already specified%]%r", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- status = F_status_set_error(F_valid_not);
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
- }
- } // for
-
- if (F_status_is_error(status)) continue;
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_limit_set_t), (void **) &rule->limits.array, &rule->limits.used, &rule->limits.size);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_memory_array_increase", F_true, F_false);
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- f_number_signed_t number = 0;
-
- for (j = 1; j < 3; ++j, number = 0) {
-
- status = fl_conversion_dynamic_partial_to_signed_detect(fl_conversion_data_base_10_c, cache->buffer_item, cache->content_actions.array[i].array[j], &number);
-
- if (F_status_set_fine(status) == F_number_positive) {
- status = fl_conversion_dynamic_partial_to_signed_detect(fl_conversion_data_base_10_c, cache->buffer_item, controller_range_after_number_sign(cache->buffer_item, cache->content_actions.array[i].array[j]), &number);
-
- // Restore error on parameter problem.
- if (F_status_set_fine(status) == F_parameter) {
- status = F_status_set_error(F_number_positive);
- }
- }
-
- if (F_status_is_error(status)) {
- status = F_status_set_fine(status);
-
- if (status == F_data_not || status == F_number || status == F_number_overflow || status == F_number_underflow || status == F_number_negative || status == F_number_positive || status == F_number_decimal) {
- if (status == F_number_underflow) {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an unsupported number", cache->content_actions.array[i].array[j], ", the number is too small for this system", i, line_item, global.thread, cache);
- }
- else if (status == F_number_overflow) {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an unsupported number", cache->content_actions.array[i].array[j], ", the number is too large for this system", i, line_item, global.thread, cache);
- }
- else {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an unsupported number", cache->content_actions.array[i].array[j], ", only whole numbers are allowed for a resource limit value", i, line_item, global.thread, cache);
- }
-
- status = F_status_set_error(F_valid_not);
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
- }
- else {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "fl_conversion_dynamic_partial_to_signed_detect", F_true, F_false);
-
- status = F_status_set_error(status);
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
- }
-
- break;
- }
-
- if (j == 1) {
- rule->limits.array[rule->limits.used].value.rlim_cur = number;
- }
- else {
- rule->limits.array[rule->limits.used].value.rlim_max = number;
- }
- } // for
-
- if (F_status_is_error(status)) continue;
-
- rule->limits.array[rule->limits.used++].type = type;
-
- controller_rule_setting_read_print_values(global, controller_limit_s, i, cache);
-
- continue;
- }
-
- if (type == controller_rule_setting_type_name_e || type == controller_rule_setting_type_path_e || type == controller_rule_setting_type_engine_e) {
-
- if (type == controller_rule_setting_type_name_e) {
- setting_value = &rule->name;
- }
- else if (type == controller_rule_setting_type_path_e) {
- setting_value = &rule->path;
- }
- else if (type == controller_rule_setting_type_engine_e) {
- setting_value = &rule->engine;
- }
-
- if (setting_value->used || !cache->content_actions.array[i].used) {
- controller_rule_setting_read_print_error(&global.main->program.error, "requires one or more Content", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- if (type == controller_rule_setting_type_name_e || type == controller_rule_setting_type_engine_e) {
- status = f_rip_dynamic_partial_nulless(cache->buffer_item, cache->content_actions.array[i].array[0], setting_value);
-
- if (type == controller_rule_setting_type_engine_e) {
- rule->engine_arguments.used = 0;
-
- if (cache->content_actions.array[i].used > 1) {
- status = f_memory_array_increase_by(cache->content_actions.array[i].used - 1, sizeof(f_string_dynamic_t), (void **) &rule->engine_arguments.array, &rule->engine_arguments.used, &rule->engine_arguments.size);
-
- for (j = 1; F_status_is_error_not(status) && j < cache->content_actions.array[i].used; ++j, ++rule->engine_arguments.used) {
-
- rule->engine_arguments.array[rule->engine_arguments.used].used = 0;
-
- status = f_string_dynamic_partial_append(cache->buffer_item, cache->content_actions.array[i].array[j], &rule->engine_arguments.array[rule->engine_arguments.used]);
- } // for
- }
- }
-
- if (F_status_is_error(status)) {
- setting_value->used = 0;
-
- if (type == controller_rule_setting_type_engine_e) {
- rule->engine_arguments.used = 0;
- }
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- status = controller_validate_has_graph(*setting_value);
-
- if (status == F_false || F_status_set_fine(status) == F_complete_not_utf) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
- }
-
- if (status == F_false) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QRule setting has an invalid name '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, *setting_value, global.main->program.error.notable);
- fl_print_format("%[', there must be at least 1 graph character.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
- }
- else {
-
- // This function should only return F_complete_not_utf on error.
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_complete_not_utf, "controller_validate_has_graph", F_true, F_false);
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
- }
-
- setting_value->used = 0;
-
- continue;
- }
-
- controller_rule_setting_read_print_value(global, type == controller_rule_setting_type_name_e ? controller_name_s : controller_engine_s, f_string_empty_s, *setting_value, 0);
- }
- else if (type == controller_rule_setting_type_path_e) {
- status = f_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[0], setting_value);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true, F_false);
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- setting_value->used = 0;
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- controller_rule_setting_read_print_value(global, controller_path_s, f_string_empty_s, *setting_value, 0);
- }
-
- continue;
- }
-
- if (type == controller_rule_setting_type_scheduler_e) {
- if (cache->content_actions.array[i].used < 1 || cache->content_actions.array[i].used > 2 || rule->has & controller_rule_has_scheduler_d) {
- controller_rule_setting_read_print_error(&global.main->program.error, "requires either one or two Content", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- if (f_compare_dynamic_partial_string(controller_batch_s.string, cache->buffer_item, controller_batch_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- rule->scheduler.policy = SCHED_BATCH;
- rule->scheduler.priority = 0;
- }
- else if (f_compare_dynamic_partial_string(controller_deadline_s.string, cache->buffer_item, controller_deadline_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- rule->scheduler.policy = SCHED_DEADLINE;
- rule->scheduler.priority = 49;
- }
- else if (f_compare_dynamic_partial_string(controller_fifo_s.string, cache->buffer_item, controller_fifo_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- rule->scheduler.policy = SCHED_FIFO;
- rule->scheduler.priority = 49;
- }
- else if (f_compare_dynamic_partial_string(controller_idle_s.string, cache->buffer_item, controller_idle_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- rule->scheduler.policy = SCHED_IDLE;
- rule->scheduler.priority = 0;
- }
- else if (f_compare_dynamic_partial_string(controller_other_s.string, cache->buffer_item, controller_other_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- rule->scheduler.policy = SCHED_OTHER;
- rule->scheduler.priority = 0;
- }
- else if (f_compare_dynamic_partial_string(controller_round_robin_s.string, cache->buffer_item, controller_round_robin_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- rule->scheduler.policy = SCHED_RR;
- rule->scheduler.priority = 49;
- }
- else {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an unknown scheduler", cache->content_actions.array[i].array[0], "", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- if (cache->content_actions.array[i].used > 1) {
- const bool zero_only = rule->scheduler.policy == SCHED_BATCH || rule->scheduler.policy == SCHED_IDLE || rule->scheduler.policy == SCHED_OTHER;
-
- f_number_signed_t number = 0;
-
- status = fl_conversion_dynamic_partial_to_signed_detect(fl_conversion_data_base_10_c, cache->buffer_item, cache->content_actions.array[i].array[1], &number);
-
- if (F_status_set_fine(status) == F_number_positive) {
- status = fl_conversion_dynamic_partial_to_signed_detect(fl_conversion_data_base_10_c, cache->buffer_item, controller_range_after_number_sign(cache->buffer_item, cache->content_actions.array[i].array[1]), &number);
-
- // Restore error on parameter problem.
- if (F_status_set_fine(status) == F_parameter) {
- status = F_status_set_error(F_number_positive);
- }
- }
-
- if (F_status_is_error(status) || (zero_only && number) || (!zero_only && (number < 1 || number > 99))) {
- status = F_status_set_fine(status);
-
- if ((zero_only && number) || (!zero_only && (number < 1 || number > 99)) || status == F_data_not || status == F_number || status == F_number_overflow || status == F_number_negative || status == F_number_positive) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QRule setting has an invalid number '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_range_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->buffer_item, cache->content_actions.array[i].array[1], global.main->program.error.notable);
-
- if (zero_only) {
- fl_print_format("%[', only%] ", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[0%]%[ is", global.main->program.error.to, global.main->program.error.notable, global.main->program.error.notable, global.main->program.error.context);
- }
- else {
- fl_print_format("%[', only the whole numbers inclusively between%] ", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[1%] %[and%] ", global.main->program.error.to, global.main->program.error.notable, global.main->program.error.notable, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[99%] %[are", global.main->program.error.to, global.main->program.error.notable, global.main->program.error.notable, global.main->program.error.context);
- }
-
- fl_print_format(" allowed for the designated scheduler.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
- }
- else {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, status, "fl_conversion_dynamic_partial_to_signed_detect", F_true, F_false);
- status = F_status_set_error(status);
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
- }
-
- continue;
- }
-
- rule->scheduler.priority = number;
- }
-
- rule->has |= controller_rule_has_scheduler_d;
-
- controller_rule_setting_read_print_values(global, controller_scheduler_s, i, cache);
-
- continue;
- }
-
- if (type == controller_rule_setting_type_timeout_e) {
- if (cache->content_actions.array[i].used != 2) {
- controller_rule_setting_read_print_error(&global.main->program.error, "requires exactly two Content", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- uint8_t timeout_code = 0;
-
- if (f_compare_dynamic_partial_string(controller_kill_s.string, cache->buffer_item, controller_kill_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- timeout_code = controller_rule_timeout_code_kill_d;
- }
- else if (f_compare_dynamic_partial_string(controller_start_s.string, cache->buffer_item, controller_start_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- timeout_code = controller_rule_timeout_code_start_d;
- }
- else if (f_compare_dynamic_partial_string(controller_stop_s.string, cache->buffer_item, controller_stop_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- timeout_code = controller_rule_timeout_code_stop_d;
- }
- else {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QRule setting's first value has '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_range_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->buffer_item, cache->content_actions.array[i].array[0], global.main->program.error.notable);
- fl_print_format("%[' but only supports %r, %r, and %r.%]%r", global.main->program.error.to, global.main->program.error.context, controller_kill_s, controller_start_s, controller_stop_s, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- f_number_unsigned_t number = 0;
-
- status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, cache->buffer_item, cache->content_actions.array[i].array[1], &number);
-
- if (F_status_set_fine(status) == F_number_positive) {
- status = fl_conversion_dynamic_partial_to_unsigned_detect(fl_conversion_data_base_10_c, cache->buffer_item, controller_range_after_number_sign(cache->buffer_item, cache->content_actions.array[i].array[1]), &number);
-
- // Restore error on parameter problem.
- if (F_status_set_fine(status) == F_parameter) {
- status = F_status_set_error(F_number_positive);
- }
- }
-
- if (F_status_is_error(status)) {
- status = F_status_set_fine(status);
-
- if (status == F_number_overflow) {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an unsupported number", cache->content_actions.array[i].array[1], ", the number is too large for this system", i, line_item, global.thread, cache);
- }
- else if (status == F_data_not || status == F_number || status == F_number_underflow || status == F_number_negative || status == F_number_positive || status == F_number_decimal) {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an invalid number", cache->content_actions.array[i].array[1], ", only positive whole numbers are allowed", i, line_item, global.thread, cache);
- }
- else {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, status, "fl_conversion_dynamic_partial_to_signed_detect", F_true, F_false);
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
- }
- else {
- if (timeout_code == controller_rule_timeout_code_kill_d) {
- rule->timeout_kill = number;
- }
- else if (timeout_code == controller_rule_timeout_code_start_d) {
- rule->timeout_start = number;
- }
- else {
- rule->timeout_stop = number;
- }
-
- if (global.main->program.error.verbosity == f_console_verbosity_debug_e || (global.main->program.error.verbosity == f_console_verbosity_verbose_e && (global.main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e))) {
- f_string_static_t name_sub = controller_stop_s;
-
- if (timeout_code == controller_rule_timeout_code_kill_d) {
- name_sub = controller_kill_s;
- }
- else if (timeout_code == controller_rule_timeout_code_start_d) {
- name_sub = controller_start_s;
- }
-
- cache->action.generic.used = 0;
-
- status = f_rip_dynamic_partial_nulless(cache->buffer_item, cache->content_actions.array[i].array[1], &cache->action.generic);
-
- if (F_status_is_error(status)) {
- controller_print_error(global.thread, &global.main->program.error, F_status_set_fine(status), "f_rip_dynamic_partial_nulless", F_true);
-
- break;
- }
-
- controller_rule_setting_read_print_value(global, controller_timeout_s, name_sub, cache->action.generic, 0);
- }
- }
-
- continue;
- }
-
- if (type == controller_rule_setting_type_capability_e || type == controller_rule_setting_type_nice_e || type == controller_rule_setting_type_user_e) {
- if (cache->content_actions.array[i].used != 1 || type == controller_rule_setting_type_capability_e && rule->capability || type == controller_rule_setting_type_group_e && (rule->has & controller_rule_has_group_d) || type == controller_rule_setting_type_nice_e && (rule->has & controller_rule_has_nice_d) || type == controller_rule_setting_type_user_e && (rule->has & controller_rule_has_user_d)) {
- controller_rule_setting_read_print_error(&global.main->program.error, "requires exactly one Content", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- if (type == controller_rule_setting_type_capability_e) {
- cache->action.generic.used = 0;
-
- status = f_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[0], &cache->action.generic);
-
- if (F_status_is_error(status)) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(global.main->program.error.to, global.thread);
-
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true, F_false);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
- }
-
- status = f_capability_from_text(cache->action.generic, &rule->capability);
-
- if (F_status_is_error(status) && F_status_set_fine(status) != F_support_not) {
- if (F_status_set_fine(status) == F_memory_not) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(global.main->program.error.to, global.thread);
-
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_capability_from_text", F_true, F_false);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
-
- status_return = status;
-
- break;
- }
-
- controller_rule_setting_read_print_error(&global.main->program.error, "failed to process the capabilities", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- controller_rule_setting_read_print_value(global, controller_capability_s, f_string_empty_s, cache->action.generic, 0);
- }
- else if (type == controller_rule_setting_type_nice_e) {
- f_number_signed_t number = 0;
-
- status = fl_conversion_dynamic_partial_to_signed_detect(fl_conversion_data_base_10_c, cache->buffer_item, cache->content_actions.array[i].array[0], &number);
-
- if (F_status_set_fine(status) == F_number_positive) {
- status = fl_conversion_dynamic_partial_to_signed_detect(fl_conversion_data_base_10_c, cache->buffer_item, controller_range_after_number_sign(cache->buffer_item, cache->content_actions.array[i].array[0]), &number);
-
- // Restore error on parameter problem.
- if (F_status_set_fine(status) == F_parameter) {
- status = F_status_set_error(F_number_positive);
- }
- }
-
- if (F_status_is_error(status) || number < -20 || number > 19) {
- status = F_status_set_fine(status);
-
- if (number < -20 || number > 19 || status == F_data_not || status == F_number || status == F_number_overflow || status == F_number_underflow || status == F_number_decimal) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QRule setting has an invalid number '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_range_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->buffer_item, cache->content_actions.array[i].array[0], global.main->program.error.notable);
- fl_print_format("%[', only the whole numbers inclusively between%] ", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[-20%]", global.main->program.error.to, global.main->program.error.notable, global.main->program.error.notable);
- fl_print_format(" %[and%] ", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context);
- fl_print_format("%[19%]", global.main->program.error.to, global.main->program.error.notable, global.main->program.error.notable);
- fl_print_format(" %[are allowed.%]%r", global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
- }
- else {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, status, "fl_conversion_dynamic_partial_to_signed_detect", F_true, F_false);
- status = F_status_set_error(status);
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
- }
- }
- else {
- rule->nice = number;
- rule->has |= controller_rule_has_nice_d;
-
- if ((global.main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) || global.main->program.error.verbosity == f_console_verbosity_verbose_e) {
- cache->action.generic.used = 0;
-
- status = f_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[0], &cache->action.generic);
-
- if (F_status_is_error(status)) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(global.main->program.error.to, global.thread);
-
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true, F_false);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
- }
-
- if (F_status_is_error_not(status)) {
- controller_rule_setting_read_print_value(global, controller_nice_s, f_string_empty_s, cache->action.generic, 0);
- }
- }
- }
- }
- else if (type == controller_rule_setting_type_user_e) {
- uid_t number = 0;
-
- status = controller_get_id_user(cache->buffer_item, cache->content_actions.array[i].array[0], cache, &number);
-
- if (F_status_is_error(status)) {
- status = F_status_set_fine(status);
-
- if (status == F_exist_not) {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an invalid user", cache->content_actions.array[i].array[0], ", because no user was found by that name", i, line_item, global.thread, cache);
- }
- else if (status == F_number_too_large) {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an invalid user", cache->content_actions.array[i].array[0], ", because the given ID is too large", i, line_item, global.thread, cache);
- }
- else if (status == F_number) {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an invalid user", cache->content_actions.array[i].array[0], ", because the given ID is not a valid supported number", i, line_item, global.thread, cache);
- }
- else {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, status, "controller_get_id_user", F_true, F_false);
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(status);
- }
- }
- else {
- rule->user = number;
- rule->has |= controller_rule_has_user_d;
-
- if (global.main->program.error.verbosity == f_console_verbosity_debug_e || (global.main->program.error.verbosity == f_console_verbosity_verbose_e && (global.main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e))) {
- cache->action.generic.used = 0;
-
- status = f_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[0], &cache->action.generic);
-
- controller_rule_setting_read_print_value(global, controller_user_s, f_string_empty_s, cache->action.generic, 0);
- }
- }
- }
-
- continue;
- }
-
- if (type == controller_rule_setting_type_group_e) {
- if (!cache->content_actions.array[i].used) {
- controller_rule_setting_read_print_error(&global.main->program.error, "requires one or more Content", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- gid_t number = 0;
-
- rule->groups.used = 0;
-
- for (j = 0; j < cache->content_actions.array[i].used; ++j) {
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_int32s_t), (void **) &rule->groups.array, &rule->groups.used, &rule->groups.size);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_memory_array_increase", F_true, F_false);
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- status = controller_get_id_group(cache->buffer_item, cache->content_actions.array[i].array[j], cache, &number);
-
- if (F_status_is_error(status)) {
- status = F_status_set_fine(status);
-
- if (status == F_exist_not) {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an invalid group", cache->content_actions.array[i].array[j], ", because no group was found by that name", i, line_item, global.thread, cache);
- }
- else if (status == F_number_too_large) {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an invalid group", cache->content_actions.array[i].array[j], ", because the given ID is too large", i, line_item, global.thread, cache);
- }
- else if (status == F_number) {
- controller_rule_setting_read_print_error_with_range(&global.main->program.error, " has an invalid group", cache->content_actions.array[i].array[j], ", because the given ID is not a valid supported number", i, line_item, global.thread, cache);
- }
- else {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, status, "f_account_group_id_by_name", F_true, F_false);
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(status);
- }
- }
- else {
- if (rule->has & controller_rule_has_group_d) {
- rule->groups.array[rule->groups.used++] = number;
- }
- else {
- rule->group = number;
- rule->has |= controller_rule_has_group_d;
- }
- }
- } // for
-
- controller_rule_setting_read_print_values(global, controller_group_s, i, cache);
-
- continue;
- }
-
- if (type == controller_rule_setting_type_environment_e) {
- setting_values = &rule->environment;
-
- for (j = 0; j < cache->content_actions.array[i].used; ++j) {
-
- status = f_memory_array_increase(controller_common_allocation_small_d, sizeof(f_string_dynamic_t), (void **) &setting_values->array, &setting_values->used, &setting_values->size);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_memory_array_increase", F_true, F_false);
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- setting_values->array[setting_values->used].used = 0;
-
- status = f_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[j], &setting_values->array[setting_values->used]);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true, F_false);
-
- setting_values->array[setting_values->used].used = 0;
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- status = controller_validate_environment_name(setting_values->array[setting_values->used]);
-
- if (status == F_false || F_status_set_fine(status) == F_complete_not_utf) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- if (status == F_false) {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QRule setting has an invalid environment variable name '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, global.main->program.error.to, global.main->program.error.notable, setting_values->array[setting_values->used], global.main->program.error.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, global.main->program.error.to, global.main->program.error.context, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
- }
- else {
-
- // This function should only return F_complete_not_utf on error.
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_complete_not_utf, "controller_validate_environment_name", F_true, F_false);
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
- }
-
- setting_values->array[setting_values->used].used = 0;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- ++setting_values->used;
- } // for
-
- rule->has |= controller_rule_has_environment_d;
-
- if (cache->content_actions.array[i].used) {
- controller_rule_setting_read_print_values(global, controller_environment_s, i, cache);
- }
- else {
- if (global.main->program.error.verbosity == f_console_verbosity_debug_e || (global.main->program.error.verbosity == f_console_verbosity_verbose_e && (global.main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e))) {
- controller_lock_print(global.main->program.output.to, global.thread);
-
- fl_print_format("%rProcessing rule item action '%[%r%]' setting value to an empty set.%r", global.main->program.output.to, f_string_eol_s, global.main->program.context.set.title, controller_environment_s, global.main->program.context.set.title, f_string_eol_s);
-
- controller_unlock_print_flush(global.main->program.output.to, global.thread);
- }
- }
-
- continue;
- }
-
- // The "on" Rule Setting.
- if (cache->content_actions.array[i].used != 4) {
- controller_rule_setting_read_print_error(&global.main->program.error, "requires exactly four Content", i, line_item, global.thread, cache);
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- if (f_compare_dynamic_partial_string(controller_freeze_s.string, cache->buffer_item, controller_freeze_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- action = controller_rule_action_type_freeze_e;
- }
- else if (f_compare_dynamic_partial_string(controller_kill_s.string, cache->buffer_item, controller_kill_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- action = controller_rule_action_type_kill_e;
- }
- else if (f_compare_dynamic_partial_string(controller_pause_s.string, cache->buffer_item, controller_pause_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- action = controller_rule_action_type_pause_e;
- }
- else if (f_compare_dynamic_partial_string(controller_reload_s.string, cache->buffer_item, controller_reload_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- action = controller_rule_action_type_reload_e;
- }
- else if (f_compare_dynamic_partial_string(controller_restart_s.string, cache->buffer_item, controller_restart_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- action = controller_rule_action_type_restart_e;
- }
- else if (f_compare_dynamic_partial_string(controller_resume_s.string, cache->buffer_item, controller_resume_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- action = controller_rule_action_type_resume_e;
- }
- else if (f_compare_dynamic_partial_string(controller_start_s.string, cache->buffer_item, controller_start_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- action = controller_rule_action_type_start_e;
- }
- else if (f_compare_dynamic_partial_string(controller_stop_s.string, cache->buffer_item, controller_stop_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- action = controller_rule_action_type_stop_e;
- }
- else if (f_compare_dynamic_partial_string(controller_thaw_s.string, cache->buffer_item, controller_thaw_s.used, cache->content_actions.array[i].array[0]) == F_equal_to) {
- action = controller_rule_action_type_thaw_e;
- }
- else {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- f_thread_mutex_lock(&global.thread->lock.print);
-
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QRule setting's second value has '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_range_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->buffer_item, cache->content_actions.array[i].array[1], global.main->program.error.notable);
- fl_print_format("%[' but only supports %r, %r, %r, %r, %r", global.main->program.error.to, global.main->program.error.context, controller_freeze_s, controller_kill_s, controller_pause_s, controller_reload_s, controller_restart_s);
- fl_print_format("%r, %r, %r, and %r.%]%r", global.main->program.error.to, controller_resume_s, controller_start_s, controller_stop_s, controller_thaw_s, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- for (j = 0; j < rule->ons.used; ++j) {
- if (rule->ons.array[j].action == action) break;
- } // for
-
- if (j == rule->ons.used) {
- status = controller_rule_ons_increase(&rule->ons);
- }
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "controller_rule_ons_increase", F_true, F_false);
- }
- else {
- if (f_compare_dynamic_partial_string(controller_need_s.string, cache->buffer_item, controller_need_s.used, cache->content_actions.array[i].array[1]) == F_equal_to) {
- setting_values = &rule->ons.array[j].need;
- }
- else if (f_compare_dynamic_partial_string(controller_want_s.string, cache->buffer_item, controller_want_s.used, cache->content_actions.array[i].array[1]) == F_equal_to) {
- setting_values = &rule->ons.array[j].want;
- }
- else if (f_compare_dynamic_partial_string(controller_wish_s.string, cache->buffer_item, controller_wish_s.used, cache->content_actions.array[i].array[1]) == F_equal_to) {
- setting_values = &rule->ons.array[j].wish;
- }
- else {
- if (global.main->program.error.verbosity > f_console_verbosity_quiet_e) {
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(global.main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QRule setting's second value has '%]", global.main->program.error.to, f_string_eol_s, global.main->program.error.context, global.main->program.error.prefix, global.main->program.error.context);
- fl_print_format(f_string_format_Q_range_single_s.string, global.main->program.error.to, global.main->program.error.notable, cache->buffer_item, cache->content_actions.array[i].array[1], global.main->program.error.notable);
- fl_print_format("%[' but only supports %r, %r, and %r.%]%r", global.main->program.error.to, global.main->program.error.context, controller_need_s, controller_want_s, controller_wish_s, global.main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&global.main->program.error, cache->action, F_false);
-
- controller_unlock_print_flush(global.main->program.error.to, global.thread);
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = F_status_set_error(F_valid_not);
- }
-
- continue;
- }
-
- status = f_memory_array_increase_by(controller_common_allocation_small_d, sizeof(f_string_dynamic_t), (void **) &setting_values->array, &setting_values->used, &setting_values->size);
-
- if (F_status_is_error(status)) {
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_memory_array_increase_by", F_true, F_false);
- }
- }
-
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- status = controller_rule_id_construct(global, cache->buffer_item, cache->content_actions.array[i].array[2], cache->content_actions.array[i].array[3], &setting_values->array[setting_values->used]);
-
- if (F_status_is_error(status)) {
- setting_values->array[setting_values->used].used = 0;
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->action.line_item, &global.main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_rule_item_print_error(global.thread, &global.main->program.error, cache->action, F_false, F_status_set_fine(status));
-
- continue;
- }
-
- cache->buffer_path.used = 0;
-
- status = f_file_name_base(setting_values->array[setting_values->used], &cache->buffer_path);
-
- if (F_status_is_error(status)) {
- setting_values->array[setting_values->used].used = 0;
-
- controller_rule_print_error(global.thread, &global.main->program.error, cache->action, F_status_set_fine(status), "f_file_name_base", F_true, F_false);
-
- if (F_status_set_fine(status) == F_memory_not) {
- status_return = status;
-
- break;
- }
-
- if (F_status_is_error_not(status_return)) {
- status_return = status;
- }
-
- continue;
- }
-
- rule->ons.array[j].action = action;
-
- ++setting_values->used;
-
- if (j == rule->ons.used) {
- ++rule->ons.used;
- }
-
- if (global.main->program.error.verbosity == f_console_verbosity_debug_e || (global.main->program.error.verbosity == f_console_verbosity_verbose_e && (global.main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e))) {
- controller_lock_print(global.main->program.output.to, global.thread);
-
- fl_print_format("%rProcessing rule item action '%[%r%]', adding ", global.main->program.output.to, f_string_eol_s, global.main->program.context.set.title, controller_on_s, global.main->program.context.set.title);
- fl_print_format("'%[%/Q%]' of ", global.main->program.output.to, global.main->program.context.set.notable, cache->buffer_item, cache->content_actions.array[i].array[1], global.main->program.context.set.notable);
- fl_print_format("'%[%/Q%]/", global.main->program.output.to, global.main->program.context.set.important, cache->buffer_item, cache->content_actions.array[i].array[2], global.main->program.context.set.important);
- fl_print_format("%[%/Q%]'.%r", global.main->program.output.to, global.main->program.context.set.important, cache->buffer_item, cache->content_actions.array[i].array[3], global.main->program.context.set.important, f_string_eol_s);
-
- controller_unlock_print_flush(global.main->program.output.to, global.thread);
- }
- } // for
-
- // Restore the current name item and line number, which there should already be enough allocated space for.
- memcpy(cache->action.name_item.string, name_item, sizeof(f_char_t) * length_name_item);
-
- cache->action.name_item.string[length_name_item] = 0;
- cache->action.name_item.used = length_name_item;
-
- cache->action.line_item = line_item;
-
- return status_return;
- }
-#endif // _di_controller_rule_setting_read_
-
-#ifndef _di_controller_rule_validate_
- void controller_rule_validate(const controller_global_t global, const controller_rule_t rule, const uint8_t action, const uint8_t options, controller_cache_t * const cache) {
-
- controller_main_t * const main = global.main;
-
- switch (action) {
- case controller_rule_action_type_freeze_e:
- case controller_rule_action_type_kill_e:
- case controller_rule_action_type_pause_e:
- case controller_rule_action_type_reload_e:
- case controller_rule_action_type_restart_e:
- case controller_rule_action_type_resume_e:
- case controller_rule_action_type_start_e:
- case controller_rule_action_type_stop_e:
- case controller_rule_action_type_thaw_e:
- break;
-
- default:
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(main->program.error.to, global.thread);
-
- fl_print_format("%r%[%QUnsupported action type '%]", main->program.error.to, f_string_eol_s, main->program.error.context, main->program.error.prefix, main->program.error.context);
- fl_print_format(f_string_format_r_single_s.string, main->program.error.to, main->program.error.notable, controller_rule_action_type_name(action), main->program.error.notable);
- fl_print_format("%[' while attempting to validate rule execution.%]%r", main->program.error.to, main->program.error.context, main->program.error.context, f_string_eol_s);
-
- controller_rule_print_error_cache(&main->program.error, cache->action, F_true);
-
- controller_unlock_print_flush(main->program.error.to, global.thread);
- }
-
- return;
- }
-
- f_number_unsigned_t i = 0;
- f_number_unsigned_t j = 0;
-
- // Find at least one of the requested action.
- {
- bool missing = F_true;
-
- for (; i < rule.items.used; ++i) {
-
- for (j = 0; j < rule.items.array[i].actions.used; ++j) {
-
- if (!action || rule.items.array[i].actions.array[j].type == action) {
- missing = F_false;
-
- break;
- }
- } // for
- } // for
-
- if (missing) {
- controller_lock_print(main->program.output.to, global.thread);
-
- if (rule.items.used) {
- fl_print_format("%rRule '", main->program.output.to, f_string_eol_s);
- fl_print_format("%[%Q%]' has no '", main->program.output.to, main->program.context.set.title, rule.name, main->program.context.set.title);
- fl_print_format("%[%r%]' action to execute and would '", main->program.output.to, main->program.context.set.title, controller_rule_action_type_name(action), main->program.context.set.title);
- fl_print_format("%[%r%]' because it is '", main->program.output.to, main->program.context.set.important, options & controller_process_option_require_d ? controller_fail_s : controller_succeed_s, main->program.context.set.important);
- fl_print_format("%[%r%]'.%r", main->program.output.to, main->program.context.set.important, options & controller_process_option_require_d ? controller_required_s : controller_optional_s, main->program.context.set.important, f_string_eol_s);
- }
- else {
- fl_print_format("%rRule '", main->program.output.to, f_string_eol_s);
- fl_print_format("%[%Q%]' has no known '", main->program.output.to, main->program.context.set.title, rule.name, main->program.context.set.title);
- fl_print_format("%[%r %r%]' (such as ", main->program.output.to, main->program.context.set.title, controller_rule_s, controller_type_s, main->program.context.set.title);
- fl_print_format("'%[%r%]', ", main->program.output.to, main->program.context.set.title, controller_command_s, main->program.context.set.title);
- fl_print_format("'%[%r%]', ", main->program.output.to, main->program.context.set.title, controller_service_s, main->program.context.set.title);
- fl_print_format("'%[%r%]', or ", main->program.output.to, main->program.context.set.title, controller_script_s, main->program.context.set.title);
- fl_print_format("'%[%r%]'", main->program.output.to, main->program.context.set.title, controller_utility_s, main->program.context.set.title);
- fl_print_format(") and would '%[%r%]' because it is '", main->program.output.to, main->program.context.set.important, options & controller_process_option_require_d ? controller_fail_s : controller_succeed_s, main->program.context.set.important);
- fl_print_format("%[%r%]'.%r", main->program.output.to, main->program.context.set.important, options & controller_process_option_require_d ? controller_required_s : controller_optional_s, main->program.context.set.important, f_string_eol_s);
- }
-
- controller_unlock_print_flush(main->program.output.to, global.thread);
- }
- }
-
- controller_lock_print(main->program.output.to, global.thread);
-
- fl_print_format("%rRule %[%Q%] {%r", main->program.output.to, f_string_eol_s, main->program.context.set.title, rule.alias, main->program.context.set.title, f_string_eol_s);
-
- // Name.
- fl_print_format(" %[%r%] %Q%r", main->program.output.to, main->program.context.set.important, controller_name_s, main->program.context.set.important, rule.name, f_string_eol_s);
-
- // Capability.
- fl_print_format(" %[%r%] ", main->program.output.to, main->program.context.set.important, controller_capability_s, main->program.context.set.important);
-
- if (f_capability_supported()) {
- if (rule.capability) {
- cache->action.generic.used = 0;
-
- if (F_status_is_error_not(f_capability_to_text(rule.capability, &cache->action.generic))) {
- f_print_dynamic_safely(cache->action.generic, main->program.output.to);
- }
- }
-
- f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
- }
- else {
- fl_print_format("%[(unsupported)%]%r", main->program.output.to, main->program.context.set.warning, main->program.context.set.warning, f_string_eol_s);
- }
-
- // Control Group.
- fl_print_format(" %[%r%]", main->program.output.to, main->program.context.set.important, controller_cgroup_s, main->program.context.set.important);
-
- if (rule.has & controller_rule_has_cgroup_d) {
- fl_print_format(" %r", main->program.output.to, rule.cgroup.as_new ? controller_new_s : controller_existing_s);
-
- for (i = 0; i < rule.cgroup.groups.used; ++i) {
-
- if (rule.cgroup.groups.array[i].used) {
- fl_print_format(" %Q", main->program.output.to, rule.cgroup.groups.array[i]);
- }
- } // for
- }
-
- f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
-
- // How.
- fl_print_format(" %[%r%] %r%r", main->program.output.to, main->program.context.set.important, controller_how_s, main->program.context.set.important, options & controller_process_option_asynchronous_d ? controller_asynchronous_s : controller_synchronous_s, f_string_eol_s);
-
- // Nice.
- fl_print_format(" %[%r%]", main->program.output.to, main->program.context.set.important, controller_nice_s, main->program.context.set.important);
-
- if (rule.has & controller_rule_has_nice_d) {
- fl_print_format(" %i", main->program.output.to, rule.nice);
- }
-
- f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
-
- // Scheduler.
- fl_print_format(" %[%r%]", main->program.output.to, main->program.context.set.important, controller_scheduler_s, main->program.context.set.important);
-
- if (rule.has & controller_rule_has_scheduler_d) {
- f_string_static_t policy = f_string_static_t_initialize;
-
- if (rule.scheduler.policy == SCHED_BATCH) {
- policy = controller_batch_s;
- }
- else if (rule.scheduler.policy == SCHED_DEADLINE) {
- policy = controller_deadline_s;
- }
- else if (rule.scheduler.policy == SCHED_FIFO) {
- policy = controller_fifo_s;
- }
- else if (rule.scheduler.policy == SCHED_IDLE) {
- policy = controller_idle_s;
- }
- else if (rule.scheduler.policy == SCHED_OTHER) {
- policy = controller_other_s;
- }
- else if (rule.scheduler.policy == SCHED_RR) {
- policy = controller_round_robin_s;
- }
-
- fl_print_format(" %r %i", main->program.output.to, policy, rule.scheduler.priority);
- }
-
- f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
-
- // Engine.
- if (rule.engine_arguments.used) {
- fl_print_format(" %[%r%] %Q", main->program.output.to, main->program.context.set.important, controller_engine_s, main->program.context.set.important, rule.engine);
-
- for (i = 0; i < rule.engine_arguments.used; ++i) {
-
- if (rule.engine_arguments.array[i].used) {
- fl_print_format(" %Q", main->program.output.to, rule.engine_arguments.array[i]);
- }
- } // for
-
- fl_print_format("%r", main->program.output.to, f_string_eol_s);
- }
- else {
- fl_print_format(" %[%r%] %Q%r", main->program.output.to, main->program.context.set.important, controller_engine_s, main->program.context.set.important, rule.engine, f_string_eol_s);
- }
-
- // User.
- fl_print_format(" %[%r%]", main->program.output.to, main->program.context.set.important, controller_user_s, main->program.context.set.important);
-
- if (rule.has & controller_rule_has_user_d) {
- fl_print_format(" %i", main->program.output.to, rule.user);
- }
-
- f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
-
- // Wait.
- fl_print_format(" %[%r%] %r%r", main->program.output.to, main->program.context.set.important, controller_wait_s, main->program.context.set.important, options & controller_process_option_wait_d ? controller_yes_s : controller_no_s, f_string_eol_s);
-
- // Affinity.
- fl_print_format(" %[%r%] {%r", main->program.output.to, main->program.context.set.important, controller_affinity_s, main->program.context.set.important, f_string_eol_s);
-
- for (i = 0; i < rule.affinity.used; ++i) {
- fl_print_format(" %i%r", main->program.output.to, rule.affinity.array[i], f_string_eol_s);
- } // for
-
- // Define.
- fl_print_format(" }%r %[%r%] {%r", main->program.output.to, f_string_eol_s, main->program.context.set.important, controller_define_s, main->program.context.set.important, f_string_eol_s);
-
- for (i = 0; i < rule.define.used; ++i) {
-
- if (rule.define.array[i].key.used && rule.define.array[i].value.used) {
- fl_print_format(" %Q %[=%] %Q%r", main->program.output.to, rule.define.array[i].key, main->program.context.set.important, main->program.context.set.important, rule.define.array[i].value, f_string_eol_s);
- }
- } // for
-
- // Environment.
- fl_print_format(" }%r %[%r%] {%r", main->program.output.to, f_string_eol_s, main->program.context.set.important, controller_environment_s, main->program.context.set.important, f_string_eol_s);
-
- for (i = 0; i < rule.environment.used; ++i) {
-
- if (rule.environment.array[i].used) {
- fl_print_format(" %Q%r", main->program.output.to, rule.environment.array[i], f_string_eol_s);
- }
- } // for
-
- fl_print_format(" }%r %[%r%] {%r", main->program.output.to, f_string_eol_s, main->program.context.set.important, controller_parameter_s, main->program.context.set.important, f_string_eol_s);
-
- // Parameter.
- for (i = 0; i < rule.parameter.used; ++i) {
-
- if (rule.parameter.array[i].key.used && rule.parameter.array[i].value.used) {
- fl_print_format(" %Q %[=%] %Q%r", main->program.output.to, rule.parameter.array[i].key, main->program.context.set.important, main->program.context.set.important, rule.parameter.array[i].value, f_string_eol_s);
- }
- } // for
-
- // Group.
- fl_print_format(" }%r %[%r%] {%r", main->program.output.to, f_string_eol_s, main->program.context.set.important, controller_group_s, main->program.context.set.important, f_string_eol_s);
-
- if (rule.has & controller_rule_has_group_d) {
- fl_print_format(" %i%r", main->program.output.to, rule.group, f_string_eol_s);
-
- for (i = 0; i < rule.groups.used; ++i) {
- fl_print_format(" %i%r", main->program.output.to, rule.groups.array[i], f_string_eol_s);
- } // for
- }
-
- // Limit.
- fl_print_format(" }%r %[%r%] {%r", main->program.output.to, f_string_eol_s, main->program.context.set.important, controller_limit_s, main->program.context.set.important, f_string_eol_s);
-
- for (i = 0; i < rule.limits.used; ++i) {
- fl_print_format(" %Q %[=%] %un %un%r", main->program.output.to, controller_rule_setting_limit_type_name(rule.limits.array[i].type), main->program.context.set.important, main->program.context.set.important, rule.limits.array[i].value.rlim_cur, rule.limits.array[i].value.rlim_max, f_string_eol_s);
- } // for
-
- // On.
- fl_print_format(" }%r %[%r%] {%r", main->program.output.to, f_string_eol_s, main->program.context.set.important, controller_on_s, main->program.context.set.important, f_string_eol_s);
-
- for (i = 0; i < rule.ons.used; ++i) {
-
- fl_print_format(" %[%r%] {%r", main->program.output.to, main->program.context.set.important, controller_action_s, main->program.context.set.important, f_string_eol_s);
-
- {
- f_string_static_t action = f_string_static_t_initialize;
-
- if (rule.ons.array[i].action == controller_rule_action_type_freeze_e) {
- action = controller_freeze_s;
- }
- else if (rule.ons.array[i].action == controller_rule_action_type_kill_e) {
- action = controller_kill_s;
- }
- else if (rule.ons.array[i].action == controller_rule_action_type_pause_e) {
- action = controller_pause_s;
- }
- else if (rule.ons.array[i].action == controller_rule_action_type_reload_e) {
- action = controller_reload_s;
- }
- else if (rule.ons.array[i].action == controller_rule_action_type_restart_e) {
- action = controller_restart_s;
- }
- else if (rule.ons.array[i].action == controller_rule_action_type_resume_e) {
- action = controller_resume_s;
- }
- else if (rule.ons.array[i].action == controller_rule_action_type_start_e) {
- action = controller_start_s;
- }
- else if (rule.ons.array[i].action == controller_rule_action_type_stop_e) {
- action = controller_stop_s;
- }
- else if (rule.ons.array[i].action == controller_rule_action_type_thaw_e) {
- action = controller_thaw_s;
- }
-
- fl_print_format(" %[%r%] %r%r", main->program.output.to, main->program.context.set.important, controller_type_s, main->program.context.set.important, action, f_string_eol_s);
- }
-
- fl_print_format(" %[%r%] {%r", main->program.output.to, main->program.context.set.important, controller_need_s, main->program.context.set.important, f_string_eol_s);
-
- for (j = 0; j < rule.ons.array[i].need.used; ++j) {
-
- if (rule.ons.array[i].need.array[j].used) {
- fl_print_format(" %Q%r", main->program.output.to, rule.ons.array[i].need.array[j], f_string_eol_s);
- }
- } // for
-
- fl_print_format(" }%r %[%r%] {%r", main->program.output.to, f_string_eol_s, main->program.context.set.important, controller_want_s, main->program.context.set.important, f_string_eol_s);
-
- for (j = 0; j < rule.ons.array[i].want.used; ++j) {
-
- if (rule.ons.array[i].want.array[j].used) {
- fl_print_format(" %Q%r", main->program.output.to, rule.ons.array[i].want.array[j], f_string_eol_s);
- }
- } // for
-
- fl_print_format(" }%r %[%r%] {%r", main->program.output.to, f_string_eol_s, main->program.context.set.important, controller_wish_s, main->program.context.set.important, f_string_eol_s);
-
- for (j = 0; j < rule.ons.array[i].wish.used; ++j) {
-
- if (rule.ons.array[i].wish.array[j].used) {
- fl_print_format(" %Q%r", main->program.output.to, rule.ons.array[i].wish.array[j], f_string_eol_s);
- }
- } // for
-
- fl_print_format(" }%r }%r", main->program.output.to, f_string_eol_s, f_string_eol_s);
- } // for
-
- fl_print_format(" }%r", main->program.output.to, f_string_eol_s);
-
- // Items.
- if (rule.items.used) {
- controller_rule_action_t *action = 0;
- controller_rule_item_t *item = 0;
- controller_rule_rerun_item_t *rerun_item = 0;
-
- f_number_unsigned_t j = 0;
- f_number_unsigned_t k = 0;
- f_number_unsigned_t l = 0;
-
- for (i = 0; i < rule.items.used; ++i) {
-
- item = &rule.items.array[i];
-
- fl_print_format(" %[%r%] {%r", main->program.output.to, main->program.context.set.important, controller_item_s, main->program.context.set.important, f_string_eol_s);
-
- // Type.
- fl_print_format(" %[%r%] %Q%r", main->program.output.to, main->program.context.set.important, controller_type_s, main->program.context.set.important, controller_rule_item_type_name(item->type), f_string_eol_s);
-
- // Pid file.
- fl_print_format(" %[%r%]", main->program.output.to, main->program.context.set.important, controller_pid_file_s, main->program.context.set.important);
- if (item->pid_file.used) {
- fl_print_format(" %Q", main->program.output.to, item->pid_file);
- }
- f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
-
- // With.
- fl_print_format(" %[%r%]", main->program.output.to, main->program.context.set.important, controller_with_s, main->program.context.set.important);
- if (item->with & controller_with_full_path_d) {
- fl_print_format(" %r", main->program.output.to, controller_full_path_s);
- }
- if (item->with & controller_with_session_new_d) {
- fl_print_format(" %r", main->program.output.to, controller_session_new_s);
- }
- if (item->with & controller_with_session_same_d) {
- fl_print_format(" %r", main->program.output.to, controller_session_same_s);
- }
- f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
-
- // Actions.
- for (j = 0; j < item->actions.used; ++j) {
-
- action = &item->actions.array[j];
-
- fl_print_format(" %[%r%] {%r", main->program.output.to, main->program.context.set.important, controller_action_s, main->program.context.set.important, f_string_eol_s);
- fl_print_format(" %[%r%] %r%r", main->program.output.to, main->program.context.set.important, controller_type_s, main->program.context.set.important, controller_rule_action_type_name(action->type), f_string_eol_s);
-
- if (item->type == controller_rule_item_type_script_e || item->type == controller_rule_item_type_utility_e) {
- fl_print_format(" %[%r%] {%r", main->program.output.to, main->program.context.set.important, controller_parameter_s, main->program.context.set.important, f_string_eol_s);
-
- if (action->parameters.used) {
- if (action->parameters.array[0].used) {
- f_print_terminated(" ", main->program.output.to);
-
- for (k = 0; k < action->parameters.array[0].used; ++k) {
-
- if (action->parameters.array[0].string[k] == f_fss_eol_s.string[0]) {
- if (k + 1 < action->parameters.array[0].used) {
- fl_print_format("%r ", main->program.output.to, f_string_eol_s);
- }
- }
- else {
- f_print_character_safely(action->parameters.array[0].string[k], main->program.output.to);
- }
- } // for
- }
-
- f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
- }
-
- fl_print_format(" }%r", main->program.output.to, f_string_eol_s);
- }
- else {
- for (k = 0; k < action->parameters.used; ++k) {
- fl_print_format(" %[%r%] %Q%r", main->program.output.to, main->program.context.set.important, controller_parameter_s, main->program.context.set.important, action->parameters.array[k], f_string_eol_s);
- } // for
- }
-
- if (action->ikis.used) {
- fl_print_format(" %[%r%] {%r", main->program.output.to, main->program.context.set.important, controller_iki_s, main->program.context.set.important, f_string_eol_s);
-
- for (k = 0; k < action->ikis.used; ++k) {
-
- for (l = 0; l < action->ikis.array[j].vocabulary.used; ++l) {
-
- fl_print_format(" %[[%]%ul%[]%]", main->program.output.to, main->program.context.set.important, main->program.context.set.important, k, main->program.context.set.important, main->program.context.set.important);
- fl_print_format(" %/Q %[:%] %/Q%r", main->program.output.to, action->parameters.array[k], action->ikis.array[k].vocabulary.array[l], main->program.context.set.important, main->program.context.set.important, action->parameters.array[k], action->ikis.array[k].content.array[l], f_string_eol_s);
- } // for
- } // for
-
- fl_print_format(" }%r", main->program.output.to, f_string_eol_s);
- }
-
- fl_print_format(" }%r", main->program.output.to, f_string_eol_s);
- } // for
-
- // Rerun.
- fl_print_format(" %[%r%] {%r", main->program.output.to, main->program.context.set.important, controller_rerun_s, main->program.context.set.important, f_string_eol_s);
- for (j = 0; j < controller_rule_action_execute_type__enum_size_e; ++j) {
-
- for (k = 0; k < 2; ++k) {
- if (!k && (item->reruns[j].is & controller_rule_rerun_is_failure_d)) {
- rerun_item = &item->reruns[j].failure;
- }
- else if (k && (item->reruns[j].is & controller_rule_rerun_is_success_d)) {
- rerun_item = &item->reruns[j].success;
- }
- else {
- rerun_item = 0;
- continue;
- }
-
- fl_print_format(" %[", main->program.output.to, main->program.context.set.important);
- switch (j) {
- case controller_rule_action_execute_type_freeze_e:
- f_print_dynamic_raw(controller_freeze_s, main->program.output.to);
- break;
-
- case controller_rule_action_execute_type_kill_e:
- f_print_dynamic_raw(controller_kill_s, main->program.output.to);
- break;
-
- case controller_rule_action_execute_type_pause_e:
- f_print_dynamic_raw(controller_pause_s, main->program.output.to);
- break;
-
- case controller_rule_action_execute_type_reload_e:
- f_print_dynamic_raw(controller_reload_s, main->program.output.to);
- break;
-
- case controller_rule_action_execute_type_restart_e:
- f_print_dynamic_raw(controller_restart_s, main->program.output.to);
- break;
-
- case controller_rule_action_execute_type_resume_e:
- f_print_dynamic_raw(controller_resume_s, main->program.output.to);
- break;
-
- case controller_rule_action_execute_type_start_e:
- f_print_dynamic_raw(controller_start_s, main->program.output.to);
- break;
-
- case controller_rule_action_execute_type_stop_e:
- f_print_dynamic_raw(controller_stop_s, main->program.output.to);
- break;
-
- case controller_rule_action_execute_type_thaw_e:
- f_print_dynamic_raw(controller_thaw_s, main->program.output.to);
- break;
-
- default:
- break;
- }
-
- fl_print_format("%] %r", main->program.output.to, main->program.context.set.important, k ? controller_success_s : controller_failure_s);
- fl_print_format(" %r %ul %r %ul", main->program.output.to, controller_delay_s, rerun_item->delay, controller_max_s, rerun_item->max);
-
- if (!k && (item->reruns[j].is & controller_rule_rerun_is_failure_reset_d) || k && (item->reruns[j].is & controller_rule_rerun_is_success_reset_d)) {
- fl_print_format(" %r", main->program.output.to, controller_reset_s);
- }
-
- f_print_dynamic_raw(f_string_eol_s, main->program.output.to);
- } // for
- } // for
- fl_print_format(" }%r", main->program.output.to, f_string_eol_s);
-
- fl_print_format(" }%r", main->program.output.to, f_string_eol_s);
- } // for
- }
-
- fl_print_format("}%r", main->program.output.to, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.output.to, global.thread);
- }
-#endif // _di_controller_rule_validate_
-
-#ifndef _di_controller_rule_wait_all_
- f_status_t controller_rule_wait_all(const controller_global_t global, const bool is_normal, const bool required) {
-
- f_status_t status_lock = controller_lock_read(is_normal, global.thread, &global.thread->lock.process);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- return status_lock;
- }
-
- if (!global.thread->processs.used) {
- f_thread_unlock(&global.thread->lock.process);
-
- return F_data_not;
- }
-
- f_status_t status = F_okay;
-
- bool required_not_run = F_false;
- bool skip = F_false;
-
- f_number_unsigned_t i = 0;
- f_number_unsigned_t j = 0;
-
- // Vuild a list of what to wait for so that anything new after this point will not be waited for.
- const f_number_unsigned_t process_total = global.thread->processs.used;
- controller_data_t *process_list[process_total];
-
- for (; i < process_total; ++i) {
- process_list[i] = global.thread->processs.array[i];
- } // for
-
- f_thread_unlock(&global.thread->lock.process);
-
- for (i = 0; i < process_total; ++i) {
-
- if (!controller_thread_is_enabled(is_normal, global.thread)) break;
-
- // Re-establish global process read lock to wait for or protect from the cleanup thread while checking the read process.
- status_lock = controller_lock_read(is_normal, global.thread, &global.thread->lock.process);
- if (F_status_is_error(status_lock)) break;
-
- if (!process_list[i]) {
- f_thread_unlock(&global.thread->lock.process);
-
- continue;
- }
-
- status_lock = controller_lock_read(is_normal, global.thread, &process_list[i]->active);
-
- if (F_status_is_error(status_lock)) {
- f_thread_unlock(&global.thread->lock.process);
-
- break;
- }
-
- // Once the active lock is obtained, then the main process read lock can be safely released.
- f_thread_unlock(&global.thread->lock.process);
-
- status_lock = controller_lock_read(is_normal, global.thread, &process_list[i]->lock);
-
- if (F_status_is_error(status_lock)) {
- f_thread_unlock(&process_list[i]->active);
-
- break;
- }
-
- if (required) {
- if (!(process_list[i]->options & controller_process_option_require_d)) {
- f_thread_unlock(&process_list[i]->lock);
- f_thread_unlock(&process_list[i]->active);
-
- continue;
- }
- }
-
- if (!process_list[i]->state || process_list[i]->state == controller_process_state_idle_e || process_list[i]->state == controller_process_state_done_e) {
-
- if (process_list[i]->state == controller_process_state_done_e) {
- f_thread_unlock(&process_list[i]->lock);
-
- status_lock = controller_lock_write(is_normal, global.thread, &process_list[i]->lock);
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_false, global.thread);
-
- f_thread_unlock(&process_list[i]->active);
-
- return status_lock;
- }
-
- if (process_list[i]->state == controller_process_state_done_e) {
- f_thread_unlock(&process_list[i]->active);
-
- if (f_thread_lock_write_try(&process_list[i]->active) == F_okay) {
- controller_thread_join(&process_list[i]->id_thread);
-
- process_list[i]->state = controller_process_state_idle_e;
-
- f_thread_unlock(&process_list[i]->active);
-
- f_thread_mutex_lock(&process_list[i]->wait_lock);
- f_thread_condition_signal_all(&process_list[i]->wait);
- f_thread_mutex_unlock(&process_list[i]->wait_lock);
- }
-
- status_lock = controller_lock_read(is_normal, global.thread, &process_list[i]->active);
-
- if (F_status_is_error(status_lock)) {
- f_thread_unlock(&process_list[i]->lock);
-
- break;
- }
- }
-
- f_thread_unlock(&process_list[i]->lock);
-
- status_lock = controller_lock_read(is_normal, global.thread, &process_list[i]->lock);
- if (F_status_is_error(status_lock)) break;
- }
-
- if (process_list[i]->options & controller_process_option_require_d) {
- if (controller_rule_status_is_error(process_list[i]->action, process_list[i]->rule)) {
- status = F_status_set_error(F_require);
-
- f_thread_unlock(&process_list[i]->lock);
- f_thread_unlock(&process_list[i]->active);
-
- break;
- }
- else if (controller_rule_status_is_available(process_list[i]->action, process_list[i]->rule)) {
- required_not_run = F_true;
- }
- }
-
- f_thread_unlock(&process_list[i]->lock);
- f_thread_unlock(&process_list[i]->active);
-
- if (F_status_set_fine(status) == F_require) break;
-
- continue;
- }
-
- if (!controller_rule_status_is_error(process_list[i]->action, process_list[i]->rule) && (process_list[i]->state == controller_process_state_active_e || process_list[i]->state == controller_process_state_busy_e)) {
- f_thread_unlock(&process_list[i]->lock);
-
- status = controller_process_wait(global, process_list[i]);
-
- if (F_status_set_fine(status) == F_interrupt) {
- f_thread_unlock(&process_list[i]->active);
-
- break;
- }
-
- status_lock = controller_lock_read(is_normal, global.thread, &process_list[i]->lock);
-
- if (F_status_is_error(status_lock)) {
- f_thread_unlock(&process_list[i]->active);
-
- break;
- }
-
- if ((process_list[i]->options & controller_process_option_require_d)) {
- f_thread_unlock(&process_list[i]->lock);
-
- if (controller_rule_status_is_error(process_list[i]->action, process_list[i]->rule)) {
- status = F_status_set_error(F_require);
-
- f_thread_unlock(&process_list[i]->active);
-
- break;
- }
- }
- else {
- f_thread_unlock(&process_list[i]->lock);
- }
- }
- else {
- f_thread_unlock(&process_list[i]->lock);
- }
-
- f_thread_unlock(&process_list[i]->active);
-
- if (F_status_set_fine(status) == F_interrupt || F_status_set_fine(status) == F_require) break;
- } // for
-
- if (F_status_is_error(status_lock)) {
- controller_lock_print_error_critical(&global.main->program.error, F_status_set_fine(status_lock), F_true, global.thread);
-
- return status_lock;
- }
-
- if (!controller_thread_is_enabled(is_normal, global.thread)) {
- return F_status_set_error(F_interrupt);
- }
-
- if (F_status_set_fine(status) == F_require) {
- return status;
- }
-
- if (required_not_run) {
- return F_require;
- }
-
- return F_okay;
- }
-#endif // _di_controller_rule_wait_all_
-
-#ifndef _di_controller_rule_wait_all_process_type_
- f_status_t controller_rule_wait_all_process_type(const controller_global_t global, const uint8_t type, const bool required) {
-
- return controller_rule_wait_all(global, type != controller_data_type_exit_e, required);
- }
-#endif // _di_controller_rule_wait_all_process_type_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_rule_h
-#define _PRIVATE_rule_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Special strings used for rules.
- */
-#ifndef _di_controller_rule_string_s_
- #define CONTROLLER_rule_needed_s "needed"
- #define CONTROLLER_rule_wanted_s "wanted"
- #define CONTROLLER_rule_wished_s "wished for"
-
- #define CONTROLLER_rule_needed_s_length 6
- #define CONTROLLER_rule_wanted_s_length 6
- #define CONTROLLER_rule_wished_s_length 10
-
- extern const f_string_static_t controller_rule_needed_s;
- extern const f_string_static_t controller_rule_wanted_s;
- extern const f_string_static_t controller_rule_wished_s;
-#endif // _di_controller_rule_print_string_s_
-
-/**
- * Get a string representing the rule action method.
- *
- * @param type
- * The rule action type code.
- *
- * @return
- * The string with used > 0 on success.
- * The string with used == 0 if no match was found.
- */
-#ifndef _di_controller_rule_action_method_name_
- extern f_string_static_t controller_rule_action_method_name(const uint8_t type) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_action_method_name_
-
-/**
- * Find the location of the Rule by the Rule alias.
- *
- * @param alias
- * The Rule alias to find.
- * @param rules
- * The rules to search through.
- * @param at
- * The index the rule was found at.
- * (optional) Set to NULL to disable.
- *
- * @return
- * F_okay on success, but the id.used is 0.
- * F_true on success and rule was found, index is updated.
- * F_false on success and rule was not found.
- */
-#ifndef _di_controller_rule_find_
- extern f_status_t controller_rule_find(const f_string_static_t alias, const controller_rules_t rules, f_number_unsigned_t *at) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_find_
-
-/**
- * Read the parameters for some rule action.
- *
- * The object and content ranges are merged together (in that order) as the action parameters.
- *
- * @param global
- * The global data.
- * @param buffer
- * The buffer containing the content.
- * @param object
- * (optional) The range representing where the object is found within the buffer.
- * Set pointer address to 0 to disable.
- * @param content
- * (optional) The ranges representing where the content is found within the buffer.
- * Set pointer address to 0 to disable.
- * @param action
- * The rule action.
- * @param state
- * The state data for passing to fl_iki_read().
- *
- * @return
- * F_okay on success.
- *
- * Errors (with error bit) from: f_fss_count_lines().
- * Errors (with error bit) from: f_memory_array_increase().
- * Errors (with error bit) from: f_memory_array_increase_by().
- * Errors (with error bit) from: f_string_dynamic_partial_append_nulless().
- * Errors (with error bit) from: f_memory_array_increase().
- * Errors (with error bit) from: fl_iki_read().
- *
- * @see f_fss_count_lines()
- * @see f_memory_array_increase()
- * @see f_memory_array_increase_by()
- * @see f_string_dynamic_partial_append_nulless()
- * @see f_memory_array_increase()
- * @see f_memory_array_increase_by()
- * @see fl_iki_read()
- */
-#ifndef _di_controller_rule_parameters_read_
- extern f_status_t controller_rule_parameters_read(const controller_global_t global, const f_string_static_t buffer, f_range_t * const object, f_ranges_t * const content, controller_rule_action_t * const action, f_state_t * const state) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_parameters_read_
-
-/**
- * Convert the action type to an action execute type.
- *
- * @param type
- * The action type to convert from.
- *
- * @return
- * The converted action type, converted into an action execute type.
- *
- * The code controller_rule_action_execute_type__enum_size_e is returned for unknown types.
- */
-#ifndef _di_controller_rule_action_type_to_action_execute_type_
- extern uint8_t controller_rule_action_type_to_action_execute_type(const uint8_t type) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_action_type_to_action_execute_type_
-
-/**
- * Read the content within the buffer, processing the action (or a set of within a list) for the given item.
- *
- * This will automatically increase the size of the actions array as needed.
- *
- * @param global
- * The global data.
- * @param is_normal
- * If TRUE, then process as if this operates during a normal operation (entry and control).
- * If FALSE, then process as if this operates during a an exit operation.
- * @param type
- * The action type for this action or set of actions.
- * @param method
- * The action method for this action or set of actions.
- * @param cache
- * A structure for containing and caching relevant data.
- * @param item
- * The processed item.
- * @param actions
- * The processed actions.
- * @param range
- * The current positions within the buffer being operated on.
- * This is expected to be set to a position immediately after a valid object read.
- *
- * @return
- * F_okay on success.
- *
- * Errors (with error bit) from: controller_rule_actions_increase_by().
- * Errors (with error bit) from: controller_rule_parameters_read().
- * Errors (with error bit) from: f_fss_count_lines().
- *
- * @see controller_rule_actions_increase_by()
- * @see controller_rule_parameters_read()
- * @see f_fss_count_lines()
- */
-#ifndef _di_controller_rule_action_read_
- extern f_status_t controller_rule_action_read(const controller_global_t global, const bool is_normal, const uint8_t type, const uint8_t method, controller_cache_t * const cache, controller_rule_item_t *item, controller_rule_actions_t *actions, f_range_t *range) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_action_read_
-
-/**
- * Copy a rule, allocating new space as necessary.
- *
- * This does not do any locking or unlocking for the rule data, be sure to lock appropriately before and after calling this.
- *
- * @param source
- * The source rule to copy from.
- * @param destination
- * The destination rule to copy to.
- *
- * @return
- * F_okay on success.
- *
- * Errors (with error bit) from: f_capability_copy().
- * Errors (with error bit) from: f_control_group_copy().
- * Errors (with error bit) from: f_iki_datas_append_all().
- * Errors (with error bit) from: f_int32s_append_all().
- * Errors (with error bit) from: f_limit_sets_copy().
- * Errors (with error bit) from: f_string_dynamic_append().
- * Errors (with error bit) from: f_string_dynamics_append_all().
- * Errors (with error bit) from: f_string_maps_append_all().
- *
- * @see f_capability_copy()
- * @see f_control_group_copy()
- * @see f_iki_datas_append_all()
- * @see f_int32s_append_all()
- * @see f_limit_sets_append()
- * @see f_string_dynamic_append()
- * @see f_string_dynamics_append_all()
- * @see f_string_maps_append_all()
- */
-#ifndef _di_controller_rule_copy_
- extern f_status_t controller_rule_copy(const controller_rule_t source, controller_rule_t *destination) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_copy_
-
-/**
- * Perform an execution of the given rule.
- *
- * This requires that a read lock be set on process->lock before being called.
- *
- * @param global
- * The global data.
- * @param action
- * The action to perform based on the action type codes.
- *
- * Only subset of the action type codes are supported:
- * - controller_rule_action_type_kill_e
- * - controller_rule_action_type_pause_e
- * - controller_rule_action_type_reload_e
- * - controller_rule_action_type_restart_e
- * - controller_rule_action_type_resume_e
- * - controller_rule_action_type_start_e
- * - controller_rule_action_type_stop_e
- * @param options
- * Process options to consider when executing.
- * If bit controller_process_option_simulate_d, then the rule execution is in simulation mode (printing a message that the rule would be executed but does not execute the rule).
- * @param process
- * The process data for processing this rule.
- *
- * @return
- * F_okay on success.
- * F_child on child process exiting.
- * F_ignore if the rule is unknown and nothing can be done.
- *
- * F_failure (with error bit) if failed to execute.
- * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
- * F_lock (with error bit) if failed to re-establish read lock on process->lock while returning.
- *
- * On success and the rule is run synchronously, then the individual status for the rule is set to F_complete.
- * On success and the rule is run asynchronously, then the individual status for the rule is set to F_busy.
- * On failure, the individual status for the rule is set to an appropriate error status.
- */
-#ifndef _di_controller_rule_execute_
- extern f_status_t controller_rule_execute(const controller_global_t global, const uint8_t action, const uint8_t options, controller_data_t * const process) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_execute_
-
-/**
- * Perform an execution of the given rule in the foreground.
- *
- * This requires that a read lock be set on process->lock before being called.
- *
- * @param type
- * The item type code.
- * @param program
- * The program to use (such as "bash").
- * @param arguments
- * The arguments to pass to the program.
- * @param options
- * Process options to consider when executing.
- * If bit controller_process_option_simulate_d, then the rule execution is in simulation mode (printing a message that the rule would be executed but does not execute the rule).
- * @param execute_set
- * The execute parameter and as settings.
- * @param process
- * The process data for processing this rule.
- *
- * @return
- * F_okay on success.
- * F_child on child process exiting.
- *
- * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
- * F_lock (with error bit) if failed to re-establish read lock on process->lock while returning.
- *
- * Errors (with error bit) from: fll_execute_program().
- *
- * @see fll_execute_program()
- */
-#ifndef _di_controller_rule_execute_foreground_
- extern f_status_t controller_rule_execute_foreground(const uint8_t type, const f_string_static_t program, const f_string_statics_t arguments, const uint8_t options, controller_execute_set_t * const execute_set, controller_data_t * const process) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_execute_foreground_
-
-/**
- * Perform an execution of the given rule in the foreground or background and creating a PID file.
- *
- * This requires that a read lock be set on process->lock before being called.
- *
- * When this is synchronous, this will wait for the PID file to be generated before continuing.
- * When this is asynchronous, this will continue on adding the rule id and action to the asynchronous list.
- *
- * @param pid_file
- * The path to the PID file.
- * @param type
- * The item type code.
- * @param program
- * The program to use (such as "bash").
- * @param arguments
- * The arguments to pass to the program.
- * @param options
- * Process options to consider when executing.
- * If bit controller_process_option_simulate_d, then the rule execution is in simulation mode (printing a message that the rule would be executed but does not execute the rule).
- * @param with
- * The "with" option flags.
- * @param execute_set
- * The execute parameter and as settings.
- * @param process
- * The process data for processing this rule.
- *
- * @return
- * F_okay on success.
- * F_child on child process exiting.
- *
- * F_file_found (with error bit) if the PID file already exists.
- * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
- * F_lock (with error bit) if failed to re-establish read lock on process->lock while returning.
- *
- * Errors (with error bit) from: fll_execute_program().
- *
- * @see fll_execute_program()
- */
-#ifndef _di_controller_rule_execute_pid_with_
- extern f_status_t controller_rule_execute_pid_with(const f_string_dynamic_t pid_file, const uint8_t type, const f_string_static_t program, const f_string_statics_t arguments, const uint8_t options, const uint8_t with, controller_execute_set_t * const execute_set, controller_data_t * const process) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_execute_pid_with_
-
-/**
- * Determine whether or not an execute rule should be re-run, applying a delay as requested.
- *
- * @param action
- * The action type.
- * @param process
- * The process data for processing this rule.
- * @param item
- * The rule item being executed.
- *
- * @return
- * A positive number to designate re-run.
- * 0 to designate do not re-run.
- * -1 to designate an error from nanosleep(), with errno set to values like:
- * - EFAULT: Designates that there was a problem copying information from user space.
- * - EINTR: Consider this having returned F_interrupt.
- * - EINVAL: Consider this having returned F_status_set_error(F_parameter);
- * -2 to designate exit due to signal/disabled thread.
- */
-#ifndef _di_controller_rule_execute_rerun_
- extern int8_t controller_rule_execute_rerun(const uint8_t action, controller_data_t * const process, controller_rule_item_t * const item) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_execute_rerun_
-
-/**
- * Expand a single IKI variable into the buffer.
- *
- * @param
- * The global data.
- * @param action
- * The rule action data.
- * @param process
- * The process information.
- *
- * @return
- * F_okay on success.
- *
- * Errors (with error bit) from: controller_rule_expand_iki().
- *
- * @see controller_rule_expand_iki()
- */
-#ifndef _di_controller_rule_expand_
- extern f_status_t controller_rule_expand(const controller_global_t global, const controller_rule_action_t action, controller_data_t * const process) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_expand_
-
-/**
- * Expand a single IKI variable into the buffer.
- *
- * @param process
- * The process information.
- * @param source
- * The source buffer holding the string referenced by the IKI data.
- * @param vocabulary
- * The range representing the IKI variable vocabulary.
- * @param content
- * The range representing the IKI variable content.
- * @param destination
- * The buffer to expand into.
- *
- * @return
- * F_okay on success.
- *
- * Errors (with error bit) from: f_environment_get().
- * Errors (with error bit) from: f_string_dynamic_append().
- *
- * @see f_environment_get()
- * @see f_string_dynamic_append()
- */
-#ifndef _di_controller_rule_expand_iki_
- extern f_status_t controller_rule_expand_iki(controller_data_t * const process, const f_string_static_t source, const f_range_t vocabulary, const f_range_t content, f_string_dynamic_t * const destination) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_expand_iki_
-
-/**
- * Construct an id from two distinct strings found within a single given source.
- *
- * @param global
- * The global data.
- * @param source
- * The source string that both the directory and basename are copied from.
- * @param directory
- * A range within the source representing the directory part of a rule id.
- * @param basename
- * A range within the source representing the basename part of a rule id.
- * @param alias
- * The constructed alias.
- *
- * @return
- * F_okay on success.
- *
- * Errors (with error bit) from: f_string_dynamic_partial_append_nulless().
- *
- * @see f_string_append()
- * @see f_string_dynamic_partial_append_nulless()
- */
-#ifndef _di_controller_rule_id_construct_
- extern f_status_t controller_rule_id_construct(const controller_global_t global, const f_string_static_t source, const f_range_t directory, const f_range_t basename, f_string_dynamic_t * const alias) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_id_construct_
-
-/**
- * Check to see if the given Rule has status F_known_not for the given Rule Action.
- *
- * The global Rule status is checked for error and any errors on the global Rule status will result in F_false.
- *
- * @param action
- * The Rule Action type.
- * @param rule
- * The Rule.
- *
- * @return
- * F_true on available (status is F_known_not).
- * F_false on unavailable.
- */
-#ifndef _di_controller_rule_status_is_available_
- extern f_status_t controller_rule_status_is_available(const uint8_t action, const controller_rule_t rule) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_status_is_available_
-
-/**
- * Check to see if the given Rule has status is designated as an error for the given Rule Action.
- *
- * The global Rule status is checked for error and any errors on the global Rule status will result in F_true.
- *
- * @param action
- * The Rule Action type.
- * @param rule
- * The Rule.
- *
- * @return
- * F_true if status represents an error.
- * F_false if status does not represent an error.
- */
-#ifndef _di_controller_rule_status_is_error_
- extern f_status_t controller_rule_status_is_error(const uint8_t action, const controller_rule_t rule) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_status_is_error_
-
-/**
- * Read the content within the buffer, extracting all valid items after determining their type for some rule file.
- *
- * This will perform additional FSS read functions as appropriate.
- *
- * @param global
- * The global data.
- * @param is_normal
- * If TRUE, then process as if this operates during a normal operation (entry and control).
- * If FALSE, then process as if this operates during a an exit operation.
- * @param cache
- * A structure for containing and caching relevant data.
- * @param item
- * The processed item.
- *
- * @return
- * F_okay on success.
- * F_valid_not (with error bit) on invalid data.
- *
- * Errors (with error bit) from: f_fss_count_lines().
- * Errors (with error bit) from: f_string_dynamic_partial_append_nulless().
- *
- * @see controller_rule_action_read()
- * @see f_fss_count_lines()
- * @see f_string_dynamic_partial_append_nulless()
- */
-#ifndef _di_controller_rule_item_read_
- extern f_status_t controller_rule_item_read(const controller_global_t global, const bool is_normal, controller_cache_t * const cache, controller_rule_item_t * const item) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_item_read_
-
-/**
- * Increase the size of the rule items array by the specified amount, but only if necessary.
- *
- * This only increases size if the current used plus amount is greater than the currently allocated size.
- *
- * @param amount
- * A positive number representing how much to increase the size by.
- * @param items
- * The items to resize.
- *
- * @return
- * F_okay on success.
- * F_array_too_large (with error bit) if the resulting new size is bigger than the max array length.
- *
- * Errors (with error bit) from: f_memory_resize().
- *
- * @see f_memory_resize()
- */
-#ifndef _di_controller_rule_items_increase_by_
- extern f_status_t controller_rule_items_increase_by(const f_number_unsigned_t amount, controller_rule_items_t * const items) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_items_increase_by_
-
-/**
- * Process and execute the given rule.
- *
- * Any dependent rules are processed and executed as per "need", "want", and "wish" rule settings.
- * All dependent rules must be already loaded, this function will not load any rules.
- *
- * This requires that a read lock be set on process->lock before being called.
- *
- * This function is recursively called for each "need", "want", and "wish", and has a max recursion length of the max size of the f_number_unsigneds_t array.
- *
- * The rule status will be updated by this function.
- *
- * @param global
- * The global data.
- * @param process
- * The process data for processing this rule.
- *
- * @return
- * F_okay on success.
- * F_child on child process exiting.
- * F_failure on execution failure.
- *
- * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
- * F_lock (with error bit) if failed to re-establish read lock on process->lock while returning.
- *
- * Errors (with error bit) from: controller_lock_read().
- * Errors (with error bit) from: controller_lock_write().
- */
-#ifndef _di_controller_rule_process_
- extern f_status_t controller_rule_process(const controller_global_t global, controller_data_t * const process) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_process_
-
-/**
- * Synchronously or asynchronously begin processing some rule.
- *
- * @param global
- * The global data.
- * @param options_force
- * Force the given process options, only supporting a subset of process options.
- *
- * If controller_process_option_asynchronous_d, then asynchronously execute.
- * If not controller_process_option_asynchronous_d, then synchronously execute.
- * @param alias_rule
- * The alias of the rule, such as "boot/init".
- * @param action
- * The action to perform based on the action type codes.
- * @param options
- * The process options to pass to the process.
- * @param type
- * The process type, such as controller_data_type_entry_e.
- * @param stack
- * A stack representing the processes already running in this rule process dependency tree.
- * This is used to prevent circular dependencies.
- * @param cache
- * A structure for containing and caching relevant data.
- *
- * @return
- * F_okay on success.
- * F_busy on success and the process was found to already be running (nothing to do).
- *
- * F_found_not (with error bit) if unable to for a process for the given rule id.
- * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
- * F_recurse (with error bit) on recursion error (the process is already on the process stack).
- *
- * Status from: controller_rule_process().
- *
- * Errors (with error bit) from: controller_rule_process().
- * Errors (with error bit) from: f_string_dynamic_append().
- * Errors (with error bit) from: f_thread_create().
- *
- * @see controller_rule_process()
- * @see f_string_dynamic_append()
- * @see f_thread_create()
- */
-#ifndef _di_controller_rule_process_begin_
- extern f_status_t controller_rule_process_begin(const controller_global_t global, const uint8_t options_force, const f_string_static_t alias_rule, const uint8_t action, const uint8_t options, const uint8_t type, const f_number_unsigneds_t stack, const controller_cache_t cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_process_begin_
-
-/**
- * Helper for calling controller_rule_process().
- *
- * This does all the preparation work that needs to be synchronously performed within the same thread.
- * This will copy the rule by the alias to the process structure.
- *
- * @param options_force
- * Force the given process options, only supporting a subset of process options.
- *
- * If controller_process_option_asynchronous_d, then asynchronously execute.
- * If not controller_process_option_asynchronous_d, then synchronously execute.
- * @param process
- * The process data.
- *
- * @return
- * F_okay on success.
- * F_found on the process was found to already be running (nothing to do).
- * F_process_not if the process was not executed because it is a "consider" Action.
- *
- * F_found_not (with error bit) if unable to for a process for the given rule id.
- * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
- *
- * Status from: controller_rule_process().
- *
- * Errors (with error bit) from: controller_rule_copy().
- * Errors (with error bit) from: controller_rule_process().
- *
- * @see controller_rule_copy()
- * @see controller_rule_process()
- * @see controller_rule_process_begin()
- */
-#ifndef _di_controller_rule_process_do_
- extern f_status_t controller_rule_process_do(const uint8_t options_force, controller_data_t * const process) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_process_do_
-
-/**
- * Read the rule file, extracting all valid items.
- *
- * @param global
- * The global data.
- * @param is_normal
- * If TRUE, then process as if this operates during a normal operation (entry and control).
- * If FALSE, then process as if this operates during a an exit operation.
- * @param alias
- * The string identifying the rule.
- * This is constructed from the path parts to the file without the file extension and without the settings directory prefix.
- * "/etc/controller/rules/example/my.rule" would have a rule id of "example/my".
- * @param cache
- * A structure for containing and caching relevant data.
- * @param entry
- * The entry containing the rule being read.
- * @param rule
- * The processed rule.
- * The rule status will be updated by this function.
- *
- * @return
- * F_okay on success.
- *
- * Simplified status (with error bit) from controller_status_simplify_error() on failure.
- *
- * @see controller_rule_items_increase_by().
- * @see controller_rule_item_read().
- * @see f_fss_count_lines().
- * @see f_fss_apply_delimit().
- * @see f_string_dynamic_partial_append().
- * @see f_string_dynamic_partial_append_nulless().
- * @see fll_fss_basic_list_read().
- */
-#ifndef _di_controller_rule_read_
- extern f_status_t controller_rule_read(const controller_global_t global, const bool is_normal, const f_string_static_t alias, controller_cache_t * const cache, controller_entry_t * const entry, controller_rule_t * const rule) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_read_
-
-/**
- * Process a number from a rule file, incrementing index as necessary.
- *
- * This prints error messages as necessary.
- *
- * This is intended to be called by controller_rule_action_read().
- *
- * @param global
- * The global data.
- * @param name
- * The name representing the value whose number is being processed.
- * @param cache
- * A structure for containing and caching relevant data.
- * @param index
- * The position within the content action array for some rule to process.
- * @param number
- * The processed number will be saved here.
- *
- * @return
- * F_okay on success.
- *
- * F_valid_not (with error bit) on failure due to invalid value.
- *
- * Errors (with error bit) from: fl_conversion_dynamic_partial_to_signed_detect().
- *
- * @see controller_rule_action_read()
- * @see fl_conversion_dynamic_partial_to_signed_detect()
- */
-#ifndef _di_controller_rule_action_read_rerun_number_
- extern f_status_t controller_rule_action_read_rerun_number(const controller_global_t global, const f_string_t name, controller_cache_t * const cache, f_number_unsigned_t * const index, f_number_unsigned_t * const number) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_action_read_rerun_number_
-
-/**
- * Read the content within the buffer, extracting all valid settings.
- *
- * This will perform additional FSS read functions as appropriate.
- *
- * Errors from this are not considered fatal, but the first error code encountered is returned.
- * Memory failure errors are always immediately returned.
- *
- * @param global
- * The global data.
- * @param is_normal
- * If TRUE, then process as if this operates during a normal operation (entry and control).
- * If FALSE, then process as if this operates during a an exit operation.
- * @param setting
- * The controller settings data.
- * @param cache
- * A structure for containing and caching relevant data.
- * @param rule
- * The processed rule.
- *
- * @return
- * F_okay on success.
- *
- * F_valid_not (with error bit) on success but there were one or more invalid settings encountered.
- *
- * Errors (with error bit) from: f_memory_array_increase().
- * Errors (with error bit) from: f_rip_dynamic_partial_nulless().
- * Errors (with error bit) from: f_string_dynamic_partial_append_nulless().
- * Errors (with error bit) from: fll_fss_extended_read().
- *
- * Errors (with error bit) from: controller_path_canonical_relative().
- *
- * @see f_memory_array_increase()
- * @see f_rip_dynamic_partial_nulless()
- * @see f_string_dynamic_partial_append_nulless()
- * @see fll_fss_extended_read()
- *
- * @see controller_path_canonical_relative()
- */
-#ifndef _di_controller_rule_setting_read_
- extern f_status_t controller_rule_setting_read(const controller_global_t global, const bool is_normal, const controller_process_t setting, controller_cache_t * const cache, controller_rule_t * const rule) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_setting_read_
-
-/**
- * Perform a simulated execution of the given rule.
- *
- * This simply prints information about the rule.
- *
- * This automatically sets the rule's status to F_complete.
- *
- * @param global
- * The global data.
- * @param rule
- * The rule to process.
- * @param action
- * The action to perform based on the action type codes.
- * @param options
- * A number using bits to represent specific boolean options.
- * If no bits set, then operate normally in a synchronous manner.
- * If bit controller_process_option_simulate_d, then the rule execution is in simulation mode (printing a message that the rule would be executed but does not execute the rule).
- * If bit controller_process_option_asynchronous_d, then run asynchronously.
- * @param cache
- * A structure for containing and caching relevant data.
- */
-#ifndef _di_controller_rule_validate_
- extern void controller_rule_validate(const controller_global_t global, const controller_rule_t rule, const uint8_t action, const uint8_t options, controller_cache_t * const cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_validate_
-
-/**
- * Wait until all currently running Rule processes are complete.
- *
- * @param global
- * The global data.
- * @param is_normal
- * If TRUE, then process as if this operates during a normal operation (entry and control).
- * If FALSE, then process as if this operates during a an exit operation.
- * This is ignored when caller is not NULL.
- * @param required
- * If TRUE, then only process required rules and if a required rule has failed, return.
- * If FALSE, process all waits, returning normally (required rules still result in failure).
- *
- * @return
- * F_okay on success.
- * F_data_not on success and nothing to do.
- * F_require on success, but a required rule has not been run yet.
- *
- * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
- * F_require (with error bit set) if a required process is in failed status when required is TRUE.
- */
-#ifndef _di_controller_rule_wait_all_
- extern f_status_t controller_rule_wait_all(const controller_global_t global, const bool is_normal, const bool required) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_wait_all_
-
-/**
- * Wait until all currently running Rule processes are complete for some process type.
- *
- * @param global
- * The global data.
- * @param type
- * The process type to use when checking if thread is enabled.
- * @param required
- * If TRUE, then only process required rules and if a required rule has failed, return.
- * If FALSE, process all waits, returning normally.
- *
- * @return
- * Success from controller_rule_wait_all().
- *
- * Errors (with error bit) from: controller_rule_wait_all().
- *
- * @see controller_rule_wait_all()
- */
-#ifndef _di_controller_rule_wait_all_process_type_
- extern f_status_t controller_rule_wait_all_process_type(const controller_global_t global, const uint8_t type, const bool required) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_wait_all_process_type_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_rule_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "../rule/private-rule_print.h"
-#include "../lock/private-lock_print.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifndef _di_controller_rule_print_string_s_
- const f_string_static_t controller_rule_print_control_groups_prepare_s = macro_f_string_static_t_initialize_1(CONTROLLER_rule_print_control_groups_prepare_s, 0, CONTROLLER_rule_print_control_groups_prepare_s_length);
-#endif // _di_controller_rule_print_string_s_
-
-#ifndef _di_controller_rule_print_error_
- void controller_rule_print_error(controller_thread_t * const thread, fl_print_t * const print, const controller_cache_action_t cache, const f_status_t status, const f_string_t function, const bool fallback, const bool item) {
-
- if (print->verbosity == f_console_verbosity_quiet_e) return;
- if (status == F_interrupt) return;
-
- // fll_error_print() automatically locks, so manually handle only the mutex locking and flushing rather than calling controller_lock_print().
- f_thread_mutex_lock(&thread->lock.print);
-
- fll_error_print(print, status, function, fallback);
-
- f_file_stream_lock(print->to);
-
- controller_rule_print_error_cache(print, cache, item);
-
- controller_unlock_print_flush(print->to, thread);
- }
-#endif // _di_controller_rule_print_error_
-
-#ifndef _di_controller_rule_print_error_cache_
- void controller_rule_print_error_cache(fl_print_t * const print, const controller_cache_action_t cache, const bool item) {
-
- if (print->verbosity == f_console_verbosity_quiet_e) return;
-
- fl_print_format("%r%[%QWhile processing ", print->to, f_string_eol_s, print->context, print->prefix);
-
- if (cache.name_action.used) {
- fl_print_format("%r '%]", print->to, item ? controller_action_s : controller_value_s, print->context);
- fl_print_format(f_string_format_Q_single_s.string, print->to, print->notable, cache.name_action, print->notable);
- fl_print_format("%[' on line%] ", print->to, print->context, print->context);
- fl_print_format("%[%un%]", print->to, print->notable, cache.line_action, print->notable);
- fl_print_format("%[ for ", print->to, print->context);
- }
-
- if (cache.name_item.used) {
- fl_print_format("rule %r '%]", print->to, item ? controller_item_s : controller_settings_s, print->context);
- fl_print_format(f_string_format_Q_single_s.string, print->to, print->notable, cache.name_item, print->notable);
- fl_print_format("%[' on line%] ", print->to, print->context, print->context);
- fl_print_format("%[%un%]", print->to, print->notable, cache.line_item, print->notable);
- fl_print_format("%[ for ", print->to, print->context);
- }
-
- if (cache.name_file.used) {
- fl_print_format("rule file '%]%[%Q%]%['", print->to, print->context, print->notable, cache.name_file, print->notable, print->context);
- }
-
- fl_print_format(".%]%r", print->to, print->context, f_string_eol_s);
- }
-#endif // _di_controller_rule_print_error_cache_
-
-#ifndef _di_controller_rule_item_print_error_
- void controller_rule_item_print_error(controller_thread_t * const thread, fl_print_t * const print, const controller_cache_action_t cache, const bool item, const f_status_t status) {
-
- if (print->verbosity == f_console_verbosity_quiet_e) return;
- if (status == F_interrupt) return;
-
- // fll_error_print() automatically locks, so manually handle only the mutex locking and flushing rather than calling controller_lock_print().
- f_thread_mutex_lock(&thread->lock.print);
-
- controller_rule_print_error_cache(print, cache, item);
-
- f_file_stream_lock(print->to);
-
- controller_unlock_print_flush(print->to, thread);
- }
-#endif // _di_controller_rule_item_print_error_
-
-#ifndef _di_controller_rule_item_print_error_execute_
- void controller_rule_item_print_error_execute(const bool script_is, const f_string_static_t name, const f_status_t status, controller_data_t * const process) {
-
- if (((controller_main_t *) process->main_data)->program.error.verbosity != f_console_verbosity_quiet_e) {
- fl_print_t * const print = &((controller_main_t *) process->main_data)->program.error;
-
- controller_lock_print(print->to, (controller_thread_t *) process->main_thread);
-
- fl_print_format("%r%[%QThe %r '%]", print->to, f_string_eol_s, print->context, print->prefix, script_is ? controller_engine_s : controller_program_s, print->context);
- fl_print_format(f_string_format_Q_single_s.string, print->to, print->notable, name, print->notable);
-
- if (status == F_control_group || status == F_limit || status == F_processor || status == F_schedule) {
- fl_print_format("%[' failed to setup the '%]%[", print->to, print->context, print->context, print->notable);
-
- if (status == F_control_group) {
- f_print_dynamic_raw(controller_cgroup_s, print->to);
- }
- else if (status == F_limit) {
- f_print_dynamic_raw(controller_limit_s, print->to);
- }
- else if (status == F_processor) {
- f_print_dynamic_raw(controller_processor_s, print->to);
- }
- else if (status == F_schedule) {
- f_print_dynamic_raw(controller_scheduler_s, print->to);
- }
-
- fl_print_format("%]%['.%]%r", print->to, print->notable, print->context, print->context, f_string_eol_s);
- }
- else if (WIFEXITED(process->result) ? WEXITSTATUS(process->result) : 0) {
- const uint8_t code = WIFEXITED(process->result) ? WEXITSTATUS(process->result) : 0;
-
- if (code == F_execute_access) {
- fl_print_format("%[' failed, access is denied.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_bad) {
- fl_print_format("%[' failed, unsupported format.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_buffer) {
- fl_print_format("%[' invalid memory access in arguments buffer.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_busy) {
- fl_print_format("%[' required resources are unavailable, too busy.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_capability) {
- fl_print_format("%[' failed to setup capabilities.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_control_group) {
- fl_print_format("%[' failed to setup control group.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_child) {
- fl_print_format("%[' failed to setup child process.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_directory_not) {
- fl_print_format("%[' invalid path, part of the path is not a valid directory.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_failure) {
- fl_print_format("%[' failed during execution.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_file_found_not) {
- fl_print_format("%[' failed, unable to find file.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_file_type_directory) {
- fl_print_format("%[' ELF interpreter is a directory.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_fork_not) {
- fl_print_format("%[' fork failure.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_format_not) {
- fl_print_format("%[' could not be executed because the program has an invalid ELF header.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_group) {
- fl_print_format("%[' failed to setup group.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_input_output) {
- fl_print_format("%[' I/O failure.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_limit) {
- fl_print_format("%[' failed to setup resource limits.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_loop) {
- fl_print_format("%[' max recursion reached.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_memory_not) {
- fl_print_format("%[' is out of memory.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_name_not) {
- fl_print_format("%[' file name or path is too long.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_nice) {
- fl_print_format("%[' failed to setup niceness.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_parameter) {
- fl_print_format("%[' failed due to an invalid parameter.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_pipe) {
- fl_print_format("%[' pipe failed.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_processor) {
- fl_print_format("%[' failed to setup processor affinity.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_prohibited) {
- fl_print_format("%[' access prohibited.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_resource_not) {
- fl_print_format("%[' resource limit reached.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_schedule) {
- fl_print_format("%[' failed to setup scheduler.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_terminal) {
- fl_print_format("%[' failed while processing the terminal.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_terminal_known_not) {
- fl_print_format("%[' cannot process terminal, unknown terminal control command.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_terminal_not) {
- fl_print_format("%[' cannot process terminal, not a known terminal.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_terminal_prohibited) {
- fl_print_format("%[' insufficient permissions to process the terminal.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_terminal_valid_not) {
- fl_print_format("%[' invalid parameter while processing the terminal.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_too_large) {
- fl_print_format("%[' too many arguments or arguments are too large.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_user) {
- fl_print_format("%[' failed to setup user.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_valid_not) {
- fl_print_format("%[' unknown ELF interpreter format.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_invoke_not) {
- fl_print_format("%[' cannot execute command.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_found_not) {
- fl_print_format("%[' command not found.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_found_not) {
- fl_print_format("%[' invalid argument to exit().%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_hangup) {
- fl_print_format("%[' hang up signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_interrupt) {
- fl_print_format("%[' interrupt signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_quit) {
- fl_print_format("%[' quit signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_illegal) {
- fl_print_format("%[' illegal signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_trap) {
- fl_print_format("%[' trap signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_abort) {
- fl_print_format("%[' abort signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_bus_error) {
- fl_print_format("%[' bus error signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_floating_point_error) {
- fl_print_format("%[' floating point error signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_kill) {
- fl_print_format("%[' kill signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_user_1) {
- fl_print_format("%[' user 1 signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_segmentation_fault) {
- fl_print_format("%[' segmentation fault signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_user_2) {
- fl_print_format("%[' user 2 signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_broken_pipe) {
- fl_print_format("%[' broken pipe signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_alarm_clock) {
- fl_print_format("%[' alarm clock signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_termination) {
- fl_print_format("%[' terminate signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_stack_fault) {
- fl_print_format("%[' stack fault signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_child) {
- fl_print_format("%[' child signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_continue) {
- fl_print_format("%[' continue signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_stop) {
- fl_print_format("%[' stop signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_keyboard_stop) {
- fl_print_format("%[' keyboard stop signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_tty_in) {
- fl_print_format("%[' TTY in signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_tty_out) {
- fl_print_format("%[' TTY out signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_urgent) {
- fl_print_format("%[' urgent signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_cpu_limit) {
- fl_print_format("%[' CPU limit signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_file_size_limit) {
- fl_print_format("%[' file size signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_virtual_alarm_clock) {
- fl_print_format("%[' virtual alarm clock signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_profile_alarm_clock) {
- fl_print_format("%[' profile alarm clock signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_window_size_change) {
- fl_print_format("%[' window size change signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_pollable_event) {
- fl_print_format("%[' pollable signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_power_failure) {
- fl_print_format("%[' power failure signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else if (code == F_execute_signal_bad_system_call) {
- fl_print_format("%[' bad system call signal received.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
- else {
- fl_print_format("%[' failed with the execute error code %]", print->to, print->context, print->context);
- fl_print_format("%[%i%]", print->to, print->notable, code, print->notable);
- fl_print_format(f_string_format_sentence_end_s.string, print->to, print->context, print->context, f_string_eol_s);
- }
- }
- else {
- fl_print_format("%[' failed.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
-
- controller_unlock_print_flush(print->to, (controller_thread_t *) process->main_thread);
- }
- }
-#endif // _di_controller_rule_item_print_error_execute_
-
-#ifndef _di_controller_rule_action_print_error_missing_pid_
- void controller_rule_action_print_error_missing_pid(fl_print_t * const print, const f_string_static_t alias) {
-
- if (print->verbosity == f_console_verbosity_quiet_e) return;
-
- fl_print_format("%r%[%QThe rule '%]", print->to, f_string_eol_s, print->context, print->prefix, print->context);
- fl_print_format(f_string_format_Q_single_s.string, print->to, print->notable, alias, print->notable);
- fl_print_format("%[' is not designating a pid file.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
-#endif // _di_controller_rule_action_print_error_missing_pid_
-
-#ifndef _di_controller_rule_item_print_error_need_want_wish_
- void controller_rule_item_print_error_need_want_wish(fl_print_t * const print, const f_string_static_t need_want_wish, const f_string_static_t value, const f_string_t why) {
-
- if (print->verbosity == f_console_verbosity_quiet_e) return;
-
- fl_print_format("%r%[%QThe %r rule '%]", print->to, f_string_eol_s, print->context, print->prefix, need_want_wish, print->context);
- fl_print_format(f_string_format_Q_single_s.string, print->to, print->notable, value, print->notable);
- fl_print_format("%[' %S.%]%r", print->to, print->context, why, print->context, f_string_eol_s);
- }
-#endif // _di_controller_rule_item_print_error_need_want_wish_
-
-#ifndef _di_controller_rule_item_print_error_rule_not_loaded_
- void controller_rule_item_print_error_rule_not_loaded(fl_print_t * const print, const f_string_static_t alias) {
-
- if (print->verbosity == f_console_verbosity_quiet_e) return;
-
- fl_print_format("%r%[%QThe rule '%]", print->to, f_string_eol_s, print->context, print->prefix, print->context);
- fl_print_format(f_string_format_Q_single_s.string, print->to, print->notable, alias, print->notable);
- fl_print_format("%[' is no longer loaded.%]%r", print->to, print->context, print->context, f_string_eol_s);
- }
-#endif // _di_controller_rule_item_print_error_rule_not_loaded_
-
-#ifndef _di_controller_rule_setting_read_print_error_
- void controller_rule_setting_read_print_error(fl_print_t * const print, const f_string_t message, const f_number_unsigned_t index, const f_number_unsigned_t line_item, controller_thread_t * const thread, controller_cache_t * const cache) {
-
- if (!print->custom) return;
- if (print->verbosity == f_console_verbosity_quiet_e) return;
-
- controller_main_t * const main = (controller_main_t *) print->custom;
-
- f_state_t state = f_state_t_initialize;
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[index].start, &cache->action.line_item, &main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(print->to, thread);
-
- fl_print_format("%r%[%QRule setting %S.%]%r", print->to, f_string_eol_s, print->context, print->prefix, message, print->context, f_string_eol_s);
-
- controller_rule_print_error_cache(print, cache->action, F_false);
-
- controller_unlock_print_flush(print->to, thread);
- }
-#endif // _di_controller_rule_setting_read_print_error_
-
-#ifndef _di_controller_rule_setting_read_print_error_with_range_
- void controller_rule_setting_read_print_error_with_range(fl_print_t * const print, const f_string_t before, const f_range_t range, const f_string_t after, const f_number_unsigned_t index, const f_number_unsigned_t line_item, controller_thread_t * const thread, controller_cache_t * const cache) {
-
- if (!print->custom) return;
- if (print->verbosity == f_console_verbosity_quiet_e) return;
-
- controller_main_t * const main = (controller_main_t *) print->custom;
-
- f_state_t state = f_state_t_initialize;
-
- // Get the current line number within the settings item.
- cache->action.line_item = line_item;
- f_fss_count_lines(cache->buffer_item, cache->object_actions.array[index].start, &cache->action.line_item, &main->setting.state);
-
- cache->action.line_action = ++cache->action.line_item;
-
- controller_lock_print(print->to, thread);
-
- fl_print_format("%r%[%QRule setting%S '%]", print->to, f_string_eol_s, print->context, print->prefix, before, print->context);
- fl_print_format(f_string_format_Q_range_single_s.string, print->to, print->notable, cache->buffer_item, range, print->notable);
- fl_print_format("%['%S.%]%r", print->to, print->context, after, print->context, f_string_eol_s);
-
- controller_rule_print_error_cache(print, cache->action, F_false);
-
- controller_unlock_print_flush(print->to, thread);
- }
-#endif // _di_controller_rule_setting_read_print_error_with_range_
-
-#ifndef _di_controller_rule_setting_read_print_mapping_
- void controller_rule_setting_read_print_mapping(const controller_global_t global, const f_string_static_t name, const f_string_map_t map) {
-
- if (global.main->program.error.verbosity != f_console_verbosity_debug_e) {
- if (!(global.main->program.error.verbosity == f_console_verbosity_verbose_e && (global.main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e))) {
- return;
- }
- }
-
- controller_lock_print(global.main->program.output.to, global.thread);
-
- fl_print_format("%rProcessing rule item action '%[%Q%]'", global.main->program.output.to, f_string_eol_s, global.main->program.context.set.title, name, global.main->program.context.set.title);
- fl_print_format(" mapping '%[%Q%]'", global.main->program.output.to, global.main->program.context.set.important, map.key, global.main->program.context.set.important);
- fl_print_format(" to value '%[%Q%]'.%r", global.main->program.output.to, global.main->program.context.set.important, map.value, global.main->program.context.set.important, f_string_eol_s);
-
- controller_unlock_print_flush(global.main->program.output.to, global.thread);
- }
-#endif // _di_controller_rule_setting_read_print_mapping_
-
-#ifndef _di_controller_rule_setting_read_print_value_
- void controller_rule_setting_read_print_value(const controller_global_t global, const f_string_static_t name, const f_string_static_t name_sub, const f_string_static_t value, const f_string_t suffix) {
-
- if (global.main->program.error.verbosity != f_console_verbosity_debug_e) {
- if (!(global.main->program.error.verbosity == f_console_verbosity_verbose_e && (global.main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e))) {
- return;
- }
- }
-
- controller_lock_print(global.main->program.output.to, global.thread);
-
- fl_print_format("%rProcessing rule item action '%[%Q%]' setting ", global.main->program.output.to, f_string_eol_s, global.main->program.context.set.title, name, global.main->program.context.set.title);
-
- if (name_sub.used) {
- fl_print_format("'%[%Q%]'", global.main->program.output.to, global.main->program.context.set.notable, name_sub, global.main->program.context.set.notable);
- }
- else {
- f_print_terminated("value", global.main->program.output.to);
- }
-
- fl_print_format(" to '%[%Q%]'", global.main->program.output.to, global.main->program.context.set.important, value, global.main->program.context.set.important);
- fl_print_format("%S.%r", global.main->program.output.to, suffix, f_string_eol_s);
-
- controller_unlock_print_flush(global.main->program.output.to, global.thread);
- }
-#endif // _di_controller_rule_setting_read_print_value_
-
-#ifndef _di_controller_rule_setting_read_print_values_
- void controller_rule_setting_read_print_values(const controller_global_t global, const f_string_static_t name, const f_number_unsigned_t index, controller_cache_t * const cache) {
-
- if (global.main->program.error.verbosity != f_console_verbosity_debug_e) {
- if (!(global.main->program.error.verbosity == f_console_verbosity_verbose_e && (global.main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e))) {
- return;
- }
- }
-
- controller_lock_print(global.main->program.output.to, global.thread);
-
- fl_print_format("%rProcessing rule item action '%[%Q%]' setting value to", global.main->program.output.to, f_string_eol_s, global.main->program.context.set.title, name, global.main->program.context.set.title);
-
- for (f_number_unsigned_t j = 0; j < cache->content_actions.array[index].used; ++j) {
-
- fl_print_format(" '%[%/Q%]'", global.main->program.output.to, global.main->program.context.set.important, cache->buffer_item, cache->content_actions.array[index].array[j], global.main->program.context.set.important);
-
- if (j + 2 == cache->content_actions.array[index].used) {
- if (cache->content_actions.array[index].used > 2) {
- f_print_terminated(",", global.main->program.output.to);
- }
-
- f_print_terminated(" and", global.main->program.output.to);
- }
- else if (j + 1 < cache->content_actions.array[index].used) {
- f_print_terminated(",", global.main->program.output.to);
- }
- } // for
-
- fl_print_format(".%r", global.main->program.output.to, f_string_eol_s);
-
- controller_unlock_print_flush(global.main->program.output.to, global.thread);
- }
-#endif // _di_controller_rule_setting_read_print_value_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_rule_print_h
-#define _PRIVATE_rule_print_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Special strings used for printing.
- */
-#ifndef _di_controller_rule_print_string_s_
- #define CONTROLLER_rule_print_control_groups_prepare_s "prepare control groups for"
- #define CONTROLLER_rule_print_control_groups_prepare_s_length 24
-
- extern const f_string_static_t controller_rule_print_control_groups_prepare_s;
-#endif // _di_controller_rule_print_string_s_
-
-/**
- * Print generic error/warning information.
- *
- * This is essentially a wrapper to fll_error_print() that includes locking.
- *
- * @param thread
- * The thread data.
- * @param print
- * Designates how printing is to be performed.
- * @param cache
- * The action cache.
- * @param status
- * The status code to process.
- * Make sure this has F_status_set_fine() called if the status code has any error or warning bits.
- * @param function
- * (optional) The name of the function where the error happened.
- *
- * Set to NULL to disable.
- * @param fallback
- * Set to F_true to print the fallback error message for unknown errors.
- * @param item
- * If TRUE, then this error is associated with an item.
- * If FALSE, then this error is associated with a rule setting.
- *
- * @see fll_error_print()
- * @see controller_rule_print_error_cache()
- */
-#ifndef _di_controller_rule_print_error_
- extern void controller_rule_print_error(controller_thread_t * const thread, fl_print_t * const print, const controller_cache_action_t cache, const f_status_t status, const f_string_t function, const bool fallback, const bool item) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_print_error_
-
-/**
- * Print additional error/warning information in addition to existing error.
- *
- * This is explicitly intended to be used in addition to the error message.
- *
- * This neither locks the thread nor does it check to see if output is enabled or disabled.
- *
- * @param print
- * The error or warning output structure.
- * @param cache
- * A structure for containing and caching relevant data.
- * @param item
- * If TRUE, then this error is associated with an item.
- * If FALSE, then this error is associated with a rule setting.
- *
- * @see controller_rule_action_read()
- * @see controller_rule_item_read()
- * @see controller_rule_items_read()
- * @see controller_rule_read()
- * @see controller_rule_setting_read()
- */
-#ifndef _di_controller_rule_print_error_cache_
- extern void controller_rule_print_error_cache(fl_print_t * const print, const controller_cache_action_t cache, const bool item) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_print_error_cache_
-
-/**
- * Print additional error/warning information in addition to existing error.
- *
- * This is explicitly intended to be used in addition to the error message.
- *
- * @param thread
- * The thread data.
- * @param print
- * The error or warning print structure.
- * @param cache
- * A structure for containing and caching relevant data.
- * @param item
- * If TRUE, then this error is associated with an item.
- * If FALSE, then this error is associated with a rule setting.
- * @param status
- * The status code representing the failure (without the error bit set).
- *
- * @see controller_rule_print_error_cache()
- */
-#ifndef _di_controller_rule_item_print_error_
- extern void controller_rule_item_print_error(controller_thread_t * const thread, fl_print_t * const print, const controller_cache_action_t cache, const bool item, const f_status_t status) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_item_print_error_
-
-/**
- * Print an error or warning message related to the failed execution of some program or script.
- *
- * @param script_is
- * If TRUE, then this represents a script.
- * If FALSE, then this represents a program.
- * @param name
- * The name of the program or script.
- * @param code
- * The code returned by the executed program or script.
- * @param status
- * The status code representing the failure (without the error bit set).
- * @param process
- * The process to use.
- */
-#ifndef _di_controller_rule_item_print_error_execute_
- extern void controller_rule_item_print_error_execute(const bool script_is, const f_string_static_t name, const f_status_t status, controller_data_t * const process) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_item_print_error_execute_
-
-/**
- * Print an error or warning message about some rule not having the pid file information.
- *
- * @param print
- * The error or warning output structure.
- * @param alias
- * The rule alias of the rule that is missing the pid file designation.
- */
-#ifndef _di_controller_rule_action_print_error_missing_pid_
- extern void controller_rule_action_print_error_missing_pid(fl_print_t * const print, const f_string_static_t alias) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_action_print_error_missing_pid_
-
-/**
- * Print an error or warning message related to need/want/wish settings of some rule.
- *
- * @param print
- * The error or warning output structure.
- * @param need_want_wish
- * The appropriate string, such as "needs", "wants", or "wishes for" to output when describing this error/warning.
- * This string is expected to already be "safe" (no control characters, etc..).
- * @param value
- * The value that is the error or warning.
- * @param why
- * A short explanation on why this is an error or warning.
- */
-#ifndef _di_controller_rule_item_print_error_need_want_wish_
- extern void controller_rule_item_print_error_need_want_wish(fl_print_t * const print, const f_string_static_t need_want_wish, const f_string_static_t value, const f_string_t why) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_item_print_error_need_want_wish_
-
-/**
- * Print an error or warning message about some rule not being loaded.
- *
- * @param print
- * The error or warning output structure.
- * @param alias
- * The rule alias of the rule that is not loaded.
- */
-#ifndef _di_controller_rule_item_print_error_rule_not_loaded_
- extern void controller_rule_item_print_error_rule_not_loaded(fl_print_t * const print, const f_string_static_t alias) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_item_print_error_rule_not_loaded_
-
-/**
- * Print a message about a rule setting problem.
- *
- * This is intended to be explicitly called by controller_rule_setting_read().
- * This is intended only to be used for simple messages.
- *
- * @param print
- * The error or warning output structure.
- * @param message
- * The string to append to the message being printed.
- * @param index
- * The position in the object actions cache representing the object.
- * @param line_item
- * The current line number.
- * @param thread
- * The thread data.
- * @param cache
- * A structure for containing and caching relevant data.
- *
- * @see controller_rule_setting_read()
- */
-#ifndef _di_controller_rule_setting_read_print_error_
- extern void controller_rule_setting_read_print_error(fl_print_t * const print, const f_string_t message, const f_number_unsigned_t index, const f_number_unsigned_t line_item, controller_thread_t * const thread, controller_cache_t * const cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_setting_read_print_error_
-
-/**
- * Print a message about a rule setting problem, with additional messages about the value.
- *
- * This is intended to be explicitly called by controller_rule_setting_read().
- * This is intended only to be used for simple messages.
- *
- * @param print
- * The error or warning output structure.
- * @param before
- * The string to add to the message being printed (before the value).
- * @param range
- * The range within the cache item buffer representing the value.
- * @param after
- * The string to add to the message being printed (after the value).
- * @param index
- * The position in the object actions cache representing the object.
- * @param line_item
- * The current line number.
- * @param thread
- * The thread data.
- * @param cache
- * A structure for containing and caching relevant data.
- *
- * @see controller_rule_setting_read()
- */
-#ifndef _di_controller_rule_setting_read_print_error_with_range_
- extern void controller_rule_setting_read_print_error_with_range(fl_print_t * const print, const f_string_t before, const f_range_t range, const f_string_t after, const f_number_unsigned_t index, const f_number_unsigned_t line_item, controller_thread_t * const thread, controller_cache_t * const cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_setting_read_print_error_with_range_
-
-/**
- * Print message regarding the mapping of a setting when in simulation or verbose mode.
- *
- * @param global
- * The global data.
- * @param name
- * The Object name of the setting being populated.
- * @param map
- * The map being applied.
- */
-#ifndef _di_controller_rule_setting_read_print_mapping_
- extern void controller_rule_setting_read_print_mapping(const controller_global_t global, const f_string_static_t name, const f_string_map_t map) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_setting_read_print_mapping_
-
-/**
- * Print message regarding the population of a setting when in simulation or verbose mode.
- *
- * @param global
- * The global data.
- * @param name
- * The Object name of the setting being populated.
- * @param name_sub
- * A sub-name associated with the setting being populated.
- * Set to a string with used set to 0 to not use.
- * @param value
- * The value being set.
- * @param suffix
- * An additional message to append at the end (before the final period).
- */
-#ifndef _di_controller_rule_setting_read_print_value_
- extern void controller_rule_setting_read_print_value(const controller_global_t global, const f_string_static_t name, const f_string_static_t name_sub, const f_string_static_t value, const f_string_t suffix) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_setting_read_print_value_
-
-/**
- * Print message regarding the population of a setting when in simulation or verbose mode.
- *
- * This handles the case where there are multiple values stored in the buffer_item at a given content_actions position.
- *
- * @param global
- * The global data.
- * @param name
- * The Object name of the setting being populated.
- * @param index
- * Position within the content_actions range cache array.
- * @param cache
- * A structure for containing and caching relevant data.
- */
-#ifndef _di_controller_rule_setting_read_print_values_
- extern void controller_rule_setting_read_print_values(const controller_global_t global, const f_string_static_t name, const f_number_unsigned_t index, controller_cache_t * const cache) F_attribute_visibility_internal_d;
-#endif // _di_controller_rule_setting_read_print_values_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_rule_print_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "../controller/private-controller.h"
-#include "../controller/private-controller_print.h"
-#include "../lock/private-lock.h"
-#include "../lock/private-lock_print.h"
-#include "../rule/private-rule.h"
-#include "../thread/private-thread.h"
-#include "../thread/private-thread_control.h"
-#include "../thread/private-thread_entry.h"
-#include "../thread/private-thread_process.h"
-#include "../thread/private-thread_rule.h"
-#include "../thread/private-thread_signal.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_thread_cleanup_
- void * controller_thread_cleanup(void * const arguments) {
-
- f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
-
- const controller_global_t *global = (controller_global_t *) arguments;
-
- if (global->thread->enabled != controller_thread_enabled_e) return 0;
-
- const f_time_spec_t delay = controller_time_seconds((global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) ? controller_thread_cleanup_interval_short_d : controller_thread_cleanup_interval_long_d);
-
- f_status_t status = F_okay;
-
- while (global->thread->enabled == controller_thread_enabled_e) {
-
- nanosleep(&delay, 0);
-
- if (global->thread->enabled != controller_thread_enabled_e) break;
-
- if (f_thread_lock_write_try(&global->thread->lock.process) == F_okay) {
- controller_data_t *process = 0;
-
- f_number_unsigned_t i = 0;
-
- for (; i < global->thread->processs.size && global->thread->enabled == controller_thread_enabled_e; ++i) {
-
- if (!global->thread->processs.array[i]) continue;
-
- process = global->thread->processs.array[i];
-
- // If "active" has a read lock, then do not attempt to clean it.
- if (f_thread_lock_write_try(&process->active) != F_okay) {
- continue;
- }
-
- // If "lock" has a read or write lock, then do not attempt to clean it.
- if (f_thread_lock_write_try(&process->lock) != F_okay) {
- f_thread_unlock(&process->active);
-
- continue;
- }
-
- // If process is active or busy, then do not attempt to clean it.
- if (process->state == controller_process_state_active_e || process->state == controller_process_state_busy_e) {
- f_thread_unlock(&process->active);
- f_thread_unlock(&process->lock);
-
- continue;
- }
-
- // If process has a PID file, then it is running in the background, only cleanup if the PID file no longer exists.
- if (process->path_pids.used) {
- f_number_unsigned_t j = 0;
-
- for (; j < process->path_pids.used; ++j) {
-
- if (process->path_pids.array[j].used && f_file_exists(process->path_pids.array[j], F_true) == F_true) {
- break;
- }
- } // for
-
- if (j < process->path_pids.used) {
- f_thread_unlock(&process->active);
- f_thread_unlock(&process->lock);
-
- continue;
- }
- }
-
- f_thread_unlock(&process->lock);
-
- // Close any still open thread.
- if (process->id_thread) {
- status = f_thread_join(process->id_thread, 0);
-
- if (F_status_is_error_not(status) || F_status_set_fine(status) == F_found_not) {
- status = f_thread_lock_write(&process->lock);
-
- if (F_status_is_error(status)) {
- controller_lock_print_error_critical(&global->main->program.error, F_status_set_fine(status), F_false, global->thread);
-
- f_thread_unlock(&process->active);
- continue;
- }
-
- process->state = controller_process_state_idle_e;
- process->id_thread = 0;
-
- f_thread_mutex_lock(&process->wait_lock);
- f_thread_condition_signal_all(&process->wait);
- f_thread_mutex_unlock(&process->wait_lock);
-
- f_thread_unlock(&process->lock);
- }
- else {
- f_thread_unlock(&process->active);
-
- continue;
- }
- }
-
- // De-allocate dynamic portions of the structure that are only ever needed while the process is running.
- controller_cache_delete_simple(&process->cache);
- f_memory_array_resize(0, sizeof(f_number_unsigned_t), (void **) &process->stack.array, &process->stack.used, &process->stack.size);
-
- // Shrink the childs array.
- if (process->childs.used) {
- for (; process->childs.used; --process->childs.used) {
- if (process->childs.array[process->childs.used]) break;
- } // for
-
- if (process->childs.used < process->childs.size) {
- controller_pids_resize(process->childs.used, &process->childs);
- }
- }
-
- // De-allocate the PID files.
- if (process->path_pids.used) {
- process->path_pids.used = 0;
-
- f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &process->path_pids.array, &process->path_pids.used, &process->path_pids.size, &f_string_dynamics_delete_callback);
- }
-
- // De-allocate any rules in the space that is declared to be unused.
- if (i >= global->thread->processs.used) {
- controller_rule_delete(&process->rule);
- }
-
- f_thread_unlock(&process->active);
- } // for
-
- f_thread_unlock(&global->thread->lock.process);
- }
- } // while
-
- return 0;
- }
-#endif // _di_controller_thread_cleanup_
-
-#ifndef _di_controller_thread_detach_
- f_status_t controller_thread_detach(f_thread_id_t * const id) {
-
- if (!id || !*id) return F_data_not;
-
- const f_status_t status = f_thread_detach(*id);
-
- if (F_status_is_error_not(status) || F_status_set_fine(status) == F_found_not) {
- *id = 0;
- }
-
- return status;
- }
-#endif // _di_controller_thread_detach_
-
-#ifndef _di_controller_thread_is_enabled_
- f_status_t controller_thread_is_enabled(const bool is_normal, controller_thread_t * const thread) {
-
- return is_normal ? thread->enabled == controller_thread_enabled_e : thread->enabled;
- }
-#endif // _di_controller_thread_is_enabled_
-
-#ifndef _di_controller_thread_is_enabled_process_
- f_status_t controller_thread_is_enabled_process(controller_data_t * const process, controller_thread_t * const thread) {
-
- return controller_thread_is_enabled_process_type(process->type, thread);
- }
-#endif // _di_controller_thread_is_enabled_process_
-
-#ifndef _di_controller_thread_is_enabled_process_type_
- f_status_t controller_thread_is_enabled_process_type(const uint8_t type, controller_thread_t * const thread) {
-
- return controller_thread_is_enabled(type != controller_data_type_exit_e, thread);
- }
-#endif // _di_controller_thread_is_enabled_process_type_
-
-#ifndef _di_controller_thread_main_
- f_status_t controller_thread_main(controller_main_t * const main, controller_process_t * const setting) {
-
- f_status_t status = F_okay;
-
- controller_thread_t thread = controller_thread_t_initialize;
- controller_global_t global = macro_controller_global_t_initialize_1(main, setting, &thread);
-
- // The global locks must be initialized, but only once, so initialize immediately upon allocation.
- status = controller_lock_create(&thread.lock);
-
- if (F_status_is_error(status)) {
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- fll_error_print(&main->program.error, status, "controller_lock_create", fll_error_file_flag_fallback_e);
- }
- }
- else {
- status = controller_processs_increase(&thread.processs);
-
- if (F_status_is_error(status)) {
- controller_print_error(&thread, &main->program.error, F_status_set_fine(status), "controller_processs_increase", F_true);
- }
- }
-
- if (F_status_is_error_not(status)) {
- status = f_thread_create(0, &thread.id_signal, &controller_thread_signal_normal, (void *) &global);
- }
-
- if (F_status_is_error(status)) {
- thread.id_signal = 0;
-
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_print_error(&thread, &main->program.error, F_status_set_fine(status), "f_thread_create", F_true);
- }
- }
- else {
- if (main->program.parameters.array[controller_parameter_daemon_e].result & f_console_result_found_e) {
- setting->ready = controller_setting_ready_done_e;
-
- if (f_file_exists(setting->path_pid, F_true) == F_true) {
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(main->program.error.to, &thread);
-
- fl_print_format("%r%[%QThe pid file '%]", main->program.error.to, f_string_eol_s, main->program.error.context, main->program.error.prefix, main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, main->program.error.to, main->program.error.notable, setting->path_pid, main->program.error.notable);
- fl_print_format("%[' must not already exist.%]%r", main->program.error.to, main->program.error.context, main->program.error.context, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.error.to, &thread);
- }
-
- setting->ready = controller_setting_ready_abort_e;
- status = F_status_set_error(F_available_not);
- }
- }
- else if (global.setting->name_entry.used) {
- const controller_main_entry_t entry = macro_controller_main_entry_t_initialize_1(&global, global.setting);
-
- status = f_thread_create(0, &thread.id_entry, &controller_thread_entry, (void *) &entry);
-
- if (F_status_is_error(status)) {
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_print_error(&thread, &main->program.error, F_status_set_fine(status), "f_thread_create", F_true);
- }
- }
- else {
- controller_thread_join(&thread.id_entry);
-
- status = thread.status;
- thread.id_entry = 0;
- }
- }
- }
-
- // Only make the rule and control threads available once any/all pre-processing and are completed.
- if (F_status_is_error_not(status) && status != F_failure && status != F_child && thread.enabled == controller_thread_enabled_e) {
- if (!(main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e)) {
-
- // Wait for the entry thread to complete before starting the rule thread.
- controller_thread_join(&thread.id_rule);
-
- if (thread.enabled && setting->mode == controller_setting_mode_service_e) {
- status = f_thread_create(0, &thread.id_rule, &controller_thread_rule, (void *) &global);
-
- if (F_status_is_error(status)) {
- thread.id_rule = 0;
- }
- else {
- status = f_thread_create(0, &thread.id_cleanup, &controller_thread_cleanup, (void *) &global);
- }
-
- if (F_status_is_error(status)) {
- thread.id_cleanup = 0;
-
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_print_error(&thread, &main->program.error, F_status_set_fine(status), "f_thread_create", F_true);
- }
- }
- }
- }
- }
-
- if (status == F_child) {
- controller_thread_delete_simple(&thread);
-
- return F_child;
- }
-
- if (F_status_is_error_not(status) && status != F_failure && !(main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e) && controller_thread_is_enabled(F_true, &thread)) {
-
- if (setting->mode == controller_setting_mode_service_e) {
- controller_thread_join(&thread.id_signal);
- }
- else if (setting->mode == controller_setting_mode_helper_e) {
- status = controller_rule_wait_all(global, F_true, F_false);
- }
- else if (setting->mode == controller_setting_mode_program_e) {
- status = controller_rule_wait_all(global, F_true, F_false);
- }
- }
-
- controller_thread_process_cancel(global, F_true, controller_thread_cancel_call_e);
-
- controller_thread_process_exit(&global);
-
- if (thread.id_signal) f_thread_join(thread.id_signal, 0);
- if (thread.id_cleanup) f_thread_join(thread.id_cleanup, 0);
- if (thread.id_control) f_thread_join(thread.id_control, 0);
- if (thread.id_entry) f_thread_join(thread.id_entry, 0);
- if (thread.id_rule) f_thread_join(thread.id_rule, 0);
-
- thread.id_cleanup = 0;
- thread.id_control = 0;
- thread.id_entry = 0;
- thread.id_rule = 0;
- thread.id_signal = 0;
-
- controller_thread_delete_simple(&thread);
-
- if (F_status_is_error(status)) {
- return F_status_set_error(F_failure);
- }
-
- if (F_status_set_fine(status) == F_interrupt) {
- fll_program_print_signal_received(&main->program.warning, thread.signal);
-
- if (main->program.output.verbosity != f_console_verbosity_quiet_e) {
- fll_print_dynamic_raw(f_string_eol_s, main->program.output.to);
- }
-
- return F_status_set_error(F_interrupt);
- }
-
- return F_okay;
- }
-#endif // _di_controller_thread_main_
-
-#ifndef _di_controller_thread_join_
- f_status_t controller_thread_join(f_thread_id_t * const id) {
-
- if (!id || !*id) return F_data_not;
-
- const f_status_t status = f_thread_join(*id, 0);
-
- if (F_status_is_error_not(status) || F_status_set_fine(status) == F_found_not) {
- *id = 0;
- }
-
- return status;
- }
-#endif // _di_controller_thread_join_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_thread_h
-#define _PRIVATE_thread_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Thread for periodically cleanup data when not busy.
- *
- * @param arguments
- * The thread arguments.
- * Must be of type controller_global_t.
- *
- * @return
- * 0, always.
- */
-#ifndef _di_controller_thread_cleanup_
- extern void * controller_thread_cleanup(void * const arguments) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_cleanup_
-
-/***
- * Detach a thread, assigning id to NULL on success.
- *
- * If the ID is not found, then it is also set to NULL.
- *
- * This should be called for asynchronous processes.
- *
- * @param id
- * The thread ID.
- *
- * @return
- * F_okay on success.
- *
- * Success from: f_thread_detach().
- *
- * Errors (with error bit) from: f_thread_detach().
- *
- * @see f_thread_detach()
- */
-#ifndef _di_controller_thread_detach_
- extern f_status_t controller_thread_detach(f_thread_id_t * const id) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_detach_
-
-/**
- * Check to see if thread is enabled for the normal operations like entry and control or for exit operations.
- *
- * @param is_normal
- * If TRUE, then process as if this operates during a normal operation (entry and control).
- * If FALSE, then process as if this operates during a an exit operation.
- * @param thread
- * The thread data.
- *
- * @return
- * TRUE when enabled.
- * FALSE when disabled.
- */
-#ifndef _di_controller_thread_is_enabled_
- extern f_status_t controller_thread_is_enabled(const bool is_normal, controller_thread_t * const thread) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_is_enabled_
-
-/**
- * Check to see if thread is enabled for the normal operations like entry and control or for exit operations for some process.
- *
- * @param process
- * The process to use when checking if thread is enabled.
- * @param thread
- * The thread data.
- *
- * @return
- *
- * Success from controller_thread_is_enabled_process_type().
- *
- * @see controller_thread_is_enabled_process_type()
- */
-#ifndef _di_controller_thread_is_enabled_process_
- extern f_status_t controller_thread_is_enabled_process(controller_data_t * const process, controller_thread_t * const thread) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_is_enabled_process_
-
-/**
- * Check to see if thread is enabled for the normal operations like entry and control or for exit operations for some process type.
- *
- * @param type
- * The process type to use when checking if thread is enabled.
- * @param thread
- * The thread data.
- *
- * @return
- *
- * Success from controller_thread_is_enabled().
- *
- * @see controller_thread_is_enabled()
- */
-#ifndef _di_controller_thread_is_enabled_process_type_
- extern f_status_t controller_thread_is_enabled_process_type(const uint8_t type, controller_thread_t * const thread) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_is_enabled_process_type_
-
-/**
- * Start all threads, wait on threads, and handle requests.
- *
- * @param main
- * The main program data.
- * @param setting
- * The controller settings data.
- *
- * @return
- * F_okay on success.
- * F_child on child process exiting.
- *
- * F_failure (with error bit) on any failure.
- * F_interrupt (with error bit) on receiving a process signal, such as an interrupt signal.
- */
-#ifndef _di_controller_thread_main_
- extern f_status_t controller_thread_main(controller_main_t * const main, controller_process_t * const setting) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_main_
-
-/***
- * Join a thread, assigning id to NULL on success.
- *
- * If the ID is not found, then it is also set to NULL.
- *
- * @param id
- * The thread ID.
- *
- * @return
- * F_okay on success.
- *
- * Success from: f_thread_join().
- *
- * Errors (with error bit) from: f_thread_join().
- *
- * @see f_thread_join()
- */
-#ifndef _di_controller_thread_join_
- extern f_status_t controller_thread_join(f_thread_id_t * const id) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_join_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_thread_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "../control/private-control.h"
-#include "../controller/private-controller.h"
-#include "../controller/private-controller_print.h"
-#include "private-thread.h"
-#include "private-thread_control.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_thread_control_
- void * controller_thread_control(void * const arguments) {
-
- f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
-
- const controller_global_t *global = (controller_global_t *) arguments;
-
- if (global->thread->enabled != controller_thread_enabled_e) return 0;
-
- f_status_t status = F_okay;
-
- if (status == F_child) {
-
- // A forked child process should de-allocate memory on exit.
- // It seems that this function doesn't return to the calling thread for a forked child process, even with the "return 0;" below.
- // De-allocate as much as possible.
- controller_thread_delete_simple(global->thread);
- controller_process_delete(global->setting);
- controller_main_delete(global->main);
- }
-
- return 0;
- }
-#endif // _di_controller_thread_control_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_thread_control_h
-#define _PRIVATE_thread_control_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Thread for handling control requests and responses.
- *
- * @param arguments
- * The thread arguments.
- * Must be of type controller_global_t.
- *
- * @return
- * 0, always.
- */
-#ifndef _di_controller_thread_control_
- extern void * controller_thread_control(void * const arguments) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_control_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_thread_control_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "../entry/private-entry.h"
-#include "../lock/private-lock_print.h"
-#include "../thread/private-thread.h"
-#include "private-thread_entry.h"
-#include "private-thread_process.h"
-#include "private-thread_signal.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_thread_entry_
- void * controller_thread_entry(void * const arguments) {
-
- f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
-
- controller_main_entry_t *entry = (controller_main_entry_t *) arguments;
-
- if (!controller_thread_is_enabled(F_true, entry->global->thread)) return 0;
-
- controller_main_t *main = entry->global->main;
- controller_cache_t *cache = &entry->global->thread->cache;
- f_status_t *status = &entry->global->thread->status;
-
- *status = controller_entry_read(*entry->global, F_true, cache);
-
- if (F_status_set_fine(*status) == F_interrupt) {
- entry->setting->ready = controller_setting_ready_abort_e;
- }
- else if (F_status_is_error(*status)) {
- entry->setting->ready = controller_setting_ready_fail_e;
- }
- else if (*status != F_child) {
- *status = controller_entry_preprocess(*entry->global, F_true, cache);
-
- if ((entry->global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) && (entry->global->main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e)) {
- controller_entry_setting_validate(*entry->global, F_true, cache);
- }
- }
-
- if (F_status_is_error_not(*status) && *status != F_child) {
- if (!(main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e) || (main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e)) {
-
- if (entry->setting->entry.pid == controller_entry_pid_require_e && f_file_exists(entry->setting->path_pid, F_true) == F_true) {
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(main->program.error.to, entry->global->thread);
-
- fl_print_format("%r%[%QThe pid file '%]", main->program.error.to, f_string_eol_s, main->program.error.context, main->program.error.prefix, main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, main->program.error.to, main->program.error.notable, entry->setting->path_pid, main->program.error.notable);
- fl_print_format("%[' must not already exist.%]%r", main->program.error.to, main->program.error.context, main->program.error.context, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.error.to, entry->global->thread);
- }
-
- entry->setting->ready = controller_setting_ready_fail_e;
- *status = F_status_set_error(F_available_not);
- }
- else {
- *status = controller_entry_process(entry->global, cache, F_false, F_true);
-
- if (F_status_is_error(*status)) {
- entry->setting->ready = controller_setting_ready_fail_e;
-
- if ((F_status_set_fine(*status) == F_execute || F_status_set_fine(*status) == F_require) && (entry->global->setting->flag & controller_setting_flag_failsafe_e)) {
- const uint8_t original_enabled = entry->global->thread->enabled;
-
- // Restore operating mode so that the failsafe can execute.
- *status = f_thread_mutex_lock(&entry->global->thread->lock.alert);
-
- if (F_status_is_error_not(*status)) {
- entry->global->thread->enabled = controller_thread_enabled_e;
-
- f_thread_mutex_unlock(&entry->global->thread->lock.alert);
- }
-
- // Restart the signal thread to allow for signals while operating the failsafe Items.
- if (!entry->global->thread->id_signal) {
- f_thread_create(0, &entry->global->thread->id_signal, &controller_thread_signal_normal, (void *) entry->global);
- }
-
- const f_status_t status_failsafe = controller_entry_process(entry->global, cache, F_true, F_true);
-
- if (F_status_is_error(status_failsafe)) {
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(main->program.error.to, entry->global->thread);
-
- fl_print_format("%r%[%QFailed while processing requested failsafe item '%]", main->program.error.to, f_string_eol_s, main->program.error.context, main->program.error.prefix, main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, main->program.error.to, main->program.error.notable, entry->global->setting->entry.items.array[entry->global->setting->failsafe_item_id].name, main->program.error.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, main->program.error.to, main->program.error.context, main->program.error.context, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.error.to, entry->global->thread);
- }
-
- *status = F_status_set_error(F_failure);
- }
- else {
-
- // Restore operating mode to value prior to failsafe mode.
- *status = f_thread_mutex_lock(&entry->global->thread->lock.alert);
-
- if (F_status_is_error_not(*status)) {
- entry->global->thread->enabled = original_enabled;
-
- f_thread_mutex_unlock(&entry->global->thread->lock.alert);
- }
-
- *status = F_failure;
- }
- }
- }
- else if (F_status_set_fine(*status) == F_interrupt) {
- entry->setting->ready = controller_setting_ready_abort_e;
- }
- else if (*status != F_child) {
- entry->setting->ready = controller_setting_ready_done_e;
- }
- }
-
- if (F_status_is_error_not(*status) && *status != F_child && entry->global->main->program.parameters.array[controller_parameter_validate_e].result == f_console_result_none_e && entry->global->setting->mode == controller_setting_mode_helper_e) {
- f_time_spec_t time;
- time.tv_sec = controller_thread_exit_helper_timeout_seconds_d;
- time.tv_nsec = controller_thread_exit_helper_timeout_nanoseconds_d;
-
- nanosleep(&time, 0);
-
- controller_thread_process_cancel(*(entry->global), F_true, controller_thread_cancel_exit_e);
- }
- }
- }
-
- if (*status == F_child) {
-
- // A forked child process should de-allocate memory on exit.
- // It seems that this function doesn't return to the calling thread for a forked child process, even with the "return 0;" below.
- // De-allocate as much as possible.
- controller_thread_delete_simple(entry->global->thread);
- controller_process_delete(entry->global->setting);
- controller_main_delete(entry->global->main);
-
- // According to the manpages, pthread_exit() calls exit(0), which is not good because a non-zero exit code may be returned.
- if (main->program.child) exit(main->program.child);
-
- return 0;
- }
-
- f_thread_condition_signal_all(&entry->global->thread->lock.alert_condition);
-
- return 0;
- }
-#endif // _di_controller_thread_entry_
-
-#ifndef _di_controller_thread_exit_
- void * controller_thread_exit(void * const arguments) {
-
- f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
-
- controller_main_entry_t *entry = (controller_main_entry_t *) arguments;
-
- controller_main_t *main = entry->global->main;
- controller_cache_t *cache = &entry->global->thread->cache;
- f_status_t *status = &entry->global->thread->status;
-
- *status = controller_entry_read(*entry->global, F_false, cache);
-
- if (F_status_set_fine(*status) == F_interrupt) {
- entry->setting->ready = controller_setting_ready_abort_e;
- }
- else if (F_status_is_error(*status)) {
- entry->setting->ready = controller_setting_ready_fail_e;
- }
- else if (*status == F_file_found_not) {
- entry->setting->ready = controller_setting_ready_done_e;
- }
- else if (*status != F_child) {
- *status = controller_entry_preprocess(*entry->global, F_false, cache);
-
- if ((entry->global->main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) && (entry->global->main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e)) {
- controller_entry_setting_validate(*entry->global, F_false, cache);
- }
- }
-
- if (F_status_is_error_not(*status) && *status != F_child && *status != F_file_found_not) {
- if (!(main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e) || (main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e)) {
-
- *status = controller_entry_process(entry->global, cache, F_false, F_false);
-
- if (F_status_is_error(*status)) {
- entry->setting->ready = controller_setting_ready_fail_e;
-
- if ((F_status_set_fine(*status) == F_execute || F_status_set_fine(*status) == F_require) && (entry->global->setting->flag & controller_setting_flag_failsafe_e)) {
-
- const uint8_t original_enabled = entry->global->thread->enabled;
-
- // Restore operating mode so that the failsafe can execute.
- if (F_status_set_fine(*status) == F_execute) {
- *status = f_thread_mutex_lock(&entry->global->thread->lock.alert);
-
- if (F_status_is_error_not(*status)) {
- entry->global->thread->enabled = controller_thread_enabled_exit_e;
-
- f_thread_mutex_unlock(&entry->global->thread->lock.alert);
- }
-
- // Restart the signal thread to allow for signals while operating the failsafe Items.
- if (!entry->global->thread->id_signal) {
- f_thread_create(0, &entry->global->thread->id_signal, &controller_thread_signal_other, (void *) entry->global);
- }
- }
-
- const f_status_t status_failsafe = controller_entry_process(entry->global, cache, F_true, F_false);
-
- if (F_status_is_error(status_failsafe)) {
- if (main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_lock_print(main->program.error.to, entry->global->thread);
-
- fl_print_format("%r%[%QFailed while processing requested failsafe item '%]", main->program.error.to, f_string_eol_s, main->program.error.context, main->program.error.prefix, main->program.error.context);
- fl_print_format(f_string_format_Q_single_s.string, main->program.error.to, main->program.error.notable, entry->global->setting->entry.items.array[entry->global->setting->failsafe_item_id].name, main->program.error.notable);
- fl_print_format(f_string_format_sentence_end_quote_s.string, main->program.error.to, main->program.error.context, main->program.error.context, f_string_eol_s);
-
- controller_unlock_print_flush(main->program.error.to, entry->global->thread);
- }
-
- *status = F_status_set_error(F_failure);
- }
- else {
-
- // Restore operating mode to value prior to failsafe mode.
- *status = f_thread_mutex_lock(&entry->global->thread->lock.alert);
-
- if (F_status_is_error_not(*status)) {
- entry->global->thread->enabled = original_enabled;
-
- f_thread_mutex_unlock(&entry->global->thread->lock.alert);
- }
-
- *status = F_failure;
- }
- }
- }
- else if (F_status_set_fine(*status) == F_interrupt) {
- entry->setting->ready = controller_setting_ready_abort_e;
- }
- else if (*status != F_child) {
- entry->setting->ready = controller_setting_ready_done_e;
- }
- }
- }
-
- if (*status == F_child) {
-
- // A forked child process should de-allocate memory on exit.
- // It seems that this function doesn't return to the calling thread for a forked child process, even with the "return 0;" below.
- // De-allocate as much as possible.
- controller_thread_delete_simple(entry->global->thread);
- controller_process_delete(entry->global->setting);
- controller_main_delete(entry->global->main);
-
- return 0;
- }
-
- if (F_status_is_error_not(f_thread_mutex_lock(&entry->global->thread->lock.alert))) {
- entry->global->thread->enabled = controller_thread_enabled_not_e;
-
- f_thread_mutex_unlock(&entry->global->thread->lock.alert);
- }
-
- f_thread_condition_signal_all(&entry->global->thread->lock.alert_condition);
-
- return 0;
- }
-#endif // _di_controller_thread_exit_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_thread_entry_h
-#define _PRIVATE_thread_entry_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Thread for handling entry processing.
- *
- * This acts as the main rule thread during entry processing.
- * This runs all synchronous rules or spawns asynchronous rules.
- *
- * @param arguments
- * The thread arguments.
- * Must be of type controller_main_entry_t.
- *
- * @return
- * 0, always.
- */
-#ifndef _di_controller_thread_entry_
- extern void * controller_thread_entry(void * const arguments) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_entry_
-
-/**
- * Thread for handling exit file processing.
- *
- * This acts as the main rule thread during exit processing.
- * This runs all synchronous rules or spawns asynchronous rules.
- *
- * Do not confuse this with exiting a thread, this is the what process the exit files (similar to that of an entry file).
- * Exit files process the "stop" action, whereas the Entry files process the "start" Action
- *
- * @param arguments
- * The thread arguments.
- * Must be of type controller_main_entry_t.
- *
- * @return
- * 0, always.
- */
-#ifndef _di_controller_thread_exit_
- extern void * controller_thread_exit(void * const arguments) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_exit_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_thread_entry_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "../controller/private-controller.h"
-#include "../controller/private-controller_print.h"
-#include "../rule/private-rule.h"
-#include "private-thread.h"
-#include "private-thread_entry.h"
-#include "private-thread_process.h"
-#include "private-thread_signal.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_thread_process_
- void controller_thread_process(const bool is_normal, controller_data_t * const process) {
-
- {
- controller_thread_t *thread = (controller_thread_t *) process->main_thread;
-
- if (!controller_thread_is_enabled(is_normal, thread)) return;
- }
-
- const f_status_t status = controller_rule_process_do(controller_process_option_asynchronous_d, process);
-
- if (status == F_child) {
-
- // A forked child process should de-allocate memory on exit.
- // It seems that this function doesn't return to the calling thread for a forked child process, even with the "return 0;" below.
- // De-allocate as much as possible.
- controller_main_t *main = (controller_main_t *) process->main_data;
- controller_process_t *setting = (controller_process_t *) process->main_setting;
- controller_thread_t *thread = (controller_thread_t *) process->main_thread;
-
- controller_thread_delete_simple(thread);
- controller_process_delete(setting);
- controller_main_delete(main);
-
- // According to the manpages, pthread_exit() calls exit(0), which is not good because a non-zero exit code may be returned.
- if (main->program.child) exit(main->program.child);
- }
- }
-#endif // _di_controller_thread_process_
-
-#ifndef _di_controller_thread_process_cancel_
- void controller_thread_process_cancel(const controller_global_t global, const bool is_normal, const uint8_t by) {
-
- f_thread_mutex_lock(&global.thread->lock.cancel);
-
- // Only cancel when enabled.
- if (!controller_thread_is_enabled(is_normal, global.thread)) {
- f_thread_mutex_unlock(&global.thread->lock.cancel);
-
- return;
- }
-
- f_time_spec_t time;
-
- controller_entry_t *entry = 0;
- controller_data_t *process = 0;
-
- f_status_t status = F_okay;
- f_number_unsigned_t i = 0;
- f_number_unsigned_t j = 0;
- pid_t pid = 0;
-
- if (is_normal) {
- entry = &global.setting->entry;
- }
- else {
- entry = &global.setting->exit;
- }
-
- // A simple but inaccurate interval counter (expect this to be replaced in the future).
- const f_number_unsigned_t interval_nanoseconds = entry->timeout_exit < 1000 ? (entry->timeout_exit < 100 ? 5000000 : 100000000) : 500000000;
- const f_number_unsigned_t interval_milliseconds = entry->timeout_exit < 1000 ? (entry->timeout_exit < 100 ? 5 : 100) : 500;
-
- time.tv_sec = 0;
- time.tv_nsec = interval_nanoseconds;
-
- if (global.setting->mode == controller_setting_mode_helper_e && global.main->program.parameters.array[controller_parameter_validate_e].result == f_console_result_none_e) {
- int value = 0;
- f_number_unsigned_t lapsed = 0;
-
- for (i = 0; i < global.thread->processs.used; ++i) {
-
- if (!global.thread->processs.array[i]) continue;
- //if (caller && i == caller->id) continue; // @fixme "caller" disappeared at some point.
-
- process = global.thread->processs.array[i];
-
- if (!process->id_thread) continue;
-
- controller_thread_detach(&process->id_thread);
-
- process->id_thread = 0;
- } // for
- }
-
- // Use the alert lock to toggle enabled (using it as if it is a write like and a signal lock).
- status = f_thread_mutex_lock(&global.thread->lock.alert);
-
- if (F_status_is_error(status)) {
- global.thread->enabled = controller_thread_enabled_not_e;
- }
- else {
- if (by == controller_thread_cancel_execute_e) {
- global.thread->enabled = controller_thread_enabled_execute_e;
- }
- else if (by == controller_thread_cancel_exit_e) {
- global.thread->enabled = controller_thread_enabled_not_e;
- }
- else if (by == controller_thread_cancel_exit_execute_e) {
- global.thread->enabled = controller_thread_enabled_exit_execute_e;
- }
- else {
- global.thread->enabled = controller_thread_enabled_exit_e;
- }
-
- f_thread_mutex_unlock(&global.thread->lock.alert);
- }
-
- if (global.thread->id_cleanup) {
- f_thread_cancel(global.thread->id_cleanup);
- f_thread_join(global.thread->id_cleanup, 0);
-
- global.thread->id_cleanup = 0;
- }
-
- if (global.thread->id_control) {
- f_thread_cancel(global.thread->id_control);
- f_thread_join(global.thread->id_control, 0);
-
- global.thread->id_control = 0;
- }
-
- // The sigtimedwait() function that is run inside of signal must be interrupted via the f_thread_cancel().
- if (by != controller_thread_cancel_signal_e && global.thread->id_signal) {
- f_thread_cancel(global.thread->id_signal);
- f_thread_join(global.thread->id_signal, 0);
-
- global.thread->id_signal = 0;
- }
-
- if (global.setting->mode == controller_setting_mode_helper_e && global.main->program.parameters.array[controller_parameter_validate_e].result == f_console_result_none_e) {
- f_thread_mutex_unlock(&global.thread->lock.cancel);
-
- return;
- }
-
- for (; i < global.thread->processs.used; ++i) {
-
- if (!global.thread->processs.array[i]) continue;
-
- process = global.thread->processs.array[i];
-
- // Do not cancel exit processes, when not performing "execute" during exit.
- if (process->type == controller_data_type_exit_e && global.thread->enabled != controller_thread_enabled_exit_execute_e) {
- continue;
- }
-
- for (j = 0; j < process->childs.used; ++j) {
-
- if (process->childs.array[j] > 0) {
- f_signal_send(global.thread->signal ? global.thread->signal : F_signal_termination, process->childs.array[j]);
- }
- } // for
-
- for (j = 0; j < process->path_pids.used; ++j) {
-
- if (process->path_pids.array[j].used && f_file_exists(process->path_pids.array[j], F_true) == F_true) {
- status = controller_file_pid_read(process->path_pids.array[j], &pid);
-
- if (pid) {
- f_signal_send(global.thread->signal ? global.thread->signal : F_signal_termination, pid);
- }
- }
- } // for
- } // for
-
- if (entry->timeout_exit && !(entry->flag & controller_entry_flag_timeout_exit_no_e)) {
- f_number_unsigned_t lapsed = 0;
-
- for (i = 0; i < global.thread->processs.used && lapsed < entry->timeout_exit; ++i) {
-
- if (!global.thread->processs.array[i]) continue;
-
- process = global.thread->processs.array[i];
-
- // Do not wait for processes, when not performing "execute" during exit.
- if (process->type == controller_data_type_exit_e && global.thread->enabled != controller_thread_enabled_exit_execute_e) {
- continue;
- }
-
- for (j = 0; j < process->childs.used && lapsed < entry->timeout_exit; ++j) {
-
- while (process->childs.array[j] > 0 && lapsed < entry->timeout_exit) {
-
- // A hackish way to determine if the child process exists while waiting.
- if (getpgid(process->childs.array[j]) >= 0) {
- time.tv_sec = 0;
- time.tv_nsec = interval_nanoseconds;
-
- nanosleep(&time, 0);
-
- lapsed += interval_milliseconds;
- }
- else {
- process->childs.array[j] = 0;
-
- break;
- }
- } // while
- } // for
-
- for (j = 0; j < process->path_pids.used && lapsed < entry->timeout_exit; ++j) {
-
- if (process->path_pids.array[j].used && f_file_exists(process->path_pids.array[j], F_true) == F_true) {
- status = controller_file_pid_read(process->path_pids.array[j], &pid);
-
- if (pid) {
- while (lapsed < entry->timeout_exit) {
-
- // A hackish way to determine if the process exists while waiting.
- if (getpgid(pid) >= 0) {
- time.tv_sec = 0;
- time.tv_nsec = interval_nanoseconds;
-
- nanosleep(&time, 0);
-
- lapsed += interval_milliseconds;
- }
- else {
- process->path_pids.array[j].used = 0;
-
- break;
- }
- } // while
- }
- }
- } // for
- } // for
- }
-
- for (i = 0; i < global.thread->processs.size; ++i) {
-
- if (!global.thread->processs.array[i]) continue;
-
- process = global.thread->processs.array[i];
-
- // Do not kill exit processes, when not performing "execute" during exit.
- if (process->type == controller_data_type_exit_e && global.thread->enabled != controller_thread_enabled_exit_execute_e) continue;
-
- if (process->id_thread) {
- if (process->childs.used) {
- for (j = 0; j < process->childs.used; ++j) {
-
- if (process->childs.array[j] > 0) {
- f_signal_send(F_signal_kill, process->childs.array[j]);
-
- time.tv_sec = 0;
- time.tv_nsec = controller_thread_exit_process_cancel_wait_d;
-
- process->childs.array[j] = 0;
- }
- } // for
-
- nanosleep(&time, 0);
- }
-
- f_thread_join(process->id_thread, 0);
-
- process->id_thread = 0;
- }
-
- if (!(entry->flag & controller_entry_flag_timeout_exit_no_e)) {
- for (j = 0; j < process->childs.size; ++j) {
-
- // Do not kill exit processes, when not performing "execute" during exit.
- if (process->type == controller_data_type_exit_e && global.thread->enabled != controller_thread_enabled_exit_execute_e) continue;
-
- if (process->childs.array[j]) {
-
- // A hackish way to determine if the child process exists, and if it does then forcibly terminate it.
- if (getpgid(process->childs.array[j]) >= 0) {
- f_signal_send(F_signal_kill, process->childs.array[j]);
- }
-
- process->childs.array[j] = 0;
- }
- } // for
- }
-
- if (!(entry->flag & controller_entry_flag_timeout_exit_no_e)) {
- for (j = 0; j < process->path_pids.used; ++j) {
-
- // Do not kill exit processes, when not performing "execute" during exit.
- if (process->type == controller_data_type_exit_e && global.thread->enabled != controller_thread_enabled_exit_execute_e) continue;
-
- if (f_file_exists(process->path_pids.array[j], F_true) == F_true) {
- status = controller_file_pid_read(process->path_pids.array[j], &pid);
-
- if (pid) {
- f_signal_send(F_signal_kill, pid);
- }
-
- f_file_remove(process->path_pids.array[j]);
- process->path_pids.array[j].used = 0;
- }
- } // for
- }
-
- // Shrink the child pids as much as possible.
- while (process->childs.used) {
-
- // Do not shrink below an exit processes, when not performing "execute" during exit.
- if (process->type == controller_data_type_exit_e && global.thread->enabled != controller_thread_enabled_exit_execute_e) break;
- if (process->childs.array[j] > 0) break;
-
- --process->childs.used;
- } // while
-
- // Shrink the path pids as much as possible.
- while (process->path_pids.used) {
-
- // Do not shrink below an exit processes, when not performing "execute" during exit.
- if (process->type == controller_data_type_exit_e && global.thread->enabled != controller_thread_enabled_exit_execute_e) break;
- if (process->path_pids.array[j].used) break;
-
- --process->path_pids.used;
- } // while
- } // for
-
- f_thread_mutex_unlock(&global.thread->lock.cancel);
- }
-#endif // _di_controller_thread_process_cancel_
-
-#ifndef _di_controller_thread_process_exit_
- void controller_thread_process_exit(controller_global_t * const global) {
-
- if (global->thread->enabled != controller_thread_enabled_exit_e) {
- return;
- }
-
- if (global->setting->ready == controller_setting_ready_done_e) {
-
- // The exit processing runs using the entry thread.
- if (global->thread->id_entry) {
- f_thread_cancel(global->thread->id_entry);
- f_thread_join(global->thread->id_entry, 0);
-
- global->thread->id_entry = 0;
- }
-
- // Restart the signal thread to allow for signals while operating the Exit.
- if (!global->thread->id_signal) {
- f_thread_create(0, &global->thread->id_signal, &controller_thread_signal_other, (void *) global);
- }
-
- const controller_main_entry_t entry = macro_controller_main_entry_t_initialize_1(global, global->setting);
-
- f_status_t status = f_thread_create(0, &global->thread->id_entry, &controller_thread_exit, (void *) &entry);
-
- if (F_status_is_error(status)) {
- if (global->main->program.error.verbosity > f_console_verbosity_quiet_e) {
- controller_print_error(global->thread, &global->main->program.error, F_status_set_fine(status), "f_thread_create", F_true);
- }
-
- if (F_status_is_error_not(f_thread_mutex_lock(&global->thread->lock.alert))) {
- global->thread->enabled = controller_thread_enabled_not_e;
-
- f_thread_mutex_unlock(&global->thread->lock.alert);
- }
- else {
- global->thread->enabled = controller_thread_enabled_not_e;
- }
- }
- else {
- f_time_spec_t time;
-
- do {
- status = f_thread_mutex_lock(&global->thread->lock.alert);
-
- if (F_status_is_error(status)) {
- global->thread->enabled = controller_thread_enabled_not_e;
-
- break;
- }
-
- controller_time(controller_thread_exit_ready_timeout_seconds_d, controller_thread_exit_ready_timeout_nanoseconds_d, &time);
-
- status = f_thread_condition_wait_timed(&time, &global->thread->lock.alert_condition, &global->thread->lock.alert);
-
- f_thread_mutex_unlock(&global->thread->lock.alert);
-
- } while (F_status_is_error_not(status) && global->thread->enabled == controller_thread_enabled_exit_e);
-
- if (F_status_is_error(status)) {
- if (F_status_is_error_not(f_thread_mutex_lock(&global->thread->lock.alert))) {
- global->thread->enabled = controller_thread_enabled_not_e;
-
- f_thread_mutex_unlock(&global->thread->lock.alert);
- }
- else {
- global->thread->enabled = controller_thread_enabled_not_e;
- }
- }
- }
-
- // The sigtimedwait() function that is run inside of signal must be interrupted via the f_thread_cancel().
- if (global->thread->id_signal) {
- f_thread_cancel(global->thread->id_signal);
- f_thread_join(global->thread->id_signal, 0);
-
- global->thread->id_signal = 0;
- }
-
- controller_thread_process_cancel(*global, F_false, controller_thread_cancel_exit_e);
- }
- else {
- if (F_status_is_error_not(f_thread_mutex_lock(&global->thread->lock.alert))) {
- global->thread->enabled = controller_thread_enabled_not_e;
-
- f_thread_mutex_unlock(&global->thread->lock.alert);
- }
- else {
- global->thread->enabled = controller_thread_enabled_not_e;
- }
- }
- }
-#endif // _di_controller_thread_process_exit_
-
-#ifndef _di_controller_thread_process_normal_
- void * controller_thread_process_normal(void * const arguments) {
-
- f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
-
- controller_thread_process(F_true, (controller_data_t *) arguments);
-
- return 0;
- }
-#endif // _di_controller_thread_process_normal_
-
-#ifndef _di_controller_thread_process_other_
- void * controller_thread_process_other(void * const arguments) {
-
- f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
-
- controller_thread_process(F_false, (controller_data_t *) arguments);
-
- return 0;
- }
-#endif // _di_controller_thread_process_other_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_thread_process_h
-#define _PRIVATE_thread_process_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Asynchronously execute a Rule process.
- *
- * @param is_normal
- * If TRUE, then process as if this operates during a normal operation (entry and control).
- * If FALSE, then process as if this operates during a an exit operation.
- * @param process
- * The process data.
- *
- * @see controller_rule_process_do()
- */
-#ifndef _di_controller_thread_process_
- extern void controller_thread_process(const bool is_normal, controller_data_t * const process) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_process_
-
-/**
- * Cancel all process threads.
- *
- * @param global
- * The global thread data.
- * @param is_normal
- * If TRUE, then process as if this operates during a normal operation (entry and control).
- * If FALSE, then process as if this operates during a an exit operation.
- * @param by
- * Designate the way in which the cancellation should operate.
- *
- * If controller_thread_cancel_signal_e, then this was called from within the signal handling thread, so do not cancel the signal thread.
- * If controller_thread_cancel_call_e, then this was not called from within the signal handling thread, so cancel the signal thread.
- * If controller_thread_cancel_execute_e, then this was called from within the Entry/Exit for executing a process, so cancel the signal thread but not the Entry thread.
- */
-#ifndef _di_controller_thread_process_cancel_
- extern void controller_thread_process_cancel(const controller_global_t global, const bool is_normal, const uint8_t by) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_process_cancel_
-
-/**
- * Process the Exit file, if applicable.
- *
- * @param global
- * The global thread data.
- */
-#ifndef _di_controller_thread_process_exit_
- extern void controller_thread_process_exit(controller_global_t * const global) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_process_exit_
-
-/**
- * Asynchronously execute a Rule process during normal operations.
- *
- * @param arguments
- * The thread arguments.
- * Must be of type controller_data_t.
- *
- * @return
- * 0, always.
- *
- * @see controller_thread_process()
- */
-#ifndef _di_controller_thread_process_normal_
- extern void * controller_thread_process_normal(void * const arguments) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_process_normal_
-
-/**
- * Asynchronously execute a Rule process during other operations.
- *
- * @param arguments
- * The thread arguments.
- * Must be of type controller_data_t.
- *
- * @return
- * 0, always.
- *
- * @see controller_thread_process()
- */
-#ifndef _di_controller_thread_process_other_
- extern void * controller_thread_process_other(void * const arguments) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_process_other_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_thread_process_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "private-thread.h"
-#include "private-thread_rule.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_thread_rule_
- void * controller_thread_rule(void * const arguments) {
-
- f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
-
- const controller_global_t *global = (controller_global_t *) arguments;
-
- if (!controller_thread_is_enabled(F_true, global->thread)) return 0;
-
- return 0;
- }
-#endif // _di_controller_thread_rule_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_thread_rule_h
-#define _PRIVATE_thread_rule_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Thread for handling rule processing.
- *
- * This acts as the main rule thread after entry processing.
- * This runs all synchronous rules or spawns asynchronous rules.
- *
- * @todo the control thread should send commands to this thread, somehow.
- *
- * @param arguments
- * The thread arguments.
- * Must be of type controller_global_t.
- *
- * @return
- * 0, always.
- */
-#ifndef _di_controller_thread_rule_
- extern void * controller_thread_rule(void * const arguments) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_rule_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_thread_rule_h
+++ /dev/null
-#include "../controller.h"
-#include "../common/private-common.h"
-#include "../controller/private-controller.h"
-#include "private-thread.h"
-#include "private-thread_entry.h"
-#include "private-thread_process.h"
-#include "private-thread_signal.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _di_controller_thread_signal_
- void controller_thread_signal(controller_global_t * const global, const bool is_normal) {
-
- if (!controller_thread_is_enabled(is_normal, global->thread)) return;
-
- siginfo_t information;
- f_time_spec_t time;
- int error = 0;
-
- while (controller_thread_is_enabled(is_normal, global->thread)) {
-
- controller_time(controller_thread_exit_ready_timeout_seconds_d, controller_thread_exit_ready_timeout_nanoseconds_d, &time);
-
- error = sigtimedwait(&global->main->program.signal.set, &information, &time);
-
- if (error == -1) {
- if (errno == EAGAIN) continue;
- }
-
- if (global->setting->flag & controller_setting_flag_interruptible_e) {
- if (information.si_signo == F_signal_interrupt || information.si_signo == F_signal_abort || information.si_signo == F_signal_quit || information.si_signo == F_signal_termination) {
- global->thread->signal = information.si_signo;
-
- controller_thread_process_cancel(*global, is_normal, controller_thread_cancel_signal_e);
-
- break;
- }
- }
- } // while
- }
-#endif // _di_controller_thread_signal_
-
-#ifndef _di_controller_thread_signal_state_fss_
- void controller_thread_signal_state_fss(f_state_t * const state, void * const internal) {
-
- if (!state || !state->custom) return;
-
- controller_global_t * const global = (controller_global_t *) state->custom;
-
- /*if (!controller_thread_is_enabled(custom->is_normal, global->thread)) {
- global->main->program.signal_received = F_signal_abort;
- global->main->setting.state.status = F_status_set_error(F_interrupt);
- }
- else if (global->thread->signal == F_signal_interrupt || global->thread->signal == F_signal_abort || global->thread->signal == F_signal_quit || global->thread->signal == F_signal_termination) {
- global->main->program.signal_received = F_signal_abort;
- global->main->setting.state.status = F_status_set_error(F_interrupt);
- }*/
- }
-#endif // _di_controller_thread_signal_state_fss_
-
-#ifndef _di_controller_thread_signal_state_iki_
- void controller_thread_signal_state_iki(f_state_t * const state, void * const internal) {
-
- if (!state || !state->custom) return;
-
- controller_global_t * const global = (controller_global_t *) state->custom;
-
- /*if (!controller_thread_is_enabled(custom->is_normal, global->thread)) {
- global->main->program.signal_received = F_signal_abort;
- global->main->setting.state.status = F_status_set_error(F_interrupt);
- }
- else if (global->thread->signal == F_signal_interrupt || global->thread->signal == F_signal_abort || global->thread->signal == F_signal_quit || global->thread->signal == F_signal_termination) {
- global->main->program.signal_received = F_signal_abort;
- global->main->setting.state.status = F_status_set_error(F_interrupt);
- }*/
- }
-#endif // _di_controller_thread_signal_state_iki_
-
-#ifndef _di_controller_thread_signal_normal_
- void * controller_thread_signal_normal(void * const arguments) {
-
- f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
-
- controller_thread_signal((controller_global_t *) arguments, F_true);
-
- return 0;
- }
-#endif // _di_controller_thread_signal_normal_
-
-#ifndef _di_controller_thread_signal_other_
- void * controller_thread_signal_other(void * const arguments) {
-
- f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
-
- controller_thread_signal((controller_global_t *) arguments, F_false);
-
- return 0;
- }
-#endif // _di_controller_thread_signal_other_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+++ /dev/null
-/**
- * FLL - Level 3
- *
- * Project: Controller
- * API Version: 0.7
- * Licenses: lgpl-2.1-or-later
- */
-#ifndef _PRIVATE_thread_signal_h
-#define _PRIVATE_thread_signal_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Thread for handling signals/interrupts.
- *
- * @param global
- * The global data.
- * @param is_normal
- * If TRUE, then process as if this operates during a normal operation (entry and control).
- * If FALSE, then process as if this operates during a an exit operation.
- */
-#ifndef _di_controller_thread_signal_
- extern void controller_thread_signal(controller_global_t * const global, const bool is_normal) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_signal_
-
-/**
- * Callback passed to FSS functions for checking for interrupts.
- *
- * @param state
- * The f_state_t data.
- * @param internal
- * Not used.
- *
- * @return
- * F_interrupt_not if not interrupted.
- *
- * F_interrupt (with error bit) if interrupted.
- */
-#ifndef _di_controller_thread_signal_state_fss_
- extern void controller_thread_signal_state_fss(f_state_t * const state, void * const internal);
-#endif // _di_controller_thread_signal_state_fss_
-
-/**
- * Callback passed to IKI functions for checking for interrupts.
- *
- * @param state
- * The f_state_t data.
- * @param internal
- * Not used.
- *
- * @return
- * F_interrupt_not if not interrupted.
- *
- * F_interrupt (with error bit) if interrupted.
- */
-#ifndef _di_controller_thread_signal_state_iki_
- extern void controller_thread_signal_state_iki(f_state_t * const state, void * const internal);
-#endif // _di_controller_thread_signal_state_iki_
-
-/**
- * Thread for handling signals/interrupts during normal operations.
- *
- * Currently this only handles signals to exist, but may be updated to handle interrupt and hangup signals.
- *
- * @param arguments
- * The thread arguments.
- * Must be of type controller_global_t.
- *
- * @return
- * 0, always.
- *
- * @see controller_thread_signal()
- */
-#ifndef _di_controller_thread_signal_normal_
- extern void * controller_thread_signal_normal(void * const arguments) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_signal_normal_
-
-/**
- * Thread for handling signals/interrupts during other operations.
- *
- * Currently this only handles signals to exist, but may be updated to handle interrupt and hangup signals.
- *
- * @param arguments
- * The thread arguments.
- * Must be of type controller_global_t.
- *
- * @return
- * 0, always.
- *
- * @see controller_thread_signal()
- */
-#ifndef _di_controller_thread_signal_other_
- extern void * controller_thread_signal_other(void * const arguments) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_signal_other_
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // _PRIVATE_thread_signal_h
+++ /dev/null
-# fss-0000
-
-_di_libcap_ Disable libcap support, allow for compiling and linking without libcap (-lcap).
-_di_thread_support_ Disables thread support.
-
-_libcap_legacy_only_ Disable functionality provided by later versions of libcap (2.43 and later).
-_controller_as_init_ Build the program to run as if it were "init" by default, including displaying the program name as "Init Program" or "Init". This changes the main.c file only, leaving the library shareable between both "controller" and "init".
-_override_controller_default_engine_ Provide a custom scripting engine name string to execute (such as php).
-_override_controller_default_engine_length_ The number of bytes representing the string in _override_controller_default_engine_ (not including the terminating NULL).
-_override_controller_path_pid_ Use this as the default custom directory path representing the location of the controller program pid.
-_override_controller_path_pid_init_ Provide a custom init path for the pid file rather than the default.
-_override_controller_path_pid_init_length_ The number of bytes representing the string in _override_controller_path_pid_init_ (not including the terminating NULL).
-_override_controller_path_pid_length_ The number of bytes representing the string in _override_controller_path_pid_ (not including the terminating NULL).
-_override_controller_path_pid_prefix_ Use this as the default custom prefix prepended to the file name of the file representing the controller program pid.
-_override_controller_path_pid_prefix_length_ The number of bytes representing the string in _override_controller_path_pid_prefix_ (not including the terminating NULL).
-_override_controller_path_pid_suffix_ Use this as the default custom prefix prepended to the file name of the file representing the controller program pid.
-_override_controller_path_pid_suffix_length_ The number of bytes representing the string in _override_controller_path_pid_suffix_ (not including the terminating NULL).
-_override_controller_path_settings_init_ Provide a custom init path for the settings file rather than the default.
-_override_controller_path_settings_init_length_ The number of bytes representing the string in _override_controller_path_settings_init_ (not including the terminating NULL).
-_override_controller_path_socket_ Use this as the default custom directory path representing the location of the controller program socket.
-_override_controller_path_socket_init_ Provide a custom init path for the socket file rather than the default.
-_override_controller_path_socket_init_length_ The number of bytes representing the string in _override_controller_path_socket_init_ (not including the terminating NULL).
-_override_controller_path_socket_length_ The number of bytes representing the string in _override_controller_path_socket_ (not including the terminating NULL).
-_override_controller_path_socket_prefix_ Use this as the default custom prefix prepended to the file name of the file representing the controller program socket.
-_override_controller_path_socket_prefix_length_ The number of bytes representing the string in _override_controller_path_socket_prefix_ (not including the terminating NULL).
-_override_controller_path_socket_suffix_ Use this as the default custom prefix prepended to the file name of the file representing the controller program socket.
-_override_controller_path_socket_suffix_length_ The number of bytes representing the string in _override_controller_path_socket_suffix_ (not including the terminating NULL).
-
-_pthread_attr_unsupported_ Disable non-portable functionality associated with pthread_attr.
-_pthread_sigqueue_unsupported_ Disable GNU specific sigqueue().
+++ /dev/null
-# fss-0000
-
-f_type
-f_status
-f_memory
-f_type_array
-f_string
-f_utf
-f_account
-f_capability
-f_color
-f_compare
-f_console
-f_control_group
-f_conversion
-f_directory
-f_environment
-f_execute
-f_file
-f_fss
-f_iki
-f_limit
-f_parse
-f_path
-f_pipe
-f_print
-f_rip
-f_signal
-f_socket
-f_status_string
-f_thread
-
-fl_control_group
-fl_conversion
-fl_directory
-fl_environment
-fl_fss
-fl_iki
-fl_path
-fl_print
-
-fll_control_group
-fll_error
-fll_execute
-fll_fss
-fll_print
-fll_program
-fll_status_string
+++ /dev/null
-# fss-0005 iki-0002
-
-settings:
- fail exit
- modes individual individual_thread level monolithic clang test fanalyzer coverage thread threadlesss
-
- environment PATH LD_LIBRARY_PATH
- environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LOCPATH NLSPATH
-
-main:
- build
-
-install:
- shell ./install.sh parameter:'work' parameter:'verbosity' parameter:'color'
-
-help:
- print
- print context:'title'Fakefile Options for Controller Program.context:'reset'
-
- print
- print The following operations are available\:
- print " - context:'notable'help:context:'reset' Perform the help operation, printing this message."
- print " - context:'notable'install:context:'reset' A helper operation that simply calls the ./install.sh script with default settings."
- print " - context:'notable'main:context:'reset' The default compilation using the build settings mode."
-
- print
- print The context:'notable'install context:'reset'operation supports the context:'notable'work,context:'reset' context:'notable'verbosity,context:'reset' and context:'notable'color context:'reset'parameters.
+++ /dev/null
-# fss-0001
-#
-# Modes:
-# - individual: Compile using per project (individual) libraries, does not handle thread or threadless cases.
-# - individual_thread: This is required when compiling in individual mode with "thread" mode.
-# - level: Compile using per level libraries.
-# - monolithic: Compile using per monolithic libraries.
-# - clang: Use clang rather than the default, which is generally gcc.
-# - gcc: Use gcc specific settings.
-# - test: Compile for a test, such as unit testing.
-# - fanalyzer: Compile using GCC's -fanalyzer compile time option.
-# - coverage: Compile for building coverage.
-# - thread: Compile with thread support.
-# - threadless: Compile without thread support.
-#
-
-build_name controller
-
-version_major 0
-version_minor 7
-version_micro 0
-version_file micro
-version_target minor
-
-modes individual individual_thread level monolithic clang gcc test fanalyzer coverage thread threadless as_init
-modes_default monolithic thread gcc
-
-build_compiler gcc
-build_compiler-clang clang
-build_indexer ar
-build_indexer_arguments rcs
-build_language c
-
-build_libraries -lc -lcap
-build_libraries-individual -lfll_control_group -lfll_error -lfll_execute -lfll_fss -lfll_print -lfll_program -lfll_status_string
-build_libraries-individual_thread -lf_thread
-build_libraries-individual -lfl_control_group -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_iki -lfl_path -lfl_print
-build_libraries-individual -lf_account -lf_capability -lf_color -lf_compare -lf_console -lf_control_group -lf_conversion -lf_directory -lf_environment -lf_execute -lf_file -lf_fss -lf_iki -lf_limit -lf_memory -lf_parse -lf_path -lf_pipe -lf_print -lf_rip -lf_signal -lf_socket -lf_status_string -lf_string -lf_type_array -lf_utf
-build_libraries-individual_thread -lf_thread
-build_libraries-level -lfll_2 -lfll_1 -lfll_0
-build_libraries-monolithic -lfll
-
-build_sources_library controller.c common.c print.c
-build_sources_library common/private-common.c common/private-cache.c common/private-control.c common/private-entry.c common/private-lock.c common/private-process.c common/private-rule.c common/private-setting.c common/private-thread.c
-build_sources_library control/private-control.c control/private-control_print.c
-build_sources_library controller/private-controller.c controller/private-controller_print.c
-build_sources_library entry/private-entry.c entry/private-entry_print.c
-build_sources_library rule/private-rule.c rule/private-rule_print.c
-build_sources_library process/private-process.c
-build_sources_library lock/private-lock.c lock/private-lock_print.c
-build_sources_library thread/private-thread.c thread/private-thread_control.c thread/private-thread_entry.c thread/private-thread_process.c thread/private-thread_rule.c thread/private-thread_signal.c
-
-build_sources_program main.c main-common.c
-
-build_sources_headers controller.h common.h print.h
-
-build_sources_documentation man
-
-build_sources_setting controller
-
-build_script yes
-build_shared yes
-build_static no
-
-path_headers program/controller
-path_library_script script
-path_library_shared shared
-path_library_static static
-path_object_script script
-path_object_shared shared
-path_object_static static
-path_program_script script
-path_program_shared shared
-path_program_static static
-
-has_path_standard yes
-preserve_path_headers yes
-
-search_exclusive yes
-search_shared yes
-search_static yes
-
-environment PATH LD_LIBRARY_PATH
-environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LOCPATH NLSPATH
-
-#defines -D_di_libcap_
-defines -D_libcap_legacy_only_
-defines-as_init -D_controller_as_init_
-defines-thread -D_pthread_attr_unsupported_ -D_pthread_sigqueue_unsupported_
-defines-threadless -D_di_thread_support_
-
-flags -O2 -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses -Wno-missing-braces
-flags -fstack-clash-protection -fno-delete-null-pointer-checks
-flags -Wl,-z,nodlopen -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now
-flags-clang -Wno-logical-op-parentheses
-flags-coverage -O0 --coverage -fprofile-abs-path -fprofile-dir=build/coverage/
-flags-fanalyzer -fanalyzer
-flags-gcc_13 -fstrict-flex-arrays=3
-flags-test -O0 -fstack-protector-strong -Wall
-flags-thread -pthread
-
-flags_library -fPIC
-flags_object -fPIC
-flags_program -fPIE
+++ /dev/null
-.TH CONTROLLER "1" "January 2023" "FLL - Controller 0.7.0" "User Commands"
-.SH NAME
-controller \- Perform a series of operations in a manner similar to that of an init program.
-.SH SYNOPSIS
-.B controller
-[\fI\,OPTIONS\/\fR] [\fI\,ENTRY\/\fR]
-.SH DESCRIPTION
-.PP
-This program performs a series of operations described by an \fBentry\fR file.
-This includes error handling.
-
-The \fBentry\fR file consists of several rules defined in individual \fBrule\fR files.
-Thee \fBrule\fR file allows for both programs and scripts to be executed.
-Any scripting language whose program supports piping commands to it are effectively supported scripting languages.
-
-Upon completion, this program may optionally process an \fBexit\fR file whose name is identical to the \fBentry\fR used.
-
-When both the \fB\-\-simulate\fR parameter and the \fB\-\-validate\fR parameter are specified, then additional information on each would be executed rule is printed but no simulation is performed.
-
-The default interrupt behavior is to operate as if the \fB\-\-interruptible\fR parameter is passed.
-
-Specify an empty string for the \fB\-\-pid\fR parameter to disable pid file creation for this program.
-.SH OPTIONS
-.TP
-\fB\{\-h, \-\-help\fR
-Print the help message.
-.TP
-\fB+C, ++copyright\fR
-Print the copyright.
-.TP
-\fB+d, ++dark\fR
-Output using colors that show up better on dark backgrounds.
-.TP
-\fB+l, ++light\fR
-Output using colors that show up better on light backgrounds.
-.TP
-\fB+n, ++no_color\fR
-Do not print using color.
-.TP
-\fB+Q, ++quiet\fR
-Decrease verbosity, silencing most output.
-.TP
-\fB+E, ++error\fR
-Decrease verbosity, using only error output.
-.TP
-\fB+N, ++normal\fR
-Set verbosity to normal.
-.TP
-\fB+V, ++verbose\fR
-Increase verbosity beyond normal output.
-.TP
-\fB+D, ++debug\fR
-Enable debugging, significantly increasing verbosity beyond normal output.
-.TP
-\fB+v, ++version\fR
-Print only the version number.
-.TP
-\fB\-c, \-\-cgroup\fR
-Specify a custom control group file path, such as '/sys/fs/cgroup/'.
-.TP
-\fB\-d, \-\-daemon\fR
-Run in daemon only mode (do not process the entry).
-.TP
-\fB\-I, \-\-init\fR
-The program will run as an init replacement.
-.TP
-\fB\-i, \-\-interruptible\fR
-Designate that this program can be interrupted by a signal.
-.TP
-\fB\-p, \-\-pid\fR
-Specify a custom pid file path, such as 'controller/run/default.pid'.
-.TP
-\fB\-s, \-\-settings\fR
-Specify a custom settings path, such as 'controller/'.
-.TP
-\fB\-S, \-\-simulate\fR
-Run as a simulation.
-.TP
-\fB\-k, \-\-socket\fR
-Specify a custom socket file path, such as 'controller/run/default.socket'.
-.TP
-\fB\-U, \-\-uninterruptible\fR
-Designate that this program cannot be interrupted by a signal.
-.TP
-\fB\-v, \-\-validate\fR
-Validate the settings (entry and rules) without running (does not simulate).
-.SH ENTRY
-.TP
-The name of an \fBentry\fR.
-.SH SEE ALSO
-.PP
-\fBcontrol\fR(1),
-\fBcontroller\-actions\fR(5),
-\fBcontroller\-entry\fR(5),
-\fBcontroller\-exit\fR(5),
-\fBcontroller\-packet\fR(5),
-\fBcontroller\-rule\fR(5)
-.SH AUTHOR
-Written by Kevin Day.
-.SH COPYRIGHT
-.PP
-Copyright \(co 2007-2024 Kevin Day, GNU LGPL Version 2.1 or later.
+++ /dev/null
-.TH controller-rule "5" "January 2023" "Controller 0.7.0" "File Formats"
-.SH NAME
-Controller \- "rule" file.
-.SH SYNOPSIS
-.B rule
-.SH DESCRIPTION
-.PP
-This describes the intent and purpose of the actions provided for individual Rules (or things related to a Rule).
-
-Each Action represents a specific intent and purpose but many of these actions are customizable via the rule file.
-One should expect an Action to operate as described here but the system administrator or distributor is fully capable of doing something different.
-For those doing something different, appropriate documentation is suggested.
-
-These actions should be usable by any \fBcontrol\fR program that communicates with this \fBcontroller\fR program.
-Should any \fBcontrol\fR or \fBcontroller\fR program implementation not support any particular Action for any reason, one should report that the Action is unsupported.
-
-\- \fBFreeze Action\fR:
- The Freeze Action is an extension of a Control Group.
- This is internal to the \fBcontroller\fR program and is not customizable via any Rule file.
- For a customizable \fBfreeze\fR\-like capability, look into the Pause and Resume Actions.
- This is the complement of the Thaw Action.
-
- This designates that a processes Control Group is to be frozen.
- All Rules (or any process not controlled by the \fBcontroller\fR) that is within the same Control Group will be frozen.
- (@todo consider instead designing this around the Control Groups instead of a \fBrule\fR.)
- (This documentation will likely change with consideration to the above @todo once this gets implemented.)
-
- This must not attempt to freeze (or unfreeze) the Control Group that the \fBcontroller\fR belongs to.
- Therefore, if a Rule does not specify a Control Group, then it is likely that the Freeze Action will be unsupported for that Rule/Control Group.
-
-\- \fBKill Action\fR:
- Forcefully terminate some process controlled by the \fBcontroller\fR.
- This action cannot be blocked and it is recommended to use a Stop Action instead for a more proper termination.
-
-\- \fBPause Action\fR:
- The Pause Action will pause (or freeze) the process controlled by the Rule.
- Although similar to the Freeze Action, this is intended to communicate to an individual process and inform to Pause.
- This is complemented by the Resume Action.
-
-\- \fBRestart Action\fR:
- The Restart Action will either perform a Stop Action and then a Restart Action or it will perform the Restart Action designated in some Rule file.
- Ideally this should inform some process to perform its own restart routines.
-
-\- \fBResume Action\fR:
- The Resume Action will unpause (or unfreeze) the process controlled by the Rule.
- Although similar to the Thaw Action, this is intended to communicate to an individual process and inform to Resume.
- This is complemented by the Pause Action.
-
-\- \fBReload Action\fR:
- The Reload Action will perform the Reload Action designated in some Rule file.
- Ideally this should inform some process to perform its own reload routines.
- Many programs often differentiate the concept \fBreload\fR from the concept "restart" in that the program remains running during a \fBreload\fR.
-
-\- \fBStart Action\fR:
- The Start Action will perform the Start Action designated in some Rule file.
- This action should be used to start some program or script.
- This is the action called by Entry file.
- This is complemented by the Stop Action.
-
-\- \fBStop Action\fR:
- The Stop Action will perform the Stop Action designated in some Rule file.
- This action should be used to stop some program or script.
- This is the action called for all running controlled processes on shutdown.
- This is complemented by the Start Action.
-
-\- \fBThaw Action\fR:
- The Thaw Action is an extension of a Control Group.
- This is internal to the \fBcontroller\fR program and is not customizable via any Rule file.
- For a customizable \fBthaw\fR\-like capability, look into the \fBpause\fR and \fBresume\fR Actions.
- This is complemented by the Freeze Action.
-
- This designates that a processes Control Group is to be unfrozen.
- All Rules (or any process not controlled by the \fBcontroller\fR) that is within the same Control Group will be unfrozen.
-
- This must not attempt to thaw (or unthaw) the Control Group that the \fBcontroller\fR belongs to.
- Therefore, if a Rule does not specify a Control Group, then it is likely that the Thaw Action will be unsupported for that Rule/Control Group.
-.SH SEE ALSO
-.PP
-\fBcontrol\fR(1),
-\fBcontroller\fR(1),
-\fBcontroller\-entry\fR(5),
-\fBcontroller\-exit\fR(5),
-\fBcontroller\-packet\fR(5),
-\fBcontroller\-rule\fR(5)
-.SH AUTHOR
-Written by Kevin Day.
-.SH COPYRIGHT
-.PP
-Copyright \(co 2007-2024 Kevin Day, Open Standard License 1.0 or later.
+++ /dev/null
-.TH controller-entry "5" "January 2023" "Controller 0.7.0" "File Formats"
-.SH NAME
-Controller \- "entry" file.
-.SH SYNOPSIS
-.B entry
-.SH DESCRIPTION
-.PP
-This describes the intent and purpose of an Entry file.
-
-An Entry file, such as \fBdefault.entry\fR, is intended to store a set of rules in which the controller will process on execution.
-These are used to run some set of commands, such as booting a system.
-
-The \fBmain\fR Item Object is always executed first (Therefore \fBmain\fR is both reserved and required).
-All other Basic List Objects are not executed unless either an \fBitem\fR or a \fBfailsafe\fR specifies a valid Item name.
-Execution of all Items is top\-down.
-
-\- The \fBsettings\fR item Object:
- Represents Entry settings and is not an \fBitem\fR that can be executed.
- A number of settings are supported, but if this Item Object is not specified, then defaults are used.
- The following settings are available: \fBcontrol\fR, \fBcontrol_group\fR, \fBcontrol_mode\fR, \fBcontrol_user\fR, \fBdefine\fR, \fBmode\fR, \fBparameter\fR, \fBpid\fR, \fBpid_file\fR, \fBsession\fR, \fBshow\fR.
-
- \- The \fBcontrol\fR setting:
- Represents the path to the socket file in which the Controller uses to communicate over with clients such as a Control program.
- A relative path is relative to the Controller PID directory.
- An absolute path is treated exactly as the path given.
- If no socket setting is specified, then no socket will be made available.
- This socket file is only created once \fBready\fR mode is achieved.
-
- Providing \fBreadonly\fR after the socket path instructs the Controller program not to create or delete the Socket file because the file system is assumed to be readonly.
- The socket file itself must therefore already exist.
- This should be possible in the cases of file systems that have pre\-created a socket file at the designated path.
- When \fBreadonly\fR, the group, mode, and user are also not processed effectively resulting in the \fBcontrol_group\fR, \fBcontrol_mode\fR, and \fBcontrol_user\fR settings being ignored.
-
- Future versions might expand this into supporting network addresses in addition to socket files.
-
- \- The \fBcontrol_group\fR setting:
- Represents the group name or group ID to assign to the socket file as the group.
-
- \- The \fBcontrol_mode\fR setting:
- Represents the file mode assigned to the socket file.
- This could either be the string version that might look like \fBu+rw\-x,g+r\-wx,o\-rwx\fR or a numeric value like \fB0750\fR.
-
- \- The \fBcontrol_user\fR setting:
- Represents the user name or user ID to assign to the socket file as the owner.
-
- \- The \fBdefine\fR setting:
- Use this to define an environment variable (this overwrites any existing environment variable with this name).
- A define is both exported as an environment variable as well as exposed as an IKI variable.
- Example IKI variable substitution: for \fBdefine PATH /bin:/sbin\fR, the associated IKI variable would look like: PATH.
-
- All environment variables, including those defined using this, must be in the \fBenvironment\fR list in any given Rule to be exported to the executed process.
- Environment variables added here that are not added to the environment are still exposed as an IKI variable.
-
- This is only expanded within any Rule operated on by this Entry.
-
- \- The \fBmode\fR setting:
- Represents the mode in which the Entry is operating in.
- The following modes are supported: \fBhelper\fR, \fBprogram\fR, and \fBservice\fR.
-
- - The \fBhelper\fR mode:
- Designates that the Entry operates as a helper for starting programs or performing actions and exits when complete.
- On exit, any background (asynchronous) processes are not cancelled.
- If terminated, the foreground (synchronous) process is cancelled.
- Will call the \fBexit\fR with the same name as this Entry, but with the extension \fBexit\fR, such as \fBdefault.exit\fR.
- Supports the Item Action \fBexecute\fR to execute a program (switching the \fBcontroller\fR program entirely with the executed process).
-
- \- The \fBprogram\fR mode:
- Designates that the Entry operates as a program and exits when complete.
- On exit, any background (asynchronous) processes are also cancelled.
- If terminated, the foreground (synchronous) process is cancelled.
- Will call the \fBexit\fR with the same name as this Entry, but with the extension \fBexit\fR, such as \fBdefault.exit\fR.
- Supports the Item Action \fBexecute\fR to execute a program (switching the \fBcontroller\fR program entirely with the executed process).
-
- \- The \fBservice\fR mode:
- Designates that the Entry operates as a service and will sit and wait for control commands when complete.
- Will call the \fBexit\fR with the same name as this Entry, but with the extension \fBexit\fR, such as \fBdefault.exit\fR.
- Does not support the Item Action \fBexecute\fR.
- This is the default mode.
-
- \- The \fBparameter\fR setting:
- Use this to define an IKI variable name and value.
- These do not conflict with environment variables and are not exposed as environment variables.
- Example IKI variable substitution: for \fBparameter hello world\fR, the associated IKI variable would look like: hello.
-
- This is only expanded within any Rule operated on by this Entry.
-
- \- The \fBpid\fR setting:
- Represents how the Entry PID file is generated or not.
- The following modes are supported: \fBdisable\fR, \fBrequire\fR, and \fBready\fR.
- For \fBdisable\fR, not PID file representing the Entry is created.
- For \fBrequire\fR, check to see if the PID file exists for an Entry at startup and then when \fBready\fR create a PID file, display error on PID file already exists or on failure and then fail.
- For \fBready\fR, when \fBready\fR create a PID file, display error on failure and then fail (does not check if PID file exists).
-
- \- The \fBpid_file\fR setting:
- When \fBpid\fR is not disabled this represents the path to the PID file.
- If \fB\-p\fR or \fB\-\-pid\fR is passed to the controller program, then this value is ignored in favor of the value passed along the command line.
-
- \- The \fBsession\fR setting:
- Represents the default way in which child processes are executed.
- This default can be overridden by individual Rules.
- For \fBnew\fR, Execute Rule processes in a new session setting the process group to the executed process' id (making the executed process a \fBcontrolling terminal\fR).
- For \fBsame\fR, Execute Rule processes in the same session where the process group is set to the parent process id.
-
- \- The \fBshow\fR setting:
- Represents the way Entry processing presents information to the screen.
- This applies only to the Entry and Rule processing itself and does not handle the output of programs and scripts being executed by some Entry or Rule.
- The following show options are supported: \fBnormal\fR and \fBinit\fR.
- For \fBnormal\fR, will not report the start or stop of some Entry or Rule execution but will report any errors or warnings as appropriate.
- For \fBinit\fR, will report when starting programs and may include reporting success and failure status.
-
- \- The \fBtimeout\fR setting:
- Represents the default timeouts for the Entry.
- See the \fBtimeout\fR Action below for details.
-
-\- The \fBmain\fR item Object:
- Each \fBitem\fR supports the following Action Names: \fBconsider\fR, \fBexecute\fR, \fBfailsafe\fR, \fBfreeze\fR, \fBitem\fR, \fBkill\fR, \fBpause\fR, \fBreload\fR, \fBrestart\fR, \fBready\fR, \fBresume\fR, \fBstart\fR, \fBstop\fR, and \fBtimeout\fR.
- Of those types, the following are considered a \fBrule\fR Action: \fBfreeze\fR, \fBkill\fR, \fBpause\fR, \fBreload\fR, \fBrestart\fR, \fBresume\fR, \fBstart\fR, \fBstop\fR, and \fBthaw\fR.
-
- \- The \fBconsider\fR Item Action:
- A special case of a \fBrule\fR Action.
- All Action Parameters are the same as with the \fBrule\fR Action Parameters.
- The difference is that \fBconsider\fR is only processed (instead of being processed and executed) and when some \fBrule\fR Action designates that this consideration is required (via \fBneed\fR), wanted (via \fBwant\fR), or wished for (via \fBwish\fR) from the within the Rule file.
- If this is determined to be executed, then this is immediately executed when needed, wanted or wished for and applies all properties as appropriate (such as \fBasynchronous\fR, for example).
- If this is determined not to be executed, then this \fBconsider\fR is ignored as if it was never there in the first place.
-
- \- The \fBexecute\fR Item Action:
- Execute into the specified program.
- On successful execution, the controller program will no longer be running and will be replaced with the designated program.
- This Item Action is only supported when operating in \fBprogram\fR mode.
-
- \- The \fBfailsafe\fR Item Action:
- Accepts only a valid Item Name in which will be executed when a failure is detected.
- Only a single \fBfailsafe\fR Item Action may function at a time.
- Each successive \fBfailsafe\fR Item Action specified replaces the previously defined \fBfailsafe\fR Item Action (in a top\-down manner).
- When operating in \fBfailsafe\fR, the \fBrequire\fR Item Action is ignored (given that it is meaningless once operating in \fBfailsafe\fR mode).
-
- \- The \fBfreeze\fR Item Action:
- A \fBrule\fR Action for freezing some Control Group.
- This Item Action will process the \fBfreeze\fR inner Content of the named Rule.
- This is specific to Control Groups and is not yet fully implemented.
- Once implemented this documentation will need to be updated and clarified.
-
- \- The \fBitem\fR Item Action:
- Accepts only a valid Item Name in which will be immediately executed.
- Any valid Item Name, except for the reserved \fBmain\fR, may be used.
-
- \- The \fBkill\fR Item Action:
- A \fBrule\fR Action for forcibly terminating some process.
- This Item Action will process the \fBkill\fR inner Content of the named Rule.
-
- \- The \fBpause\fR Item Action:
- A \fBrule\fR Action for pausing some process.
- This Item Action will process the \fBpause\fR inner Content of the named Rule.
-
- \- The \fBreload\fR Item Action:
- A \fBrule\fR Action for pausing some process.
- This Item Action will process the \fBreload\fR inner Content of the named Rule.
-
- \- The \fBrestart\fR Item Action:
- A \fBrule\fR Action for pausing some process.
- This Item Action will process the \fBrestart\fR inner Content of the named Rule.
-
- \- The \fBresume\fR Item Action:
- A \fBrule\fR Action for pausing some process.
- This Item Action will process the \fBresume\fR inner Content of the named Rule.
-
- \- The \fBready\fR Item Action:
- Instructs the controller program when it is safe to perform normal tasks, such as creating the PID file.
- When not specified, the state is always assumed to be ready.
- For example, the controller program may be used as a full blown \fBinit\fR replacement and therefore may need to mount the /var/run/ directory.
- If the PID file is created at program start, then the /var/run/controller.pid would be written before the /var/run/ directory is ready.
- This could be a problem, such as on a read\-only file system the PID creation fails and controller bails out on error.
- Adding \fBready\fR essentially specifies a point in time in the Entry in which things are expected to be safe for such basic operations.
- When the optional \fBwait\fR is provided, then \fBready\fR will wait for all currently started asynchronous processes to complete before operating.
-
- \- The \fBstart\fR Item Action:
- A \fBrule\fR Action for pausing some process.
- This Item Action will process the \fBstart\fR inner Content of the named Rule.
-
- \- The \fBstop\fR Item Action:
- A \fBrule\fR Action for pausing some process.
- This Item Action will process the \fBstop\fR inner Content of the named Rule.
-
- \- The \fBthaw\fR Item Action:
- A \fBrule\fR Action for unfreezing some Control Group.
- This Item Action will process the \fBthaw\fR inner Content of the named Rule.
- This is specific to Control Groups and is not yet fully implemented.
- Once implemented this documentation will need to be updated and clarified.
-
- \- The \fBtimeout\fR Item Action:
- (This is not currently fully implemented, only \fBexit\fR is implemented.)
- Provides default global settings for each of the four special situations: \fBexit\fR, \fBkill\fR, \fBstart\fR, and \fBstop\fR.
- Each of these may only have a single one exist at a time (one \fBexit\fR, one \fBkill\fR, one \fBstart\fR, and one \fBstop\fR).
- Each successive \fBtimeout\fR Item Action, specific to each Action Name (such as \fBstart\fR), specified replaces the previously defined \fBtimeout\fR Action (in a top\-down manner).
- The second Content for each of these, when specified, may be a 0 or greater whole number representing the number of MegaTime (MT) (equivalent to milliseconds).
- For \fBkill\fR, this represents the number of MegaTime to wait after stopping some Rule and that Rule has not yet stopped to forcefully stop the Rule (aka kill the Rule).
- For \fBstart\fR, this represents the number of MegaTime to wait after starting some Rule before assuming something went wrong and the Rule is returned as failed.
- For \fBstop\fR, this represents the number of MegaTime to wait after stopping some Rule before assuming something went wrong and the Rule is returned as failed.
- If the second Content is not specified, then this disables the type (prevents the specified timeout action).
- For \fBexit\fR, this represents the number of MegaTime to wait when the Controller program is exiting (such as having received a terminate signal).
- In this case, a terminate signal is sent to all child processes.
- The \fBexit\fR timeout represents the amount of time to wait after sending the terminate signal before sending a kill signal to each child process still running.
- When disabled, the program will not send a kill signal will continue running until all child processes to terminate.
- The \fBexit\fR timeout does not get applied to any Rule.
-.SH SPECIFICATION
-.PP
-The Entry files follow the \fBFSS\-0005 (Somewhat Basic List)\fR format.
-
-An Entry file name is expected to have the file extension \fB.entry\fR.
-
-For each Entry file:
- \- The outer most part is a \fBFSS\-0002 (Basic List)\fR.
- \- The Basic List Object is considered the \fBItem\fR.
- \- The Basic List Content are considered the \fBActions\fR.
- \- The \fBActions\fR are \fBFSS\-0001 (Extended)\fR.
- \- Each Action Object is the \fBAction Name\fR.
- \- Each Action Content are the \fBAction Parameters\fR.
-
-The Items:
- \- \fBmain\fR: required.
-
- \- \fBsettings\fR: optional, Actions may be one of:
- \- \fBcontrol\fR: One to two Content.
- The first Content is a relative or absolute path to a socket file.
- The second Content an optional \fBreadonly\fR.
- \- \fBcontrol_group\fR: Exactly one Content that is a group name or group id.
- \- \fBcontrol_mode\fR: Exactly one Content that is a valid file mode.
- \- \fBcontrol_user\fR: Exactly one Content that is a user name or user id.
- \- \fBdefine\fR: Two Content, the first Content must be a case\-sensitive valid environment variable name (alpha\-numeric or underscore, but no leading digits).
- \- \fBmode\fR: Exactly one Content that is one of \fBprogram\fR or \fBservice\fR.
- \- \fBparameter\fR: Two Content, the first Content must be a case\-sensitive valid IKI name and the second being an IKI value.
- \- \fBpid\fR: Exactly one Content that is one of \fBdisable\fR, \fBrequire\fR, or \fBready\fR.
- \- \fBpid_file\fR: Exactly one Content that is a relative or absolute path to a pid file.
- \- \fBsession\fR: Exactly one Content that is one of \fBnew\fR or \fBsame\fR.
- \- \fBshow\fR: Exactly one Content that is one of \fBnormal\fR or \fBinit\fR.
- \- \fBtimeout\fR: One or two content with the first being one of \fBexit\fR, \fBstart\fR, \fBstop\fR, or \fBkill\fR and the (optional) second Content being a positive whole number or 0.
-
- The Entry file may have any other valid Item Objects, but only the above are reserved.
-
- The Actions:
- \- \fBconsider\fR: One or more Content.
- The first Content is the relative file path (without any leading/trailing slashes and without file extension).
- The second Content is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBexecute\fR: One or more Content.
- The first Content is the program name or full path to the program (the program may be a script).
- All remaining Content are passed as parameters to the program being executed.
-
- \- \fBfailsafe\fR: One Content that is a valid Object name, except for the reserved \fBmain\fR.
-
- \- \fBfreeze\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBitem\fR: One Content that is a valid Object name, except for the reserved \fBmain\fR.
-
- \- \fBkill\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBpause\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBready\fR: Zero or One Content.
- The first may only be one of:
- \- \fBwait\fR
-
- \- \fBreload\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBrestart\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBresume\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBstart\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBstop\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBthaw\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBtimeout\fR: One or two Content.
- The first being one of:
- \- \fBexit\fR
- \- \fBstart\fR
- \- \fBstop\fR
- \- \fBkill\fR
- The (optional) second Content being a positive whole number or 0.
-.SH SEE ALSO
-.PP
-\fBcontrol\fR(1),
-\fBcontroller\fR(1),
-\fBcontroller\-actions\fR(5),
-\fBcontroller\-exit\fR(5),
-\fBcontroller\-packet\fR(5),
-\fBcontroller\-rule\fR(5)
-.SH AUTHOR
-Written by Kevin Day.
-.SH COPYRIGHT
-.PP
-Copyright \(co 2007-2024 Kevin Day, Open Standard License 1.0 or later.
+++ /dev/null
-.TH controller-rule "5" "January 2023" "Controller 0.7.0" "File Formats"
-.SH NAME
-Controller \- "rule" file.
-.SH SYNOPSIS
-.B rule
-.SH DESCRIPTION
-.PP
-This describes the intent and purpose of an Exit file.
-
-An Exit file, such as \fBdefault.exit\fR, is intended to store a set of rules in which the controller will process on execution.
-These are used to run some set of commands, such as shutting down a system.
-
-An Exit is a special variation or subset of an Entry.
-
-\- The \fBsettings\fR Item Object:
- Represents Exit settings and is not an \fBitem\fR that can be executed.
- A number of settings are supported, but if this Item Object is not specified, then defaults are used.
- The following settings are available: \fBpid\fR and \fBshow\fR.
-
- \- The \fBdefine\fR setting:
- Use this to define an environment variable (this overwrites any existing environment variable with this name).
- A define is both exported as an environment variable as well as exposed as an IKI variable.
- Example IKI variable substitution: for \fBdefine PATH /bin:/sbin\fR, the associated IKI variable would look like: PATH.
-
- All environment variables, including those defined using this, must be in the \fBenvironment\fR list in any given Rule to be exported to the executed process.
- Environment variables added here that are not added to the environment are still exposed as an IKI variable.
-
- This is only expanded within any Rule operated on by this Exit.
-
- \- The \fBparameter\fR setting:
- Use this to define an IKI variable name and value.
- These do not conflict with environment variables and are not exposed as environment variables.
- Example IKI variable substitution: for \fBparameter hello world\fR, the associated IKI variable would look like: hello.
-
- This is only expanded within any Rule operated on by this Exit.
-
- \- The \fBpid\fR setting:
- Represents how the Exit PID file is generated or not.
- The following modes are supported: \fBdisable\fR, \fBrequire\fR, and \fBready\fR.
- For \fBdisable\fR, not PID file representing the Exit is created.
- For \fBrequire\fR, check to see if the PID file exists for an Exit at startup and then when \fBready\fR create a PID file, display error on PID file already exists or on failure and then fail.
- For \fBready\fR, when \fBready\fR create a PID file, display error on failure and then fail (does not check if PID file exists).
-
- \- The \fBshow\fR setting:
- Represents the way Exit processing presents information to the screen.
- This applies only to the Exit and Rule processing itself and does not handle the output of programs and scripts being executed by some Exit or Rule.
- The following show options are supported: \fBnormal\fR and \fBinit\fR.
- For \fBnormal\fR, will not report the start or stop of some Exit or Rule execution but will report any errors or warnings as appropriate.
- For \fBinit\fR, will report when starting programs and may include reporting success and failure status.
-
- \- The \fBtimeout\fR setting:
- Represents the default timeouts for the Exit.
- See the \fBtimeout\fR Action below for details.
-
-\- The \fBmain\fR Item Object:
- Is always executed first (Therefore \fBmain\fR is both reserved and required).
- All other Basic List Objects are not executed unless either an \fBitem\fR or a \fBfailsafe\fR specifies a valid Item name.
- Execution of all Items are top\-down.
-
- Each \fBitem\fR supports the following Action Names: \fBconsider\fR, \fBexecute\fR, \fBfailsafe\fR, \fBfreeze\fR, \fBitem\fR, \fBkill\fR, \fBpause\fR, \fBreload\fR, \fBrestart\fR, \fBready\fR, \fBresume\fR, \fBstart\fR, \fBstop\fR, and \fBtimeout\fR.
- Of those types, the following are considered a \fBrule\fR Action: \fBfreeze\fR, \fBkill\fR, \fBpause\fR, \fBreload\fR, \fBrestart\fR, \fBresume\fR, \fBstart\fR, \fBstop\fR, and \fBthaw\fR.
-
- \- The \fBconsider\fR Item Action:
- A special case of a \fBrule\fR Action.
- All Action Parameters are the same as with the \fBrule\fR Action Parameters.
- The difference is that \fBconsider\fR is only processed (instead of being processed and executed) and when some \fBrule\fR Action designates that this consideration is required (via \fBneed\fR), wanted (via \fBwant\fR), or wished for (via \fBwish\fR) from the within the Rule file.
- If this is determined to be executed, then this is immediately executed when needed, wanted or wished for and applies all properties as appropriate (such as \fBasynchronous\fR, for example).
- If this is determined not to be executed, then this \fBconsider\fR is ignored as if it was never there in the first place.
-
- \- The \fBexecute\fR Item Action:
- Execute into the specified program.
- On successful execution, the controller program will no longer be running and will be replaced with the designated program.
- This Item Action is only supported when operating in \fBprogram\fR mode.
-
- \- The \fBfailsafe\fR Item Action:
- Accepts only a valid Item Name in which will be executed when a failure is detected.
- Only a single \fBfailsafe\fR Item Action may function at a time.
- Each successive \fBfailsafe\fR Item Action specified replaces the previously defined \fBfailsafe\fR Item Action (in a top\-down manner).
- When operating in \fBfailsafe\fR, the \fBrequire\fR Item Action is ignored (given that it is meaningless once operating in \fBfailsafe\fR mode).
-
- \- The \fBfreeze\fR Item Action:
- A \fBrule\fR Action for freezing some Control Group.
- This Item Action will process the \fBfreeze\fR inner Content of the named Rule.
- This is specific to Control Groups and is not yet fully implemented.
- Once implemented this documentation will need to be updated and clarified.
-
- \- The \fBitem\fR Item Action:
- Accepts only a valid Item Name in which will be immediately executed.
- Any valid Item Name, except for the reserved \fBmain\fR, may be used.
-
- \- The \fBkill\fR Item Action:
- A \fBrule\fR Action for forcibly terminating some process.
- This Item Action will process the \fBkill\fR inner Content of the named Rule.
-
- \- The \fBpause\fR Item Action:
- A \fBrule\fR Action for pausing some process.
- This Item Action will process the \fBpause\fR inner Content of the named Rule.
-
- \- The \fBreload\fR Item Action:
- A \fBrule\fR Action for pausing some process.
- This Item Action will process the \fBreload\fR inner Content of the named Rule.
-
- \- The \fBrestart\fR Item Action:
- A \fBrule\fR Action for pausing some process.
- This Item Action will process the \fBrestart\fR inner Content of the named Rule.
-
- \- The \fBresume\fR Item Action:
- A \fBrule\fR Action for pausing some process.
- This Item Action will process the \fBresume\fR inner Content of the named Rule.
-
- \- The \fBready\fR Action:
- Instructs the controller program when it is safe to perform normal tasks, such as creating the PID file.
- When not specified, the state is always assumed to be ready.
- For example, the controller program may be used as a full blown \fBinit\fR replacement and therefore may need to mount the /var/run/ directory.
- If the PID file is created at program start, then the /var/run/controller.pid would be written before the /var/run/ directory is ready.
- This could be a problem, such as on a read\-only file system the PID creation fails and controller bails out on error.
- Adding \fBready\fR essentially specifies a point in time in the Exit in which things are expected to be safe for such basic operations.
- When the optional \fBwait\fR is provided, then \fBready\fR will wait for all currently started asynchronous processes to complete before operating.
-
- \- The \fBstart\fR Item Action:
- A \fBrule\fR Action for pausing some process.
- This Item Action will process the \fBstart\fR inner Content of the named Rule.
-
- \- The \fBstop\fR Item Action:
- A \fBrule\fR Action for pausing some process.
- This Item Action will process the \fBstop\fR inner Content of the named Rule.
-
- \- The \fBthaw\fR Item Action:
- A \fBrule\fR Action for unfreezing some Control Group.
- This Item Action will process the \fBthaw\fR inner Content of the named Rule.
- This is specific to Control Groups and is not yet fully implemented.
- Once implemented this documentation will need to be updated and clarified.
-
- \- The \fBtimeout\fR Item Action:
- (This is not currently fully implemented, only \fBexit\fR is implemented.)
- Provides default global settings for each of the four special situations: \fBexit\fR, \fBkill\fR, \fBstart\fR, and \fBstop\fR.
- Each of these may only have a single one exist at a time (one \fBexit\fR, one \fBkill\fR, one \fBstart\fR, and one \fBstop\fR).
- Each successive \fBtimeout\fR Item Action, specific to each Action Name (such as \fBstart\fR), specified replaces the previously defined \fBtimeout\fR Action (in a top\-down manner).
- The second Content for each of these, when specified, may be a 0 or greater whole number representing the number of MegaTime (MT) (equivalent to milliseconds).
- For \fBkill\fR, this represents the number of MegaTime to wait after stopping some Rule and that Rule has not yet stopped to forcefully stop the Rule (aka kill the Rule).
- For \fBstart\fR, this represents the number of MegaTime to wait after starting some Rule before assuming something went wrong and the Rule is returned as failed.
- For \fBstop\fR, this represents the number of MegaTime to wait after stopping some Rule before assuming something went wrong and the Rule is returned as failed.
- If the second Content is not specified, then this disables the type (prevents the specified timeout action).
-
- For \fBexit\fR, this represents the number of MegaTime to wait when the Controller program is exiting (such as having received a terminate signal).
- In this case, a terminate signal is sent to all child processes.
- The \fBexit\fR timeout represents the amount of time to wait after sending the terminate signal before sending a kill signal to each child process still running.
- When disabled, the program will not send a kill signal will continue running until all child processes to terminate.
- The \fBexit\fR timeout does not get applied to any Rule.
-.SH SPECIFICATION
-.PP
-The Exit files follow the \fBFSS\-0005 (Somewhat Basic List)\fR format.
-
-An Exit file name is expected to have the file extension \fB.exit\fR.
-
-For each Exit file:
- \- The outer most part is a \fBFSS\-0002 (Basic List)\fR.
- \- The Basic List Object is considered the \fBItem\fR.
- \- The Basic List Content are considered the \fBActions\fR.
- \- The \fBActions\fR are \fBFSS\-0001 (Extended)\fR.
- \- Each Action Object is the \fBAction Name\fR.
- \- Each Action Content are the \fBAction Parameters\fR.
-
-The Items:
- \- \fBmain\fR: required.
-
- \- \fBsettings\fR: optional, Actions may be one of:
- \- \fBpid\fR: Exactly one Content that is one of \fBdisable\fR, \fBrequire\fR, or \fBready\fR.
- \- \fBsession\fR: Exactly one Content that is one of \fBnew\fR or \fBsame\fR.
- \- \fBshow\fR: Exactly one Content that is one of \fBnormal\fR or \fBinit\fR.
- \- \fBtimeout\fR: One or Two content with the first being one of \fBexit\fR, \fBstart\fR, \fBstop\fR, or \fBkill\fR and the (optional) second Content being a positive whole number or 0.
-
- The Exit file may have any other valid Item Objects, but only the above are reserved.
-
- The Actions:
- \- \fBconsider\fR: One or more Content.
- The first Content that is the relative file path (without any leading/trailing slashes and without file extension).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBfailsafe\fR: One Content that is a valid Object name, except for the reserved \fBmain\fR.
-
- \- \fBfreeze\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBitem\fR: One Content that is a valid Object name, except for the reserved \fBmain\fR.
-
- \- \fBkill\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBpause\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBready\fR: Zero or One Content.
- The first may only be one of:
- \- \fBwait\fR
-
- \- \fBreload\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBrestart\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBresume\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBstart\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBstop\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBthaw\fR: Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of:
- \- \fBasynchronous\fR
- \- \fBrequire\fR
- \- \fBwait\fR
-
- \- \fBtimeout\fR: Two Content.
- The first being one of:
- \- \fBexit\fR
- \- \fBstart\fR
- \- \fBstop\fR
- \- \fBkill\fR
- The (optional) second Content being a positive whole number or 0.
-.SH SEE ALSO
-.PP
-\fBcontrol\fR(1),
-\fBcontroller\fR(1),
-\fBcontroller\-actions\fR(5),
-\fBcontroller\-entry\fR(5),
-\fBcontroller\-packet\fR(5),
-\fBcontroller\-rule\fR(5)
-.SH AUTHOR
-Written by Kevin Day.
-.SH COPYRIGHT
-.PP
-Copyright \(co 2007-2024 Kevin Day, Open Standard License 1.0 or later.
+++ /dev/null
-.TH controller-rule "5" "January 2023" "Controller 0.7.0" "File Formats"
-.SH NAME
-Controller \- "rule" file.
-.SH SYNOPSIS
-.B rule
-.SH DESCRIPTION
-.PP
-Describes how a packet is designed and intended to be used.
-
-The \fBpacket\fR is the general category in which multiple types of packets belong.
-This describes the different packets based on their \fBtype\fR.
-
-Each packet begins with a control block and a size block followed by a payload block.
-
- The control block:
- The leading bit (starting from the left) designates the the format of the payload, which is 0 for string and 1 for binary.
- The second bit (starting from the left) designates the the byte order for the rest of the packet, which 0 is for little endian and 1 is for big endian.
- The remaining 6\-bits are reserved for future use.
-
- The size block:
- The size block represents the size of the entire packet (the control block, the size blocks, and the payload block).
- This number is a single 32\-bit unsigned integer.
-
- Example packet structure:
-
- [ Control Block ] [ Size Block ] [ Payload Block ]
- [ 0b10000000 ] [ 0b00000000 0b00000000 0b00000100 0b11010010 ] [ size: 1229 (1234 \- 5) ]
-
-
- The payload block:
- This block is represented by the \fBFSS\-000E (Payload)\fR specification and its structure ad use is described in the next sections.
-
- The following types of payload are received or sent:
- 1) controller payload.
- 2) error payload.
- 3) init payload.
-
-The controller payload:
- Commands being sent to the controller and their respective responses utilize a \fBcontroller\fR payload.
- These are pre\-defined commands to rules or the controller program itself.
- Commands such as starting or stopping some rule, for example.
- A controller payload is also sent in response to a controller payload request to represent a success.
-
- The \fBnow\fR condition designates that the kexec, reboot, or shutdown is to begin immediately.
- The \fBat\fR condition designates that the kexec, reboot, or shutdown is to begin once a specific date and time is reached by the system clock.
- The \fBin\fR condition designates that the kexec, reboot, or shutdown is to begin once a specific amount of time is passed by the system clock since the execution of this command started.
-
- For these \fBtime\fR conditions, different units of time should be supported, such as \fBseconds\fR, \fBdays\fR, \fByears\fR as standard time, Time, or UNIX Time (Epoch Time).
-
- The normal \fBcontroller\fR payload commands are any valid Rule Action that performs some action.
- This does not include Actions that provide some setting or configuration (such as \fBwith_pid\fR).
- Some of the supported commands are: \fBfreeze\fR, \fBkill\fR, \fBpause\fR, \fBreload\fR, \fBrerun\fR, \fBrestart\fR, \fBresume\fR, \fBstart\fR, \fBstop\fR, or \fBthaw\fR.
- Multiple commands may be sent multiple \fBaction\fR headers.
- The \fBaction\fR headers are order sensitive, executing from top to bottom, and one does not start until the previous successfully completes.
-
- Multiple \fBstatus\fR headers may exist in the response so long as they each match an \fBaction\fR in the request.
-
- The \fBpayload\fR is expected to be empty and have a length of 0 for a request.
- The \fBpayload\fR may have an \fBFSS\-0000 (Basic)\fR format containing a single Object \fBmessage\fR to represent a message associated with an action.
- Multiple \fBmessage\fR may exist in the response so long as they each match an \fBaction\fR in the request.
-
-The error payload:
- The error payload is intended to communicate some sort of failure.
- The error payload is only sent in response to some request (and not in response to another response).
- The control (the client) is not expected to send error payloads and the controller (the service) should send an error in response to an error payload or ignore it entirely.
- The \fBstatus\fR from the \fBheader\fR designates the status code as either a status code name string or a status code number (where a number may have error and warning bits).
- The \fBpayload\fR will contain a NULL terminated string representing the message used to describe the error.
-
-The init payload:
- The init payload is intended exclusively for the \fBinit\fR operation mode and is expected to only be available when running as \fBinit\fR.
- This is used to provide special actions, namely \fBkexec\fR, \fBreboot\fR, and \fBshutdown\fR.
-
- The \fBkexec\fR is for booting into another kernel, which may effectively be the same as a \fBreboot\fR ("kexec" is currently neither supported nor implemented).
- The \fBreboot\fR is for rebooting the machine (currently not implemented).
- The \fBshutdown\fR is for shutting down the machine (currently not implemented).
- These three commands are configurable to fire off based on conditions.
-.SH SPECIFICATION
-.PP
-The controller program communicates use the \fBFSS\-000F (Packet)\fR.
-This specification declares how the Payload Block, which is in \fBFSS\-000E (Payload)\fR format, is required to be used.
-
-Only a single \fBheader\fR is allowed.
-Only a single \fBpayload\fR is allowed.
-
-Packet Structure:
- Packet is grouped into the following blocks:
- \- \fBcontrol\fR: A single 1\-byte block representing control codes.
- \- \fBsize\fR: A single 4\-byte block representing the size of the entire packet, including the control block.
-
-The \fBheader\fR Object contains the following \fBFSS\-0001 (Extended)\fR Objects (depending on \fBtype\fR):
- \- \fBaction\fR: A valid action type: \fBfreeze\fR, \fBkexec\fR, \fBkill\fR, \fBpause\fR, \fBreboot\fR, \fBreload\fR, \fBrerun\fR, \fBrestart\fR, \fBresume\fR, \fBshutdown\fR, \fBstart\fR, \fBstop\fR, or \fBthaw\fR.
- \- \fBlength\fR: A positive whole number inclusively between 0 and 4294965248 representing the length of the \fBpayload\fR (may be in binary, octal, decimal, duodecimal, or hexidecimal).
- \- \fBstatus\fR: The status code name or number representing an FSS status code, such as F_okay, F_failure, or 200 (where a number may have error and warning bits and may be in binary, octal, decimal, duodecimal, or hexidecimal).
- \- \fBtype\fR: The packet type that is one of \fBcontroller\fR, \fBerror\fR, or \fBinit\fR.
-
-When there are multiple Objects of the same name inside the \fBheader\fR:
- \- \fBaction\fR: The order represents the order in which the actions are performed.
- \- \fBlength\fR: There may only be one length Object, all others after the first are ignored (may be in binary, octal, decimal, duodecimal, or hexidecimal).
- \- \fBstatus\fR: A status for each action, in the same order as the order of the action, such as F_okay, F_failure, or 200 (where a number may have error and warning bits and may be in binary, octal, decimal, duodecimal, or hexidecimal).
- \- \fBtype\fR: The first represent the type and all others represents a sub\-type.
-
-There are different headers and payload properties based on the \fBtype\fR.
-
-The \fBcontroller\fR type:
- Supports the following headers: \fBaction\fR, \fBlength\fR, \fBstatus\fR, and \fBtype\fR.
-
- Only a single \fBaction\fR may be provided and must exist for request and response packets.
- Only a single \fBstatus\fR may be provided and must exist for response packets.
-
- The \fBpayload\fR is dependent on the \fBaction\fR.
-
-The \fBerror\fR type:
- Supports the following headers: \fBlength\fR, \fBstatus\fR, and \fBtype\fR.
-
- Only a single \fBstatus\fR may be provided and must exist for request and response packets.
-
- The \fBpayload\fR is a NULL terminated string whose length is defined by the \fBlength\fR \fBheader\fR Content.
-
-There are different headers and payload properties based on the \fBtype\fR.
-
-The \fBinit\fR type:
- Supports the following headers: \fBaction\fR, \fBlength\fR, \fBstatus\fR, and \fBtype\fR.
-
- Only a single \fBaction\fR may be provided and must exist for request and response packets.
- Only a single \fBstatus\fR may be provided and must exist for response packets.
-
- The \fBpayload\fR is dependent on the \fBaction\fR.
-.SH SEE ALSO
-.PP
-\fBcontrol\fR(1),
-\fBcontroller\fR(1),
-\fBcontroller\-actions\fR(5),
-\fBcontroller\-entry\fR(5),
-\fBcontroller\-exit\fR(5),
-\fBcontroller\-rule\fR(5)
-.SH AUTHOR
-Written by Kevin Day.
-.SH COPYRIGHT
-.PP
-Copyright \(co 2007-2024 Kevin Day, Open Standard License 1.0 or later.
+++ /dev/null
-.TH controller-rule "5" "January 2023" "Controller 0.7.0" "File Formats"
-.SH NAME
-Controller \- "rule" file.
-.SH SYNOPSIS
-.B rule
-.SH DESCRIPTION
-.PP
-This describes the intent and purpose of a Rule file.
-
-A Rule file, such as \fBssh.rule\fR, is intended to designate what to execute.
-
-The rule file is read top\-down, except for the outer most list \fBsettings\fR, which is intended to store setting data for this rule.
-Multiple outer most list Objects may be specified and they are executed as provided, in a top\-down manner.
-
-\- The \fBsettings\fR Rule Type has the following \fBFSS\-0001 (Extended)\fR Content:
- \- \fBaffinity\fR: Define one or more processors to restrict this rule by with each number representing a specific processor by its id (starting at 0).
- \- \fBcapability\fR: Define a set of capabilities in which to use, using the capability \fBtext\fR format (such as \fB= cap_chown+ep\fR).
- \- \fBcgroup\fR: Define a cgroup (control group) in which everything within this rule executes under.
- \- \fBdefine\fR: A single environment variable name and its associated value that is automatically exposed to processes executed within this rule.
- \- \fBengine\fR: An executable name of a script, such as \fBbash\fR, to use for the \fBscript\fR Rule Type (which likely defaults to \fBbash\fR if not specified).
- \- \fBenvironment\fR: A set of environment variables to expose to the processes executed within this rule (PATH is always exposed).
- \- \fBgroup\fR: A set of group names or IDs to execute as with the first group being the primary group and all remaining being supplementary groups.
- \- \fBlimit\fR: Define a resource limit to use (multiple limits may be specified, but only once for each type).
- \- \fBname\fR: A name used to represent this rule, which is printed to the user, screen, logs, etc...
- \- \fBnice\fR: A single niceness value to run all processes executed within this rule as (\-20 gets to be greediest in CPU usage and 19 being the nicest in CPU usage).
- \- \fBon\fR: Define a Rule Action in which a specified dependency is needed, wanted, or wished for.
- \- \fBparameter\fR: An IKI name and its associated value for use in this rule file.
- \- \fBpath\fR: A single Content used to set a custom PATH environment variable value.
- \- \fBscheduler\fR: A valid name of a scheduler to use followed by an optional priority number.
- \- \fBtimeout\fR: A set of timeouts to wait for in which to perform a set action or to consider failure.
- \- \fBuser\fR: A single user name or ID to execute as.
-
-\- The \fBcapability\fR setting:
- If the user the controller program is run as does not have the desired capabilities already, they cannot be added.
- This essentially maintains or reduces the capabilities already available.
- Due to capabilities only being a draft in the POSIX standard, one may expect \fBcapabilities\fR support may not be available and in such a case this setting will do nothing.
- If the dependent project (f_capability) does not have libcap support enabled, then capabilities will be unsupported by the compilation of this project.
-
-\- The \fBcontrol\fR setting:
- The first argument is either \fBexisting\fR or \fBnew\fR, where for \fBexisting\fR the process is run inside the existing control used by the parent and when \fBnew\fR the process is executed within a new control group namespace entirely.
-
-\- The \fBdefine\fR setting:
- Use this to define an environment variable (this overwrites any existing environment variable with this name).
- A define is both exported as an environment variable as well as exposed as an IKI variable.
- Example IKI variable substitution: for \fBdefine PATH /bin:/sbin\fR, the associated IKI variable would look like: PATH.
-
- All environment variables, including those defined using this, must be in the \fBenvironment\fR list to be exported to the executed process.
- Environment variables added here that are not added to the environment are still exposed as an IKI variable.
-
-\- The \fBengine\fR setting:
- This engine is used for both \fBscript\fR and \fButility\fR Rule Types.
- The program that engine refers to must accept a standard input pipe to be supported.
- Additional parameters may be passed to the engine.
-
-\- The \fBgroup\fR and \fBuser\fR settings:
- Only users and groups that the user the controller program is being run as is allowed to use may be used.
-
-\- The \fBlimit\fR setting:
- The first parameter must be one of: \fBas\fR, \fBcore\fR, \fBcpu\fR, \fBdata\fR, \fBfsize\fR, \fBlocks\fR, \fBmemlock\fR, \fBmsgqueue\fR, \fBnice\fR, \fBnofile\fR, \fBnproc\fR, \fBrss\fR, \fBrtprio\fR, \fBrttime\fR, \fBsigpending\fR, or \fBstack\fR.
- The second parameter represents the soft limit.
- The third parameter represents the hard limit.
- This may be specified multiply times, but only once for each type.
-
-\- The \fBon\fR setting:
- The first parameter represents the Action the dependency exists under and must be one of: \fBfreeze\fR, \fBkill\fR, \fBpause\fR, \fBreload\fR, \fBrestart\fR, \fBresume\fR, \fBstart\fR, \fBstop\fR, or \fBthaw\fR.
- The second parameter represents how the dependency is required and must be one of: \fBneed\fR, \fBwant\fR, or \fBwish\fR.
- The third parameter is a partial path to the rule file.
- The fourth parameter represents the name of the rule file.
-
- \- In the case of the second parameter:
- \- A \fBneed\fR designates that the dependent rule is required to be executed (must exist and must succeed).
- \- A \fBwant\fR designates that the dependent rule is to be executed (may exist and if it does, then it must succeed).
- \- A \fBwish\fR designates that the dependent rule is to be executed (may exist and if it does, but it does not need to succeed).
-
- In the case of \fBwant\fR and \fBwish\fR, if the desired rule is either not found or is otherwise disabled, then this will not fail or otherwise block the wanting or wishing rule.
-
-\- The \fBpath\fR setting:
- When specified, the \fBPATH\fR environment variable is automatically added to the \fBenvironment\fR setting.
-
-\- The \fBparameter\fR setting:
- Use this to define an IKI variable name and value.
- These do not conflict with environment variables and are not exposed as environment variables.
- Example IKI variable substitution: for \fBparameter hello world\fR, the associated IKI variable would look like: hello.
-
-\- The \fBscheduler\fR setting:
- The valid range of the priority number is dependent on the scheduler.
- For example, non\-real\-time schedulers (such as \fBidle\fR) only support a value of 0 whereas real\-time schedulers (such as \fBfifo\fR) only support an inclusive range of 1 to 99.
- Supported non\-real\-time schedulers are: \fBbatch\fR, \fBidle\fR, and \fBother\fR (aka: normal/default).
- Supported real\-time schedulers are: \fBdeadline\fR, \fBfifo\fR, \fBround_robin\fR.
-
-\- The \fBtimeout\fR setting:
- (This is not currently implemented.)
- Provides settings for each of the three special situations: \fBkill\fR, \fBstart\fR, and \fBstop\fR.
- Each of these may only have a single one exist at a time (one \fBkill\fR, one \fBstart\fR, and one \fBstop\fR).
- Each successive \fBtimeout\fR Item Action, specific to each Action Name (such as \fBstart\fR), specified replaces the previously defined \fBtimeout\fR Action (in a top\-down manner).
- The second Content for each of these, when specified, may be a 0 or greater whole number representing the number of MegaTime (MT) (equivalent to milliseconds).
- For \fBkill\fR, this represents the number of MegaTime to wait after stopping some Rule and that Rule has not yet stopped to forcefully stop the Rule (aka kill the Rule).
- For \fBstart\fR, this represents the number of MegaTime to wait after starting some Rule before assuming something went wrong and the Rule is returned as failed.
- For \fBstop\fR, this represents the number of MegaTime to wait after stopping some Rule before assuming something went wrong and the Rule is returned as failed.
- If the second Content is not specified, then this disables the type (prevents the specified timeout action).
-
-There are four available Rule Types to choose from: \fBcommand\fR, \fBservice\fR, \fBscript\fR, and \fButility\fR.
-
-The \fBcommand\fR Rule Type provides a simple command to run under the different circumstances: \fBstart\fR, \fBstop\fR, \fBrestart\fR, and \fBreload\fR.
-A \fBcommand\fR always operates in the foreground.
-
-The \fBservice\fR Rule Type provides a \fBcommand\fR accompanied with a PID file (Process Identifier file).
-
-The \fBscript\fR Rule Type provides a series of lines to be executed by some engine, such as GNU Bash.
-This \fBscript\fR operates in the foreground, but individual things done within the script may operate in foreground or background.
-The last return state is treated as an error, so be sure to finish the script with a return code of 0 to designate no error and any other whole number, such a 1, to designate an error.
-Therefore passing \fBexit 1\fR would return as an error and passing \fBexit 0\fR would return as a success.
-A \fBscript\fR is assumed to be in GNU Bash, which is the default expected behavior, but the specification does not explicitly require this.
-Another scripting language can be used but changing this incurs the responsibility to ensure all rules are updated to the appropriate scripting language.
-
-The \fButility\fR Rule Type provides a \fBscript\fR accompanied with a PID file (Process Identifier file).
-
-There are nine Rule Actions used to execute ("freeze", \fBkill\fR, \fBpause\fR, \fBreload\fR, \fBrestart\fR, \fBresume\fR, \fBstart\fR, \fBstop\fR, and \fBthaw\fR):
- When \fBrestart\fR Object's Content is not provided, then \fBstart\fR and \fBstop\fR is called when the rule is executed using the restart Action, if both \fBstart\fR and \fBstop\fR are provided.
- When \fBreload\fR, \fBstart\fR, or \fBstop\fR Object's Content are not provided, then no respective Action is performed.
-
- Commands are conditionally available depending on the presence of these, such as if \fBstop\fR is not provided then \fBstop\fR (and \fBrestart\fR) will not be available for the \fBcontrol\fR program(s) to use.
-
-Thee are additional Rule Actions not used to execute ("pid_file", \fBrerun\fR, and \fBwith\fR):
- \- The \fBpid_file\fR Object's Content designates the path to the PID file created by the called program.
-
- \- The \fBrerun\fR Object's Content designates how to re\-run a given execution Rule type.
- \- The first Content represents the execution type, which may be one of: \fBfreeze\fR, \fBkill\fR, \fBpause\fR, \fBreload\fR, \fBrestart\fR, \fBresume\fR, \fBstart\fR, \fBstop\fR, and \fBthaw\fR.
-
- \- The second Content represents when to run this re\-run is triggered, which is either \fBsuccess\fR (return code of 0) or \fBfailure\fR (return code is not 0).
-
- \- The third Content and more represent additional options for fine tuning how the re\-run is Performed:
- When \fBdelay\fR, followed by a number of MegaTime (MT) (equivalent to milliseconds) in which to wait before attempting the re\-run.
- When \fBmax\fR, followed by a positive number or the number 0 designating the maximum number of re\-runs to perform.
- When \fBreset\fR, the \fBmax\fR re\-run counter is reset for the opposite re\-run when this re\-run is triggered, such as:
- A \fBrerun start success reset\fR and a \fBrerun failure max 10\fR, the failure counter would reset to 0 when the \fBsuccess\fR re\-run is performed and not when the \fBfailure\fR re\-run is performed.
-
- A \fBmax\fR of 0 designates that the re\-run will happen infinitely.
-
- \- The \fBwith\fR Object's Content designates special flags designating very specific behavior to be applied to any single Rule Type.
-.SH SPECIFICATION
-.PP
-The Rule files follow the \fBFSS\-000D (Basic Rule)\fR format with IKI\-0000 (Unrestricted).
-
-A Rule file name is expected to have the file extension \fB.rule\fR.
-
-For each Rule file:
- \- The outer most part is a \fBFSS\-0002 (Basic List)\fR.
- \- The Basic List Object is considered the \fBRule Type\fR.
- \- The Basic List Content is determined by the specific \fBRule Type\fR.
- \- The Content for each \fBRule Type\fR is called the \fBItem\fR.
- \- Each Item Object is the \fBItem Name\fR.
- \- Each Item Content is either the \fBAction\fR or the \fBSetting\fR.
- \- Each Action Object is the \fBAction Name\fR.
- \- Each Action Content are the \fBAction Parameters\fR.
- \- Each Setting Object is the \fBSetting Name\fR.
- \- Each Setting Content are the \fBSetting Values\fR.
-
-The Rule Types:
- \- \fBcommand\fR: Follows either \fBFSS\-0003 (Extended List)\fR or \fBFSS\-0001 (Extended)\fR.
- \- \fBscript\fR: Follows either \fBFSS\-0003 (Extended List)\fR or \fBFSS\-0001 (Extended)\fR.
- \- \fBservice\fR: Follows either \fBFSS\-0003 (Extended List)\fR or \fBFSS\-0001 (Extended)\fR.
- \- \fBsettings\fR: Is required and follows either \fBFSS\-0001 (Extended)\fR.
- \- \fButility\fR: Follows either \fBFSS\-0003 (Extended List)\fR or \fBFSS\-0001 (Extended)\fR.
-
-For the above Rule Types, \fBsettings\fR may be specified only once whereas the others may be specifed multiple times.
-The \fBsettings\fR Rule Type is always processed first, regardless of position.
-The other Rule Types are processed top\-down.
-
-The \fBsettings\fR Rule Type has the following \fBFSS\-0001 (Extended)\fR:
- \- \fBaffinity\fR: One or more Content, each must be a 0 or greater whole number.
- \- \fBcapability\fR: One Content representing capabilities.
- \- \fBcgroup\fR: Two or more Content, the first Content being either \fBexisting\fR or \fBnew\fR and the remaining representing a valid cgroup (control group) name, must have at least 1 graph character (non white space printing character) (leading and trailing white space are trimmed off).
- \- \fBdefine\fR: Two Content, the first Content must be a case\-sensitive valid environment variable name (alpha\-numeric or underscore, but no leading digits).
- \- \fBengine\fR: One or more Content representing a valid program name or path (such as \fBbash\fR or \fB/bin/bash\fR) and any optional arguments.
- \- \fBenvironment\fR: Zero or more Content, each must be a case\-sensitive valid environment variable name (alpha\-numeric or underscore, but no leading digits).
- \- \fBgroup\fR: One or more Content representing group names or group ids.
- \- \fBlimit\fR: Three Content, with the first representing a valid resource type and the second and third being a valid resource limit number (positive whole number or 0).
- \- \fBname\fR: One Content, must have at least 1 graph character (non white space printing character) (leading and trailing white space are trimmed off).
- \- \fBnice\fR: One Content, must be a valid number for process \fBniceness\fR (Any whole number inclusively between \-20 to 19).
- \- \fBon\fR: Four Content, the first being a Rule Action, the second being \fBneed\fR, \fBwant\fR, or \fBwish\fR, the third being a partial path, and the fourth being a Rule file name without \fB.rule\fR extension.
- \- \fBparameter\fR: Two Content, the first Content must be a case\-sensitive valid IKI name and the second being an IKI value.
- \- \fBpath\fR: One Content representing a valid \fBPATH\fR environment string (such as \fB/bin:/sbin:/usr/bin\fR).
- \- \fBscheduler\fR: One or two Content representing a scheduler name and the optional numeric priority (Any whole number inclusively between 0 and 99).
- \- \fBtimeout\fR: One or two content with the first being one of \fBexit\fR, \fBstart\fR, \fBstop\fR, or \fBkill\fR and the (optional) second Content being a positive whole number or 0.
- \- \fBuser\fR: One Content representing a user name or user id.
-
-The \fBcommand\fR and \fBscript\fR Rule Types allow the following the \fBFSS\-0001 (Extended)\fR:
- \- \fBfreeze\fR: One or more Content representing a program being executed and its arguments.
- \- \fBkill\fR: One or more Content representing a program being executed and its arguments.
- \- \fBpause\fR: One or more Content representing a program being executed and its arguments.
- \- \fBreload\fR: One or more Content representing a program being executed and its arguments.
- \- \fBrerun\fR: Two or more Content representing a Rule type that executes and its properties.
- \- \fBrestart\fR: One or more Content representing a program being executed and its arguments.
- \- \fBresume\fR: One or more Content representing a program being executed and its arguments.
- \- \fBstart\fR: One or more Content representing a program being executed and its arguments.
- \- \fBstop\fR: One or more Content representing a program being executed and its arguments.
- \- \fBthaw\fR: One or more Content representing a program being executed and its arguments.
- \- \fBwith\fR: One or more Content representing special options for the Rule Type.
-
-The \fBservice\fR and \fButility\fR Rule Types allow the following the \fBFSS\-0001 (Extended)\fR:
- \- \fBpid_file\fR: One Content representing the path to a PID file.
- \- \fBrerun\fR: Two or more Content representing a Rule type that executes and its properties.
- \- \fBwith\fR: One or more Content being one of \fBfull_path\fR, \fBsession_new\fR, or \fBsession_same\fR.
-
-The \fBcommand\fR and \fBservice\fR Rule Types allow the following the \fBFSS\-0003 (Extended List)\fR:
- \- \fBfreeze\fR: A list repesenting multiple programs and their respective arguments to execute.
- \- \fBkill\fR: A list repesenting multiple programs and their respective arguments to execute.
- \- \fBpause\fR: A list repesenting multiple programs and their respective arguments to execute.
- \- \fBreload\fR: A list repesenting multiple programs and their respective arguments to execute.
- \- \fBrestart\fR: A list repesenting multiple programs and their respective arguments to execute.
- \- \fBresume\fR: A list repesenting multiple programs and their respective arguments to execute.
- \- \fBstart\fR: A list repesenting multiple programs and their respective arguments to execute.
- \- \fBstop\fR: A list repesenting multiple programs and their respective arguments to execute.
- \- \fBthaw\fR: A list repesenting multiple programs and their respective arguments to execute.
-
-The \fBscript\fR and \fButility\fR Rule Types allow the following the \fBFSS\-0003 (Extended List)\fR:
- \- \fBfreeze\fR: A list repesenting the contents of a script, such as a GNU Bash shell.
- \- \fBkill\fR: A list repesenting the contents of a script, such as a GNU Bash shell.
- \- \fBpause\fR: A list repesenting the contents of a script, such as a GNU Bash shell.
- \- \fBreload\fR: A list repesenting the contents of a script, such as a GNU Bash shell.
- \- \fBrestart\fR: A list repesenting the contents of a script, such as a GNU Bash shell.
- \- \fBresume\fR: A list repesenting the contents of a script, such as a GNU Bash shell.
- \- \fBstart\fR: A list repesenting the contents of a script, such as a GNU Bash shell.
- \- \fBstop\fR: A list repesenting the contents of a script, such as a GNU Bash shell.
- \- \fBthaw\fR: A list repesenting the contents of a script, such as a GNU Bash shell.
-
-The \fBrerun\fR Rule Type Content has the following structure:
- The first Content represents one of: \fBfreeze\fR, \fBkill\fR, \fBpause\fR, \fBreload\fR, \fBrestart\fR, \fBresume\fR, \fBstart\fR, \fBstop\fR, or \fBthaw\fR.
- The second Content represents one of: \fBsuccess\fR or \fBfailure\fR.
- The third and more Content represents one of: \fBdelay\fR, \fBmax\fR, or \fBreset\fR.
- Where \fBdelay\fR and \fBmax\fR must be followed by a positive number or the number 0.
-.SH SEE ALSO
-.PP
-\fBcontrol\fR(1),
-\fBcontroller\fR(1),
-\fBcontroller\-actions\fR(5),
-\fBcontroller\-entry\fR(5),
-\fBcontroller\-exit\fR(5),
-\fBcontroller\-packet\fR(5)
-.SH AUTHOR
-Written by Kevin Day.
-.SH COPYRIGHT
-.PP
-Copyright \(co 2007-2024 Kevin Day, Open Standard License 1.0 or later.
+++ /dev/null
-# fss-0005
-#
-# A very basic boot process.
-#
-
-settings:
- pid ready
- show init
-
- control init.socket
- control_user 0
- control_group 0
- control_mode ug+rwx,o-rwx
-
-task:
- reboot system reboot
- shutdown system shutdown
-
-main:
- timeout start 7
- timeout stop 7
- timeout kill 3
-
- failsafe maintenance
-
- item boot
- item net
- item time
- item keyboard
- item console
-
-boot:
- start boot root require
- start boot proc asynchronous require
- start boot devices asynchronous require
- start boot file_system asynchronous
- start boot modules wait
-
- start service logger
- start service dbus asynchronous
-
- ready
-
-net:
- start net all asynchronous
-
-time:
- start task clock asynchronous
-
-keyboard:
- start task keyboard asynchronous
-
-console:
- start service mouse asynchronous
-
- start terminal two asynchronous
- start terminal three asynchronous
- start terminal four asynchronous
- start terminal one require wait
-
-maintenance:
- #execute /bin/agetty -8 -i -J tty1 linux
- #execute /bin/setsid -c /bin/bash --login
- execute /bin/bash --login
+++ /dev/null
-# fss-0005
-#
-# A boot to bash process.
-#
-
-settings:
- pid disable
- show init
-
-main:
- #execute /bin/agetty -8 -i -J tty1 linux
- #execute /bin/setsid -c /bin/bash --login
- execute /bin/bash --login
+++ /dev/null
-# fss-0005
-
-settings:
- mode helper
-
-main:
- start program chromium asynchronous
+++ /dev/null
-# fss-0005
-
-settings:
- mode helper
-
-main:
- start program eclipse asynchronous
+++ /dev/null
-# fss-0005
-
-settings:
- mode helper
-
-main:
- start program firefox asynchronous
+++ /dev/null
-# fss-0005
-
-settings:
- mode program
-
-main:
- start setup cgroups
+++ /dev/null
-# fss-000d
-
-settings:
- name "Run Chromium"
- cgroup existing user.slice/user-1000.slice/user@1000.service/user_you/group/browser
-
-command:
- start chromium --disable-features=UserAgentClientHint
+++ /dev/null
-# fss-000d
-
-settings:
- name "Run Eclipse"
- cgroup existing user.slice/user-1000.slice/user@1000.service/user_you/group/eclipse
-
-command:
- start eclipse
+++ /dev/null
-# fss-000d
-
-settings:
- name "Run Firefox (ESR)"
- cgroup existing user.slice/user-1000.slice/user@1000.service/user_you/group/browser
-
-command:
- start firefox-esr
+++ /dev/null
-# fss-000d
-#
-# A cgroups2 example for systemd-based system using example user with example subdirectories and example programs.
-#
-# This uses a 12-core system as an example.
-#
-# This is intended to be run as the user rather than as root.
-#
-# Example sizes:
-# For 2GB: 2 * 1024 * 1024 * 1024.
-#
-
-settings:
- name "Setup Cgroups for User 1000, named "you""
-
-script:
-
- start {
- main() {
- local user="you"
- local group="you"
- local path_cgroup="/sys/fs/cgroup/"
- local path_slice_1="${path_cgroup}user.slice/"
- local path_slice_2="${path_slice_1}user-1000.slice/"
- #local path_slice_3="${path_slice_2}" # Some systemd's might work without the service directory.
- local path_slice_3="${path_slice_2}user@1000.service/" # Some systemd's only give access to this service directory (the '@' is a problem and requires quoting).
- local path_user="${path_slice_3}user_${user}/"
- local path_group="${path_user}group/"
- local path_top_subtree="${path_cgroup}cgroup.subtree_control" # Modifying this likely requires root privileges.
- local directories="browser eclipse untrusted"
- local d=
- local i=
- local subtree="+cpu +cpuset +memory +pids"
-
- # The user path is for restricting the user and should not grant permissions to user other than read and execute directory.
- if [[ ! -d "${path_user}" ]] ; then
- mkdir -p "${path_user}"
-
- if [[ $? -ne 0 ]] ; then echo "Failed mkdir ${path_user}." ; return 1 ; fi
- fi
-
- chmod -R u+rwX,g+rX-w,o-rwx "${path_user}" &&
- chgrp -R ${group} "${path_user}"
-
- if [[ $? -ne 0 ]] ; then echo "Failed mkdir ${path_group}." ; return 1 ; fi
-
- # The group path is for the user to restrict processes they run and must have ownership with write access.
- if [[ ! -d "${path_group}" ]] ; then
- mkdir -p "${path_group}"
-
- if [[ $? -ne 0 ]] ; then echo "Failed mkdir ${path_group}." ; return 1 ; fi
- fi
-
- # Must have common ancestor with write acces, so fix setup from systemd to work with this one.
- chmod -R u+rw+X,g+rX-w,o-rwx "${path_group}" &&
- chown -R ${user}:${group} "${path_group}"
-
- if [[ $? -ne 0 ]] ; then echo "Failed change permission on ${path_group}." ; return 1 ; fi
-
- # Make sure the user can manipulate subtrees (May fail if any path outside of ${path_slice_1} lacks things wanted by ${subtree}).
- echo ${subtree} >> "${path_slice_1}cgroup.subtree_control"
- if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_slice_1}cgroup.subtree_control." ; return 1 ; fi
-
- echo ${subtree} >> "${path_slice_2}cgroup.subtree_control"
- if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_slice_2}cgroup.subtree_control." ; return 1 ; fi
-
- echo ${subtree} >> "${path_slice_3}cgroup.subtree_control"
- if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_slice_3}cgroup.subtree_control." ; return 1 ; fi
-
- echo ${subtree} >> "${path_slice_4}cgroup.subtree_control"
- if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_slice_4}cgroup.subtree_control." ; return 1 ; fi
-
- echo ${subtree} >> "${path_user}cgroup.subtree_control"
- if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_user}cgroup.subtree_control." ; return 1 ; fi
-
- echo ${subtree} >> "${path_group}cgroup.subtree_control"
- if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_group}cgroup.subtree_control." ; return 1 ; fi
-
- for d in ${directories} ; do
- i="${path_group}${d}/"
-
- if [[ ! -d ${i} ]] ; then
- echo "Creating cgroup directory '${i}'."
-
- mkdir -p "${i}" &&
- chown -R ${user}:${group} "${i}" &&
- chmod -R u+rw+X,g+rX-w,o-rwx "${i}" &&
- chmod g+s "${i}"
-
- if [[ $? -ne 0 ]] ; then echo "Failed change permission on ${i}." ; return 1 ; fi
- fi
-
- if [[ ${d} == "browser" ]] ; then
- put_into "7516192768" "${i}memory.high" &&
- put_into "8589934592" "${i}memory.max" &&
- put_into "3-6" "${i}cpuset.cpus"
- elif [[ ${d} == "eclipse" ]] ; then
- put_into "3758096384" "${i}memory.high" &&
- put_into "4294967296" "${i}memory.max" &&
- put_into "5-8" "${i}cpuset.cpus"
- else
- put_into "858993459" "${i}memory.high" &&
- put_into "1073741824" "${i}memory.max" &&
- put_into "9-11" "${i}cpuset.cpus"
- fi
-
- if [[ $? -ne 0 ]] ; then echo "Failed to restrictions for ${d} at ${i}." ; return 1 ; fi
- done
-
- return 0
- \}
-
- put_into() {
- if [[ -e ${2} ]] ; then
- echo ${1} > ${2} || return 1
- fi
-
- return 0
- \}
-
- main
- }
+++ /dev/null
-# fss-0005
-
-main:
- start serial s_1 asynchronous
- start serial s_2 asynchronous
- start serial s_3 asynchronous
- start serial s_4 asynchronous
- start serial s_5 asynchronous
- start serial s_6 asynchronous
-
- ready wait
+++ /dev/null
-# fss-0005
-
-settings:
- mode program
-
-main:
- ready
-
- consider asynchronous sleep_8 asynchronous
- consider asynchronous sleep_10 asynchronous
-
- start asynchronous sleep_1 asynchronous
- start asynchronous sleep_2 asynchronous
- start asynchronous sleep_3 asynchronous
- start asynchronous sleep_5 asynchronous
- start asynchronous sleep_8 asynchronous
- start asynchronous sleep_10 asynchronous
+++ /dev/null
-# fss-0005
-
-settings:
- mode program
-
-main:
- start delay short
- start delay long
+++ /dev/null
-# fss-0005
-
-settings:
- mode service
-
-main:
- start delay short
- start delay long
+++ /dev/null
-# fss-0005
-
-settings:
- mode program
-
-main:
- start environment default
- start environment exported
- start environment empty
- start environment exporting
- start environment fake-nothing
- start environment fake-something
-
- start print newline
+++ /dev/null
-# fss-0005
-#
-# This example shows how htop can be started during the exit process rather than the entry.
-# See the htop-alternate.exit example.
-
-settings:
- mode program
-
- control htop.socket
- control_user 0
- control_group 0
- control_mode ug+rwx,o-rwx
-
-main:
- start serial s_1 asynchronous
- start serial s_2 asynchronous
- start serial s_3 asynchronous
-
- ready wait
+++ /dev/null
-# fss-0005
-
-settings:
- mode program
-
- control htop.socket
- control_user 0
- control_group 0
- control_mode ug+rwx,o-rwx
-
-main:
- start command htop
+++ /dev/null
-# fss-0005
-
-settings:
- mode program
-
- control htop.socket
- control_user 0
- control_group 0
- control_mode ug+rwx,o-rwx
-
-main:
- failsafe start_top
-
- start serial s_1 asynchronous require
- start serial s_2 asynchronous require
- start serial s_3 asynchronous require
-
- ready wait
-
- execute htop
-
-start_top:
- execute top
+++ /dev/null
-# fss-0005
-
-settings:
- mode program
-
-main:
- ready
-
- start script iki
+++ /dev/null
-# fss-0005
-
-settings:
- mode program
-
-main:
- start serial s_1
- start serial s_2
- start serial s_3
- start serial s_4
- start serial s_5
- start serial s_6
-
- ready
+++ /dev/null
-# fss-0005
-
-main:
- consider serial s_1
- consider serial s_2
- consider serial s_3
- consider serial s_4
- consider serial s_5
-
- start serial s_6
-
- ready
+++ /dev/null
-# fss-0005
-
-main:
- timeout start 7
- timeout stop 7
- timeout kill 3
-
- failsafe explode
-
- start service sshd
-
-explode:
- start maintenance boom
+++ /dev/null
-# fss-0005
-
-main:
- timeout start 7
- timeout stop 7
- timeout kill 3
-
- failsafe explode
-
- item first
- item last
-
-first:
- consider script require_me
-
- start script succeed
- start script php
- start command multiple
-
- # uncomment python to see it fail.
- #start script python
-
-last:
- start script fail require wait
-
-explode:
- start maintenance boom
+++ /dev/null
-# fss-0005
-
-settings:
- control controller/run/up.socket
- pid ready
- pid_file controller/run/up.pid
-
-main:
- failsafe maintenance
-
- start script create_socket_path
-
- ready
-
-maintenance:
- start maintenance boom
+++ /dev/null
-# fss-0005
-
-main:
- timeout start 7
- timeout stop 7
- timeout kill 3
-
- failsafe explode
-
- start utility sleeper_1
- start utility sleeper_2
- start utility sleeper_3
-
-explode:
- start maintenance boom
+++ /dev/null
-# fss-0005
-#
-# This example shows how htop can be started during the exit process rather than the entry.
-# See the htop-alternate.entry example.
-
-main:
- failsafe "start top"
-
- consider serial s_5
- consider serial s_6
-
- stop serial s_4 asynchronous
- stop serial s_5 asynchronous
- stop serial s_6 asynchronous
-
- ready wait
-
- execute htop
-
-start top:
- execute top
+++ /dev/null
-# fss-0005
-
-main:
- consider serial s_1
- consider serial s_2
- consider serial s_3
- consider serial s_4
- consider serial s_5
- consider serial s_6
-
- stop serial s_1
-
- ready
+++ /dev/null
-# fss-0005
-
-main:
- timeout start 7
- timeout stop 7
- timeout kill 3
-
- failsafe boom
-
- stop service sshd
-
-boom:
- stop maintenance explode
+++ /dev/null
-# fss-000d
-#
-# Note: The example setting "limit nice 1 2" may cause this rule to fail if the user has insufficient privileges granted by ulimits or some other system security measure.
-#
-
-settings:
- name "Sleep 1 Seconds."
- nice 15
- limit nice 1 2
- on start need asynchronous sleep_10
-
-script:
- start echo "Sleeping 1: $(date -u), depends: 10"
-
-script:
- start sleep 1
-
-script:
- start echo "Slept 1: $(date -u)"
+++ /dev/null
-# fss-000d
-#
-# Note: The example setting "limit nice 1 2" may cause this rule to fail if the user has insufficient privileges granted by ulimits or some other system security measure.
-#
-
-settings:
- name "Sleep 10 Seconds."
- nice 15
- limit nice 1 2
-
-script:
- start echo "Sleeping 10: $(date -u), depends: none"
-
-script:
- start sleep 10
-
-script:
- start echo "Slept 10: $(date -u)"
+++ /dev/null
-# fss-000d
-#
-# Note: The example setting "limit nice 1 2" may cause this rule to fail if the user has insufficient privileges granted by ulimits or some other system security measure.
-#
-
-settings:
- name "Sleep 2 Seconds."
- nice 15
- limit nice 1 2
- on start need asynchronous sleep_10
-
-script:
- start echo "Sleeping 2: $(date -u), depends: 10"
-
-script:
- start sleep 2
-
-script:
- start echo "Slept 2: $(date -u)"
+++ /dev/null
-# fss-000d
-#
-# Note: The example setting "limit nice 1 2" may cause this rule to fail if the user has insufficient privileges granted by ulimits or some other system security measure.
-#
-
-settings:
- name "Sleep 3 Seconds."
- nice 15
- limit nice 1 2
- on start need asynchronous sleep_8
-
-script:
- start echo "Sleeping 3: $(date -u), depends: 8"
-
-script:
- start sleep 3
-
-script:
- start echo "Slept 3: $(date -u)"
+++ /dev/null
-# fss-000d
-#
-# Note: The example setting "limit nice 1 2" may cause this rule to fail if the user has insufficient privileges granted by ulimits or some other system security measure.
-#
-
-settings:
- name "Sleep 5 Seconds."
- nice 15
- limit nice 1 2
-
-script:
- start echo "Sleeping 5: $(date -u), depends: none"
-
-script:
- start sleep 5
-
-script:
- start echo "Slept 5: $(date -u)"
+++ /dev/null
-# fss-000d
-#
-# Note: The example setting "limit nice 1 2" may cause this rule to fail if the user has insufficient privileges granted by ulimits or some other system security measure.
-#
-
-settings:
- name "Sleep 8 Seconds."
- nice 15
- limit nice 1 2
-
-script:
- start echo "Sleeping 8: $(date -u), depends: none"
-
-script:
- start sleep 8
-
-script:
- start echo "Slept 8: $(date -u)"
+++ /dev/null
-# fss-000d
-
-settings:
- name "Run htop"
-
-command:
- start htop
-
- rerun start success delay 3000 max 3
+++ /dev/null
-# fss-000d
-
-settings:
- name "Multiple Commands: id, whoami, date, etc.."
- capability "all="
- control_group new memory/example
- nice 15
- scheduler batch 0
- #user kevin
- #group list 8 root
-
- limit nofile 5000 10000
- limit nproc 1000 2000
- limit nice 1 2
-
- affinity 0
-
- on start need script require_me
-
-script:
- start {
- echo
- echo "Current ulimit is"
- ulimit -a
- sleep 5
-
- echo
- echo "Current cgroup for self (PPID $PPID, PID $$) is: '$(cat /proc/self/cgroup)'"
- sleep 5
- }
-
-command:
- start {
- id
- sleep 5
- }
-
-script:
- start echo
-
-command:
- start whoami
-
-script:
- start echo
-
-command:
- start sleep 5
-
-command:
- start date -u
-
-script:
- start echo
-
-script:
- start sleep 5
+++ /dev/null
-# fss-000d
-#
-# Rule for a long delay.
-#
-
-settings:
- name "Delay for 3 minutes."
-
-script:
- start sleep 3m
+++ /dev/null
-# fss-000d
-#
-# Rule for a short delay.
-#
-
-settings:
- name "Delay for 3 seconds."
-
-script:
- start sleep 3s
+++ /dev/null
-# fss-000d
-#
-# Note: bash automatically creates PWD, SHLVL, and _ environment variables.
-#
-
-settings:
- name "Environment default"
- engine bash
-
-script:
- start {
- echo
- echo "==================================="
- echo "Environment using default settings."
- echo "==================================="
-
- env
- }
+++ /dev/null
-# fss-000d
-#
-# Note: bash automatically creates PWD, SHLVL, and _ environment variables.
-#
-
-settings:
- name "Environment set to nothing"
- environment
- engine bash
-
-script:
- start {
- echo
- echo "============================="
- echo "Environment allowing nothing."
- echo "============================="
-
- env
- }
+++ /dev/null
-# fss-000d
-#
-# Note: bash automatically creates PWD, SHLVL, and _ environment variables.
-#
-
-settings:
- name "Environment with PATH"
- environment PATH
- engine bash
-
-script:
- start {
- echo
- echo "=========================="
- echo "Environment allowing PATH."
- echo "=========================="
-
- env
- }
+++ /dev/null
-# fss-000d
-#
-# Note: bash automatically creates PWD, SHLVL, and _ environment variables.
-#
-
-settings:
- name "Environment with PATH"
- environment PATH custom_variable
- engine bash
-
-script:
- start {
- echo
- echo "================================="
- echo "Exported Environment is isolated."
- echo "================================="
-
- export custom_variable="is not retained"
- echo "export custom_variable='$custom_variable'"
- echo
- echo "Now for 'env' command:"
- }
-
-command:
- start env
+++ /dev/null
-# fss-000d
-
-settings:
- name "Environment using fake as an engine"
- engine fake ++quiet
-
- # PATH must be expoted so that "run env" works.
- environment PATH
-
-script:
- start {
- settings\:
- environment
-
- main\:
- print
- print "========================================"
- print "Environment allowing nothing using fake."
- print "========================================"
-
- run env
- }
+++ /dev/null
-# fss-000d
-
-settings:
- name "Environment using fake as an engine"
- engine fake ++quiet
-
- environment PATH PWD
-
-script:
- start {
- main\:
- print
- print "============================================="
- print "Environment allowing PATH and PWD using fake."
- print "============================================="
-
- run env
- }
+++ /dev/null
-# fss-000d
-
-settings:
- name "Explosion!"
- engine sh
-
-script:
- start {
- echo "kaboooom!"
- }
-
+++ /dev/null
-# fss-000d
-
-settings:
- name "Print New Line"
- engine bash
-
-script:
- start echo
+++ /dev/null
-# fss-000d
-
-settings:
- name "Create Socket Path"
-
- parameter verbose -v
- parameter socket controller/run/
-
-script:
- start {
- if [[ ! -d "parameter:"socket"" ]] ; then
- mkdir parameter:"verbose" -p parameter:"socket"
- fi
- }
+++ /dev/null
-# fss-000d
-
-settings:
- name "Script #2"
- on start need script succeed
-
-script:
- start {
- \#!/bin/bash
- my_function() {
- echo "Hello this is the last script, it should trigger failure."
- return 1;
- \}
-
- my_function
- }
+++ /dev/null
-# fss-000d
-
-settings:
- name "IKI Variable Substitution"
- environment PATH IKI_TEST
- define IKI_TEST "This is iki data in an environment variable."
- parameter some "Some Parameter Value"
-
-script:
- start {
- \#!/bin/bash
- echo "====================================="
- env
- echo "====================================="
- echo "IKI Path is 'define:"PATH"'"
- echo "IKI define IKI_TEST 'define:"IKI_TEST"'"
- echo "ENV IKI_TEST '$IKI_TEST'"
- echo "Some Parameter is 'parameter:"some"'"
- echo "Unknown parameter is: 'parameter:"unknown"'"
- echo "Unknown environment is: 'define:"unknown"'"
- echo "Unavailable environment via IKI: 'define:"USER"'"
- echo "Unavailable environment via ENV: '$USER'"
- echo "Program parameter verbose: 'program:"verbose"'"
- echo "Program parameter verbose(option): 'program:"verbose:option"'"
- echo "Program parameter verbose(value): 'program:"verbose:value"'"
- echo "Program parameter PID: 'program:"pid"'"
- echo "Program parameter PID(option): 'program:"pid:option"'"
- echo "Program parameter PID(value): 'program:"pid:value"'"
- echo "====================================="
- }
+++ /dev/null
-# fss-000d
-
-settings:
- name "PHP script"
- environment PATH
- engine php
-
-script:
- start {
- <?php
- print("\nThis is a PHP script.\n\n");
-
- print(date("Y/m/d h:i:s a") . "\n\n");
-
- var_dump(getenv());
- print("\n");
-
- print("Now executing 'date -u' program, assuming that it exists in \$PATH.\n");
- passthru("date -u");
- print("\n");
- }
+++ /dev/null
-# fss-000d
-
-settings:
- name "Python (Version 3.X) script"
- environment PATH
- engine python3
-
-script:
- start {
- # Python's indentation design presents problems here and this will likely fail with "IndentationError: unexpected indent"
- print("This is a Python script.\n");
-
- # this is simply a design flaw of Python and as such Python scripts must not be tabbed over (making these files less readable).
- }
+++ /dev/null
-# fss-000d
-
-settings:
- name "Example script for needs, wants, and wishes."
- environment PATH
- engine sh
-
-script:
- start {
- echo
- echo "This should be included via a need, want, or wish."
- echo
- }
-
+++ /dev/null
-# fss-000d
-
-settings:
- name "Script #1"
- environment PATH
- engine sh
-
-script:
- start {
- echo
- echo "Hello this is script #1 and should succeed."
- echo
-
- date -u
- echo
- }
-
+++ /dev/null
-# fss-000d
-
-settings:
- name "Serial 1"
- on stop need serial s_2
-
-script:
- start {
- echo "Serial 1: sleeping $(date -u)"
- sleep 1
- echo "Serial 1: slept $(date -u)"
- }
-
- stop {
- echo "Serial 1: stopping, sleeping $(date -u)"
- sleep 1
- echo "Serial 1: stopping, slept $(date -u)"
- }
+++ /dev/null
-# fss-000d
-
-settings:
- name "Serial 2"
- on start need serial s_1
- on stop need serial s_3
-
-script:
- start {
- echo "Serial 2: sleeping $(date -u)"
- sleep 1
- echo "Serial 2: slept $(date -u)"
- }
-
- stop {
- echo "Serial 2: stopping, sleeping $(date -u)"
- sleep 1
- echo "Serial 2: stopping, slept $(date -u)"
- }
+++ /dev/null
-# fss-000d
-
-settings:
- name "Serial 3"
- on start need serial s_2
- on stop need serial s_4
-
-script:
- start {
- echo "Serial 3: sleeping $(date -u)"
- sleep 1
- echo "Serial 3: slept $(date -u)"
- }
-
- stop {
- echo "Serial 3: stopping, sleeping $(date -u)"
- sleep 1
- echo "Serial 3: stopping, slept $(date -u)"
- }
+++ /dev/null
-# fss-000d
-
-settings:
- name "Serial 4"
- on start need serial s_3
- on stop need serial s_5
-
-script:
- start {
- echo "Serial 4: sleeping $(date -u)"
- sleep 1
- echo "Serial 4: slept $(date -u)"
- }
-
- stop {
- echo "Serial 4: stopping, sleeping $(date -u)"
- sleep 1
- echo "Serial 4: stopping, slept $(date -u)"
- }
+++ /dev/null
-# fss-000d
-
-settings:
- name "Serial 5"
- on start need serial s_4
- on stop need serial s_6
-
-script:
- start {
- echo "Serial 5: sleeping $(date -u)"
- sleep 1
- echo "Serial 5: slept $(date -u)"
- }
-
- stop {
- echo "Serial 5: stopping, sleeping $(date -u)"
- sleep 1
- echo "Serial 5: stopping, slept $(date -u)"
- }
+++ /dev/null
-# fss-000d
-
-settings:
- name "Serial 6"
- on start need serial s_5
-
-script:
- start {
- echo "Serial 6: sleeping $(date -u)"
- sleep 1
- echo "Serial 6: slept $(date -u)"
- }
-
- stop {
- echo "Serial 6: stopping, sleeping $(date -u)"
- sleep 1
- echo "Serial 6: stopping, slept $(date -u)"
- }
+++ /dev/null
-# fss-000d
-#
-# Example using the common sshd service.
-# Sshd appears to require a full path.
-#
-
-settings:
- name "SSH Service"
- nice 15
-
-service:
- pid_file /var/run/sshd.pid
- with full_path
- start sshd
+++ /dev/null
-# fss-000d
-# sleeper rule whose program creates its own PID file, runs in the background, sleep for a while, removes PID file, and returns.
-
-settings:
- name "Sleeper #1"
- nice 10
-
-utility:
- pid_file /tmp/sleeper_1.pid
- start {
- \#!/bin/bash
-
- main() {
- if [[ -f /tmp/sleeper_1.pid ]] ; then
- echo "Failure: pid file '/tmp/sleeper_1.pid' already exists."
- return 1
- fi
-
- echo "$BASHPID" > /tmp/sleeper_1.pid
-
- echo "Sleeper 1, now sleeping."
- sleep 20m
-
- echo "Sleeper 1, done sleeping."
- rm -f /tmp/sleeper_1.pid
- return 0
- \}
-
- main &
- }
+++ /dev/null
-# fss-000d
-# sleeper rule whose program creates its own PID file, runs in the background, sleep for a while, removes PID file, and returns.
-
-settings:
- name "Sleeper #2"
- nice 10
-
-utility:
- pid_file /tmp/sleeper_2.pid
- start {
- \#!/bin/bash
-
- main() {
- if [[ -f /tmp/sleeper_2.pid ]] ; then
- echo "Failure: pid file '/tmp/sleeper_2.pid' already exists."
- return 1
- fi
-
- echo "$BASHPID" > /tmp/sleeper_2.pid
-
- echo "Sleeper 2, now sleeping."
- sleep 25m
-
- echo "Sleeper 2, done sleeping."
- rm -f /tmp/sleeper_2.pid
- return 0
- \}
-
- main &
- }
+++ /dev/null
-# fss-000d
-# sleeper rule whose program creates its own PID file, runs in the background, sleep for a while, removes PID file, and returns.
-
-settings:
- name "Sleeper #2"
- nice 10
-
-utility:
- pid_file /tmp/sleeper_3.1.pid
- start {
- \#!/bin/bash
-
- main() {
- if [[ -f /tmp/sleeper_3.1.pid ]] ; then
- echo "Failure: pid file '/tmp/sleeper_3.1.pid' already exists."
- return 1
- fi
-
- echo "$BASHPID" > /tmp/sleeper_3.1.pid
-
- echo "Sleeper 3.1, now sleeping."
- sleep 15
-
- echo "Sleeper 3.1, done sleeping."
- rm -f /tmp/sleeper_3.1.pid
- return 0
- \}
-
- main &
- }
-
-utility:
- pid_file /tmp/sleeper_3.2.pid
- start {
- \#!/bin/bash
-
- main() {
- if [[ -f /tmp/sleeper_3.2.pid ]] ; then
- echo "Failure: pid file '/tmp/sleeper_3.2.pid' already exists."
- return 1
- fi
-
- echo "$BASHPID" > /tmp/sleeper_3.2.pid
-
- echo "Sleeper 3.2, now sleeping."
- sleep 20
-
- echo "Sleeper 3.2, done sleeping."
- rm -f /tmp/sleeper_3.2.pid
- return 0
- \}
-
- main &
- }
+++ /dev/null
-# fss-000d
-#
-# Rule for initializing the /dev file system.
-#
-
-settings:
- name "Setup /dev file system"
-
- on start need boot root
-
-# Newer kernels automount a devpts file system on /dev, so this may not be needed.
-#command:
-# start mount /dev
-
-script:
- start {
- if [[ ! -d /dev/pts ]] ; then
- mkdir /dev/pts
- fi
-
- if [[ ! -d /dev/shm ]] ; then
- mkdir /dev/shm
- fi
-
- exit 0
- }
-
-command:
- start mount /dev/pts
- stop umount -l /dev/pts
-
-command:
- start mount /dev/shm
- stop umount -l /dev/shm
+++ /dev/null
-# fss-000d
-#
-# Rule for initializing the filesystem.
-#
-
-settings:
- name "Setup Filesystem"
-
- on start need boot root
- on start need boot proc
- on start need boot devices
-
- on stop need boot proc
- on stop need boot devices
-
-command:
- start mount -n -a -O no_netdev
- stop umount -n -arf -O no_netdev
-
-command:
- start swapon -a
- stop swapoff -a
-
-script:
- start {
- if [[ ! -d /var/run/init ]] ; then
- mkdir /var/run/init
- fi
- }
+++ /dev/null
-# fss-000d
-#
-# Rule for initializing the kernel modules.
-#
-
-settings:
- name "Setup Kernel Modules"
-
- on start need boot root
- on start need boot proc
- on start want boot filesystem
-
-script:
- start {
- if [[ ! -f /proc/modules ]] ; then
- exit 0
- fi
-
- if [[ -d /modules ]] ; then
- if [[ ! -e /modules/$(uname -r)/modules.dep ]] ; then
- depmod
- else
- depmod -A
- fi
- fi
-
- exit 0
- }
+++ /dev/null
-# fss-000d
-#
-# Rule for initializing the /proc filesystem.
-#
-
-settings:
- name "Setup /proc Filesystem"
-
- on start need boot root
-
-command:
- start mount /proc
-
-script:
- start {
- if [[ -d /proc/bus/usb ]] ; then
- mount /proc/bus/usb
- fi
-
- exit 0
- }
-
- stop {
- if [[ -d /proc/bus/usb ]] ; then
- umount -l /proc/bus/usb
- fi
-
- exit 0
- }
+++ /dev/null
-# fss-000d
-#
-# Rule for initializing the root filesystem, assuring certain directories always exist.
-#
-
-settings:
- name "Setup Root Filesystem"
-
-command:
- start mount -o remount,rw /
-
-script:
- start {
- if [[ ! -d /dev ]] ; then
- mkdir /dev
- fi
-
- if [[ ! -d /dev/pts ]] ; then
- mkdir /dev/pts
- fi
-
- if [[ ! -d /dev/shm ]] ; then
- mkdir /dev/shm
- fi
-
- if [[ ! -d /firmware ]] ; then
- mkdir /firmware
- fi
-
- if [[ ! -d /mnt ]] ; then
- mkdir /mnt
- fi
-
- if [[ ! -d /modules ]] ; then
- mkdir /modules
- fi
-
- if [[ ! -d /proc ]] ; then
- mkdir /proc
- fi
-
- if [[ ! -d /sys ]] ; then
- mkdir /sys
- fi
-
- if [[ ! -d /tmp ]] ; then
- mkdir /tmp
- fi
-
- if [[ ! -d /var ]] ; then
- mkdir /var
- fi
-
- if [[ ! -d /var/log ]] ; then
- mkdir /var/log
- fi
-
- if [[ ! -d /var/run ]] ; then
- mkdir /var/run
- fi
-
- if [[ ! -d /var/tmp ]] ; then
- mkdir /var/tmp
- fi
-
- exit 0
- }
+++ /dev/null
-# fss-000d
-#
-# Rule for maintenance/failsafe console.
-#
-
-settings:
- name "Maintenance Console"
-
-command:
- #start setsid -c bash --login
- start bash --login
-
- with session
+++ /dev/null
-# fss-000d
-#
-# Rule for starting all network devices.
-#
-
-settings:
- name "System Network"
- capability cap_net_admin=
-
-command:
- start network start
- stop network stop
- restart network restart
+++ /dev/null
-# fss-000d
-#
-# Rule for loopback device.
-#
-
-settings:
- name "Loopback Device"
-
- on start need boot modules
-
-script:
- start {
- ip addr add 127.0.0.1/8 label lo dev lo
- ip link set lo up
- }
-
- stop {
- ip link set lo down
- }
+++ /dev/null
-# fss-000d
-#
-# Rule for D-Bus service.
-#
-
-settings:
- name "D-BUS"
- capability all=
- nice 15
-
-service:
- pid_file /var/run/dbus/dbus.pid
-
- start dbus-daemon --system --fork
+++ /dev/null
-# fss-000d
-#
-# Rule for system logger service.
-#
-
-settings:
- name "System Logger"
- capability all=
- nice 19
- scheduler idle
-
-service:
- # @todo consider adding support for IKI to make "/var/run/logger/logger.pid" a variable.
- pid_file /var/run/logger/logger.pid
-
- start metalog -B -p /var/run/logger/logger.pid -C /etc/logger.conf
+++ /dev/null
-# fss-000d
-#
-# Rule for console mouse.
-#
-
-settings:
- name "Console Mouse"
- capability all=
- nice 15
-
-script:
- start {
- # This works if gpm service is run as root, but if not then this should be in a separate rule file with appropriate access to write to /var/run (don't forget to chown!).
- if [[ ! -d /var/run/mouse/ && -d /var/run ]] ; then
- mkdir /var/run/mouse/
- fi
- }
-
-service:
- pid_file /var/run/mouse/mouse.pid
-
- # @todo consider a new type, such as "variable" than can be used to get the variable and store it in an iki parseable variable.
- # This, however, may be too complicated than desirable (in terms of passing output back to the parent process).
- # such as:
- #variable device command fss_basic_read -can 0 device /etc/mouse
- #variable protocal script {
- # fss_basic_read -can 0 device /etc/mouse
- #}
- #variable options set ""
-
- # @todo
- start gpm -m variable:"device" -t variable:"protocol" variable:"options"
+++ /dev/null
-# fss-000d
-#
-# Rule for setting the clock.
-#
-
-settings:
- name "Setup Clock"
- capability cap_sys_time=
- nice 15
-
- on start want boot filesystem
- on start want net all
-
-script:
- start {
- clock_file=/etc/clock
- clock_mode=
- clock_server=
- clock_ntpdate=
-
- if [[ -f $clock_file ]] ; then
- clock_mode=$(fss_basic_read -can 0 mode $clock_file);
- clock_server=$(fss_basic_read -can 0 server $clock_file)
- clock_ntpdate=$(fss_basic_read -can 0 ntpdate $clock_file)
- fi
-
- if [[ $clock_mode == "local" ]] ; then
- hwclock --hctosys;
- elif [[ $clock_mode == "ntp" ]] ; then
- if [[ $clock_ntpdate == "yes" ]] ; then
- ntpdate $clock_server &&
- hwclock --systohc --utc
- fi
- elif [[ $clock_mode == "ntpdate" && $clock_host != "" ]] ; then
- ntpdate $clock_server
- elif [[ $clock_mode == "utc" ]] ; then
- hwclock --hctosys --utc;
- fi
- }
+++ /dev/null
-# fss-000d
-#
-# Rule for setting the keyboard.
-#
-
-settings:
- name "System Keyboard"
- nice 15
+++ /dev/null
-# fss-000d
-#
-# Rule for executing ntpdate.
-#
-
-settings:
- name "System Clock Using NTP Date"
- capability cap_sys_time=
- nice 15
-
- on start want boot filesystem
- on start need net all
-
-script:
- start {
- clock_file=/etc/clock
- clock_mode=
- clock_server=
-
- if [[ -f $clock_file ]] ; then
- clock_mode=$(fss_basic_read -can 0 mode $clock_file);
- clock_server=$(fss_basic_read -can 0 server $clock_file)
- fi
-
- if [[ $clock_mode == "ntpdate" && $clock_host != "" ]] ; then
- ntpdate $clock_server
- fi
- }
+++ /dev/null
-# fss-000d
-#
-# Rule for the terminal programs.
-#
-# -m = don't prompt for login.
-# -J = don't clear on start, good for debugging.
-# 9600 and 115200 are common frequencies.
-
-settings:
- name "System Terminal 4"
-
-command:
- start agetty -8 tty4 linux
-
- rerun start success delay 1000 reset
- rerun start failure delay 5000 max 100
+++ /dev/null
-# fss-000d
-#
-# Rule for the terminal programs.
-#
-# -m = don't prompt for login.
-# -J = don't clear on start, good for debugging.
-# 9600 and 115200 are common frequencies.
-
-settings:
- name "System Terminal 1"
-
-command:
- start agetty -8 -i -J - linux
-
- rerun start success delay 1000 reset
- rerun start failure delay 5000
+++ /dev/null
-# fss-000d
-#
-# Rule for the terminal programs.
-#
-# -m = don't prompt for login.
-# -J = don't clear on start, good for debugging.
-# 9600 and 115200 are common frequencies.
-
-settings:
- name "System Terminal 3"
-
-command:
- start agetty -8 tty3 linux
-
- rerun start success delay 1000 reset
- rerun start failure delay 5000 max 100
+++ /dev/null
-# fss-000d
-#
-# Rule for the terminal programs.
-#
-# -m = don't prompt for login.
-# -J = don't clear on start, good for debugging.
-# 9600 and 115200 are common frequencies.
-
-settings:
- name "System Terminal 2"
-
-command:
- start agetty -8 tty2 linux
-
- rerun start success delay 1000 reset
- rerun start failure delay 5000 max 100
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: open-standard-license-1.0-or-later
-# version 2024/07/02
-#
-# This file (assumed to be named actions.txt) can be more easily read using the following iki_read commands:
-# iki_read actions.txt +Q -w -W code '"' '"'
-#
-# To read the "Actions Documentation" section of this file, use this command sequence:
-# fss_basic_list_read actions.txt +Q -cn "Actions Documentation" | iki_read +Q -w -W code '"' '"'
-#
-
-Actions Documentation:
- This describes the intent and purpose of the actions provided for individual Rules (or things related to a Rule).
-
- Each Action represents a specific intent and purpose but many of these actions are customizable via the rule file.
- One should expect an Action to operate as described here but the system administrator or distributor is fully capable of doing something different.
- For those doing something different, appropriate documentation is suggested.
-
- These actions should be usable by any code:"control" program that communicates with this code:"controller" program.
- Should any code:"control" or code:"controller" program implementation not support any particular Action for any reason, one should report that the Action is unsupported.
-
- - Freeze Action\:
- The Freeze Action is an extension of a Control Group.
- This is internal to the code:"controller" program and is not customizable via any Rule file.
- For a customizable code:"freeze"-like capability, look into the Pause and Resume Actions.
- This is the complement of the Thaw Action.
-
- This designates that a processes Control Group is to be frozen.
- All Rules (or any process not controlled by the code:"controller") that is within the same Control Group will be frozen.
- (@todo consider instead designing this around the Control Groups instead of a code:"rule".)
- (This documentation will likely change with consideration to the above @todo once this gets implemented.)
-
- This must not attempt to freeze (or unfreeze) the Control Group that the code:"controller" belongs to.
- Therefore, if a Rule does not specify a Control Group, then it is likely that the Freeze Action will be unsupported for that Rule/Control Group.
-
- - Kill Action\:
- Forcefully terminate some process controlled by the code:"controller".
- This action cannot be blocked and it is recommended to use a Stop Action instead for a more proper termination.
-
- - Pause Action\:
- The Pause Action will pause (or freeze) the process controlled by the Rule.
- Although similar to the Freeze Action, this is intended to communicate to an individual process and inform to Pause.
- This is complemented by the Resume Action.
-
- - Restart Action\:
- The Restart Action will either perform a Stop Action and then a Restart Action or it will perform the Restart Action designated in some Rule file.
- Ideally this should inform some process to perform its own restart routines.
-
- - Resume Action\:
- The Resume Action will unpause (or unfreeze) the process controlled by the Rule.
- Although similar to the Thaw Action, this is intended to communicate to an individual process and inform to Resume.
- This is complemented by the Pause Action.
-
- - Reload Action\:
- The Reload Action will perform the Reload Action designated in some Rule file.
- Ideally this should inform some process to perform its own reload routines.
- Many programs often differentiate the concept code:"reload" from the concept "restart" in that the program remains running during a code:"reload".
-
- - Start Action\:
- The Start Action will perform the Start Action designated in some Rule file.
- This action should be used to start some program or script.
- This is the action called by Entry file.
- This is complemented by the Stop Action.
-
- - Stop Action\:
- The Stop Action will perform the Stop Action designated in some Rule file.
- This action should be used to stop some program or script.
- This is the action called for all running controlled processes on shutdown.
- This is complemented by the Start Action.
-
- - Thaw Action\:
- The Thaw Action is an extension of a Control Group.
- This is internal to the code:"controller" program and is not customizable via any Rule file.
- For a customizable code:"thaw"-like capability, look into the code:"pause" and code:"resume" Actions.
- This is complemented by the Freeze Action.
-
- This designates that a processes Control Group is to be unfrozen.
- All Rules (or any process not controlled by the code:"controller") that is within the same Control Group will be unfrozen.
- (@todo consider instead designing this around the Control Groups instead of a code:"rule".)
- (This documentation will likely change with consideration to the above @todo once this gets implemented.)
-
- This must not attempt to thaw (or unthaw) the Control Group that the code:"controller" belongs to.
- Therefore, if a Rule does not specify a Control Group, then it is likely that the Thaw Action will be unsupported for that Rule/Control Group.
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: open-standard-license-1.0-or-later
-# version 2024/07/02
-#
-# This file (assumed to be named entry.txt) can be more easily read using the following iki_read commands:
-# iki_read entry.txt +Q -r PID PID -w -WW code '"' '"'
-#
-# To read the "Entry Documentation" section of this file, use this command sequence:
-# fss_basic_list_read entry.txt +Q -cn "Entry Documentation" | iki_read +Q -r PID PID -w -W code '"' '"'
-#
-
-Entry Documentation:
- This describes the intent and purpose of an Entry file.
-
- An Entry file, such as code:"default.entry", is intended to store a set of rules in which the controller will process on execution.
- These are used to run some set of commands, such as booting a system.
-
- The code:"main" Item Object is always executed first (Therefore code:"main" is both reserved and required).
- All other Basic List Objects are not executed unless either an code:"item" or a code:"failsafe" specifies a valid Item name.
- Execution of all Items is top-down.
-
- - The code:"settings" item Object\:
- Represents Entry settings and is not an code:"item" that can be executed.
- A number of settings are supported, but if this Item Object is not specified, then defaults are used.
- The following settings are available: code:"control", code:"control_group", code:"control_mode", code:"control_user", code:"define", code:"mode", code:"parameter", code:"pid", code:"pid_file", code:"session", code:"show".
-
- - The code:"control" setting\:
- Represents the path to the socket file in which the Controller uses to communicate over with clients such as a Control program.
- A relative path is relative to the Controller PID:"Process Identifier" directory.
- An absolute path is treated exactly as the path given.
- If no socket setting is specified, then no socket will be made available.
- This socket file is only created once code:"ready" mode is achieved.
-
- Providing code:"readonly" after the socket path instructs the Controller program not to create or delete the Socket file because the file system is assumed to be readonly.
- The socket file itself must therefore already exist.
- This should be possible in the cases of file systems that have pre-created a socket file at the designated path.
- When code:"readonly", the group, mode, and user are also not processed effectively resulting in the code:"control_group", code:"control_mode", and code:"control_user" settings being ignored.
-
- Future versions might expand this into supporting network addresses in addition to socket files.
-
- - The code:"control_group" setting\:
- Represents the group name or group ID to assign to the socket file as the group.
-
- - The code:"control_mode" setting\:
- Represents the file mode assigned to the socket file.
- This could either be the string version that might look like code:"u+rw-x,g+r-wx,o-rwx" or a numeric value like code:"0750".
-
- - The code:"control_user" setting\:
- Represents the user name or user ID to assign to the socket file as the owner.
-
- - The code:"define" setting\:
- Use this to define an environment variable (this overwrites any existing environment variable with this name).
- A define is both exported as an environment variable as well as exposed as an IKI variable.
- Example IKI variable substitution: for code:"define PATH /bin:/sbin", the associated IKI variable would look like: define:"PATH".
-
- All environment variables, including those defined using this, must be in the code:"environment" list in any given Rule to be exported to the executed process.
- Environment variables added here that are not added to the environment are still exposed as an IKI variable.
-
- This is only expanded within any Rule operated on by this Entry.
-
- - The code:"mode" setting\:
- Represents the mode in which the Entry is operating in.
- The following modes are supported: code:"helper", code:"program", and code:"service".
-
- - The code:"helper" mode\:
- Designates that the Entry operates as a helper for starting programs or performing actions and exits when complete.
- On exit, any background (asynchronous) processes are not cancelled.
- If terminated, the foreground (synchronous) process is cancelled.
- Will call the code:"exit" with the same name as this Entry, but with the extension code:"exit", such as code:"default.exit".
- Supports the Item Action code:"execute" to execute a program (switching the code:"controller" program entirely with the executed process).
-
- - The code:"program" mode\:
- Designates that the Entry operates as a program and exits when complete.
- On exit, any background (asynchronous) processes are also cancelled.
- If terminated, the foreground (synchronous) process is cancelled.
- Will call the code:"exit" with the same name as this Entry, but with the extension code:"exit", such as code:"default.exit".
- Supports the Item Action code:"execute" to execute a program (switching the code:"controller" program entirely with the executed process).
-
- - The code:"service" mode\:
- Designates that the Entry operates as a service and will sit and wait for control commands when complete.
- Will call the code:"exit" with the same name as this Entry, but with the extension code:"exit", such as code:"default.exit".
- Does not support the Item Action code:"execute".
- This is the default mode.
-
- - The code:"parameter" setting\:
- Use this to define an IKI variable name and value.
- These do not conflict with environment variables and are not exposed as environment variables.
- Example IKI variable substitution: for code:"parameter hello world", the associated IKI variable would look like: parameter:"hello".
-
- This is only expanded within any Rule operated on by this Entry.
-
- - The code:"pid" setting\:
- Represents how the Entry PID:"Process Identifier" file is generated or not.
- The following modes are supported: code:"disable", code:"require", and code:"ready".
- For code:"disable", not PID:"Process Identifier" file representing the Entry is created.
- For code:"require", check to see if the PID:"Process Identifier" file exists for an Entry at startup and then when code:"ready" create a PID:"Process Identifier" file, display error on PID:"Process Identifier" file already exists or on failure and then fail.
- For code:"ready", when code:"ready" create a PID:"Process Identifier" file, display error on failure and then fail (does not check if PID:"Process Identifier" file exists).
-
- - The code:"pid_file" setting\:
- When code:"pid" is not disabled this represents the path to the PID:"Process Identifier" file.
- If code:"-p" or code:"--pid" is passed to the controller program, then this value is ignored in favor of the value passed along the command line.
-
- - The code:"session" setting\:
- Represents the default way in which child processes are executed.
- This default can be overridden by individual Rules.
- For code:"new", Execute Rule processes in a new session setting the process group to the executed process' id (making the executed process a code:"controlling terminal").
- For code:"same", Execute Rule processes in the same session where the process group is set to the parent process id.
-
- - The code:"show" setting\:
- Represents the way Entry processing presents information to the screen.
- This applies only to the Entry and Rule processing itself and does not handle the output of programs and scripts being executed by some Entry or Rule.
- The following show options are supported: code:"normal" and code:"init".
- For code:"normal", will not report the start or stop of some Entry or Rule execution but will report any errors or warnings as appropriate.
- For code:"init", will report when starting programs and may include reporting success and failure status.
-
- - The code:"timeout" setting\:
- Represents the default timeouts for the Entry.
- See the code:"timeout" Action below for details.
-
- - The code:"main" item Object\:
- Each code:"item" supports the following Action Names: code:"consider", code:"execute", code:"failsafe", code:"freeze", code:"item", code:"kill", code:"pause", code:"reload", code:"restart", code:"ready", code:"resume", code:"start", code:"stop", and code:"timeout".
- Of those types, the following are considered a code:"rule" Action: code:"freeze", code:"kill", code:"pause", code:"reload", code:"restart", code:"resume", code:"start", code:"stop", and code:"thaw".
-
- - The code:"consider" Item Action\:
- A special case of a code:"rule" Action.
- All Action Parameters are the same as with the code:"rule" Action Parameters.
- The difference is that code:"consider" is only processed (instead of being processed and executed) and when some code:"rule" Action designates that this consideration is required (via code:"need"), wanted (via code:"want"), or wished for (via code:"wish") from the within the Rule file.
- If this is determined to be executed, then this is immediately executed when needed, wanted or wished for and applies all properties as appropriate (such as code:"asynchronous", for example).
- If this is determined not to be executed, then this code:"consider" is ignored as if it was never there in the first place.
-
- - The code:"execute" Item Action\:
- Execute into the specified program.
- On successful execution, the controller program will no longer be running and will be replaced with the designated program.
- This Item Action is only supported when operating in code:"program" mode.
-
- - The code:"failsafe" Item Action\:
- Accepts only a valid Item Name in which will be executed when a failure is detected.
- Only a single code:"failsafe" Item Action may function at a time.
- Each successive code:"failsafe" Item Action specified replaces the previously defined code:"failsafe" Item Action (in a top-down manner).
- When operating in code:"failsafe", the code:"require" Item Action is ignored (given that it is meaningless once operating in code:"failsafe" mode).
-
- - The code:"freeze" Item Action\:
- A code:"rule" Action for freezing some Control Group.
- This Item Action will process the code:"freeze" inner Content of the named Rule.
- This is specific to Control Groups and is not yet fully implemented.
- Once implemented this documentation will need to be updated and clarified.
-
- - The code:"item" Item Action\:
- Accepts only a valid Item Name in which will be immediately executed.
- Any valid Item Name, except for the reserved code:"main", may be used.
-
- - The code:"kill" Item Action\:
- A code:"rule" Action for forcibly terminating some process.
- This Item Action will process the code:"kill" inner Content of the named Rule.
-
- - The code:"pause" Item Action\:
- A code:"rule" Action for pausing some process.
- This Item Action will process the code:"pause" inner Content of the named Rule.
-
- - The code:"reload" Item Action\:
- A code:"rule" Action for pausing some process.
- This Item Action will process the code:"reload" inner Content of the named Rule.
-
- - The code:"restart" Item Action\:
- A code:"rule" Action for pausing some process.
- This Item Action will process the code:"restart" inner Content of the named Rule.
-
- - The code:"resume" Item Action\:
- A code:"rule" Action for pausing some process.
- This Item Action will process the code:"resume" inner Content of the named Rule.
-
- - The code:"ready" Item Action\:
- Instructs the controller program when it is safe to perform normal tasks, such as creating the PID:"Process Identifier" file.
- When not specified, the state is always assumed to be ready.
- For example, the controller program may be used as a full blown code:"init" replacement and therefore may need to mount the /var/run/ directory.
- If the PID:"Process Identifier" file is created at program start, then the /var/run/controller.pid would be written before the /var/run/ directory is ready.
- This could be a problem, such as on a read-only file system the PID:"Process Identifier" creation fails and controller bails out on error.
- Adding code:"ready" essentially specifies a point in time in the Entry in which things are expected to be safe for such basic operations.
- When the optional code:"wait" is provided, then code:"ready" will wait for all currently started asynchronous processes to complete before operating.
-
- - The code:"start" Item Action\:
- A code:"rule" Action for pausing some process.
- This Item Action will process the code:"start" inner Content of the named Rule.
-
- - The code:"stop" Item Action\:
- A code:"rule" Action for pausing some process.
- This Item Action will process the code:"stop" inner Content of the named Rule.
-
- - The code:"thaw" Item Action\:
- A code:"rule" Action for unfreezing some Control Group.
- This Item Action will process the code:"thaw" inner Content of the named Rule.
- This is specific to Control Groups and is not yet fully implemented.
- Once implemented this documentation will need to be updated and clarified.
-
- - The code:"timeout" Item Action\:
- (This is not currently fully implemented, only code:"exit" is implemented.)
- Provides default global settings for each of the four special situations: code:"exit", code:"kill", code:"start", and code:"stop".
- Each of these may only have a single one exist at a time (one code:"exit", one code:"kill", one code:"start", and one code:"stop").
- Each successive code:"timeout" Item Action, specific to each Action Name (such as code:"start"), specified replaces the previously defined code:"timeout" Action (in a top-down manner).
- The second Content for each of these, when specified, may be a 0 or greater whole number representing the number of MegaTime (MT) (equivalent to milliseconds).
- For code:"kill", this represents the number of MegaTime to wait after stopping some Rule and that Rule has not yet stopped to forcefully stop the Rule (aka kill the Rule).
- For code:"start", this represents the number of MegaTime to wait after starting some Rule before assuming something went wrong and the Rule is returned as failed.
- For code:"stop", this represents the number of MegaTime to wait after stopping some Rule before assuming something went wrong and the Rule is returned as failed.
- If the second Content is not specified, then this disables the type (prevents the specified timeout action).
- For code:"exit", this represents the number of MegaTime to wait when the Controller program is exiting (such as having received a terminate signal).
- In this case, a terminate signal is sent to all child processes.
- The code:"exit" timeout represents the amount of time to wait after sending the terminate signal before sending a kill signal to each child process still running.
- When disabled, the program will not send a kill signal will continue running until all child processes to terminate.
- The code:"exit" timeout does not get applied to any Rule.
-
-Entry Rule Documentation:
- There are multiple Entry Actions that are considered code:"rule" Actions.
- These are: code:"freeze", code:"kill", code:"pause", code:"reload", code:"restart", code:"resume", code:"start", code:"stop", and code:"thaw".
-
- The code:"rule" Actions immediately execute a named Rule file.
- - The first Action Parameter represents the Rule directory, which is a relative directory path the Rule file is to be found.
- - Do not include leading or trailing slashes.
- - This is relative to the settings rules directory.
-
- - The second Action Parameter represents the base name for the Rule file, without the file extension.
- - This must not have any directory paths.
-
- - The remaining Action Parameters may be specified in any order\:
- - code:"asynchronous": Designates that execution will not block (wait).
- - code:"require": Designates that this Rule must succeed or trigger execution of failsafe.
- - code:"wait": Designates that this Rule will not execute until all other Actions before this (including code:"asynchronous" ones) finish executing (in a top-down manner).
-
- The full path to the code:"rule" is relative to the settings, such that if the controller Rule settings are found in code:"/etc/controller/rules/", then for a directory called code:"[directory]" and a Rule base name of code:"[base_name]", the resulting path would be: code:"/etc/controller/rules/[directory]/[base_name].rule".
-
- It is important to note that for any given code:"rule", execution within that code:"rule" may be internally asynchronous (even if the code:"rule" is synchronous).
- For example, a service that is often called a daemon will execute in the background.
- Until that execution succeeds and the daemon goes into the background the representing Rule will block.
- After the daemon goes into the background, then the representing Rule will no longer block and be fully executed.
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: open-standard-license-1.0-or-later
-# version 2024/07/02
-#
-# This file (assumed to be named exit.txt) can be more easily read using the following iki_read commands:
-# iki_read exit.txt +Q -w -r PID PID -w -W code '"' '"'
-#
-# To read the "Exit Documentation" section of this file, use this command sequence:
-# fss_basic_list_read exit.txt +Q -cn "Exit Documentation" | iki_read +Q -r PID PID -w -W code '"' '"'
-#
-
-Exit Documentation:
- This describes the intent and purpose of an Exit file.
-
- An Exit file, such as code:"default.exit", is intended to store a set of rules in which the controller will process on execution.
- These are used to run some set of commands, such as shutting down a system.
-
- An Exit is a special variation or subset of an Entry.
-
- - The code:"settings" Item Object\:
- Represents Exit settings and is not an code:"item" that can be executed.
- A number of settings are supported, but if this Item Object is not specified, then defaults are used.
- The following settings are available: code:"pid" and code:"show".
-
- - The code:"define" setting\:
- Use this to define an environment variable (this overwrites any existing environment variable with this name).
- A define is both exported as an environment variable as well as exposed as an IKI variable.
- Example IKI variable substitution: for code:"define PATH /bin:/sbin", the associated IKI variable would look like: define:"PATH".
-
- All environment variables, including those defined using this, must be in the code:"environment" list in any given Rule to be exported to the executed process.
- Environment variables added here that are not added to the environment are still exposed as an IKI variable.
-
- This is only expanded within any Rule operated on by this Exit.
-
- - The code:"parameter" setting\:
- Use this to define an IKI variable name and value.
- These do not conflict with environment variables and are not exposed as environment variables.
- Example IKI variable substitution: for code:"parameter hello world", the associated IKI variable would look like: parameter:"hello".
-
- This is only expanded within any Rule operated on by this Exit.
-
- - The code:"pid" setting\:
- Represents how the Exit PID:"Process Identifier" file is generated or not.
- The following modes are supported: code:"disable", code:"require", and code:"ready".
- For code:"disable", not PID:"Process Identifier" file representing the Exit is created.
- For code:"require", check to see if the PID:"Process Identifier" file exists for an Exit at startup and then when code:"ready" create a PID:"Process Identifier" file, display error on PID:"Process Identifier" file already exists or on failure and then fail.
- For code:"ready", when code:"ready" create a PID:"Process Identifier" file, display error on failure and then fail (does not check if PID:"Process Identifier" file exists).
-
- - The code:"show" setting\:
- Represents the way Exit processing presents information to the screen.
- This applies only to the Exit and Rule processing itself and does not handle the output of programs and scripts being executed by some Exit or Rule.
- The following show options are supported: code:"normal" and code:"init".
- For code:"normal", will not report the start or stop of some Exit or Rule execution but will report any errors or warnings as appropriate.
- For code:"init", will report when starting programs and may include reporting success and failure status.
-
- - The code:"timeout" setting\:
- Represents the default timeouts for the Exit.
- See the code:"timeout" Action below for details.
-
- - The code:"main" Item Object\:
- Is always executed first (Therefore code:"main" is both reserved and required).
- All other Basic List Objects are not executed unless either an code:"item" or a code:"failsafe" specifies a valid Item name.
- Execution of all Items are top-down.
-
- Each code:"item" supports the following Action Names: code:"consider", code:"execute", code:"failsafe", code:"freeze", code:"item", code:"kill", code:"pause", code:"reload", code:"restart", code:"ready", code:"resume", code:"start", code:"stop", and code:"timeout".
- Of those types, the following are considered a code:"rule" Action: code:"freeze", code:"kill", code:"pause", code:"reload", code:"restart", code:"resume", code:"start", code:"stop", and code:"thaw".
-
- - The code:"consider" Item Action\:
- A special case of a code:"rule" Action.
- All Action Parameters are the same as with the code:"rule" Action Parameters.
- The difference is that code:"consider" is only processed (instead of being processed and executed) and when some code:"rule" Action designates that this consideration is required (via code:"need"), wanted (via code:"want"), or wished for (via code:"wish") from the within the Rule file.
- If this is determined to be executed, then this is immediately executed when needed, wanted or wished for and applies all properties as appropriate (such as code:"asynchronous", for example).
- If this is determined not to be executed, then this code:"consider" is ignored as if it was never there in the first place.
-
- - The code:"execute" Item Action\:
- Execute into the specified program.
- On successful execution, the controller program will no longer be running and will be replaced with the designated program.
- This Item Action is only supported when operating in code:"program" mode.
-
- - The code:"failsafe" Item Action\:
- Accepts only a valid Item Name in which will be executed when a failure is detected.
- Only a single code:"failsafe" Item Action may function at a time.
- Each successive code:"failsafe" Item Action specified replaces the previously defined code:"failsafe" Item Action (in a top-down manner).
- When operating in code:"failsafe", the code:"require" Item Action is ignored (given that it is meaningless once operating in code:"failsafe" mode).
-
- - The code:"freeze" Item Action\:
- A code:"rule" Action for freezing some Control Group.
- This Item Action will process the code:"freeze" inner Content of the named Rule.
- This is specific to Control Groups and is not yet fully implemented.
- Once implemented this documentation will need to be updated and clarified.
-
- - The code:"item" Item Action\:
- Accepts only a valid Item Name in which will be immediately executed.
- Any valid Item Name, except for the reserved code:"main", may be used.
-
- - The code:"kill" Item Action\:
- A code:"rule" Action for forcibly terminating some process.
- This Item Action will process the code:"kill" inner Content of the named Rule.
-
- - The code:"pause" Item Action\:
- A code:"rule" Action for pausing some process.
- This Item Action will process the code:"pause" inner Content of the named Rule.
-
- - The code:"reload" Item Action\:
- A code:"rule" Action for pausing some process.
- This Item Action will process the code:"reload" inner Content of the named Rule.
-
- - The code:"restart" Item Action\:
- A code:"rule" Action for pausing some process.
- This Item Action will process the code:"restart" inner Content of the named Rule.
-
- - The code:"resume" Item Action\:
- A code:"rule" Action for pausing some process.
- This Item Action will process the code:"resume" inner Content of the named Rule.
-
- - The code:"ready" Action\:
- Instructs the controller program when it is safe to perform normal tasks, such as creating the PID:"Process Identifier" file.
- When not specified, the state is always assumed to be ready.
- For example, the controller program may be used as a full blown code:"init" replacement and therefore may need to mount the /var/run/ directory.
- If the PID:"Process Identifier" file is created at program start, then the /var/run/controller.pid would be written before the /var/run/ directory is ready.
- This could be a problem, such as on a read-only file system the PID:"Process Identifier" creation fails and controller bails out on error.
- Adding code:"ready" essentially specifies a point in time in the Exit in which things are expected to be safe for such basic operations.
- When the optional code:"wait" is provided, then code:"ready" will wait for all currently started asynchronous processes to complete before operating.
-
- - The code:"start" Item Action\:
- A code:"rule" Action for pausing some process.
- This Item Action will process the code:"start" inner Content of the named Rule.
-
- - The code:"stop" Item Action\:
- A code:"rule" Action for pausing some process.
- This Item Action will process the code:"stop" inner Content of the named Rule.
-
- - The code:"thaw" Item Action\:
- A code:"rule" Action for unfreezing some Control Group.
- This Item Action will process the code:"thaw" inner Content of the named Rule.
- This is specific to Control Groups and is not yet fully implemented.
- Once implemented this documentation will need to be updated and clarified.
-
- - The code:"timeout" Item Action\:
- (This is not currently fully implemented, only code:"exit" is implemented.)
- Provides default global settings for each of the four special situations: code:"exit", code:"kill", code:"start", and code:"stop".
- Each of these may only have a single one exist at a time (one code:"exit", one code:"kill", one code:"start", and one code:"stop").
- Each successive code:"timeout" Item Action, specific to each Action Name (such as code:"start"), specified replaces the previously defined code:"timeout" Action (in a top-down manner).
- The second Content for each of these, when specified, may be a 0 or greater whole number representing the number of MegaTime (MT) (equivalent to milliseconds).
- For code:"kill", this represents the number of MegaTime to wait after stopping some Rule and that Rule has not yet stopped to forcefully stop the Rule (aka kill the Rule).
- For code:"start", this represents the number of MegaTime to wait after starting some Rule before assuming something went wrong and the Rule is returned as failed.
- For code:"stop", this represents the number of MegaTime to wait after stopping some Rule before assuming something went wrong and the Rule is returned as failed.
- If the second Content is not specified, then this disables the type (prevents the specified timeout action).
-
- For code:"exit", this represents the number of MegaTime to wait when the Controller program is exiting (such as having received a terminate signal).
- In this case, a terminate signal is sent to all child processes.
- The code:"exit" timeout represents the amount of time to wait after sending the terminate signal before sending a kill signal to each child process still running.
- When disabled, the program will not send a kill signal will continue running until all child processes to terminate.
- The code:"exit" timeout does not get applied to any Rule.
-
-Exit Rule Documentation:
- There are multiple Exit Actions that are considered code:"rule" Actions.
- These are: code:"freeze", code:"kill", code:"pause", code:"reload", code:"restart", code:"resume", code:"start", code:"stop", and code:"thaw".
-
- The code:"rule" Actions immediately execute a named Rule file.
- - The first Action Parameter represents the Rule directory, which is a relative directory path the Rule file is to be found.
- - Do not include leading or trailing slashes.
- - This is relative to the settings rules directory.
-
- - The second Action Parameter represents the base name for the Rule file, without the file extension.
- - This must not have any directory paths.
-
- - The remaining Action Parameters may be specified in any order\:
- - code:"asynchronous": Designates that execution will not block (wait).
- - code:"require": Designates that this Rule must succeed or trigger execution of failsafe.
- - code:"wait": Designates that this Rule will not execute until all other Actions before this (including code:"asynchronous" ones) finish executing (in a top-down manner).
-
- The full path to the code:"rule" is relative to the settings, such that if the controller Rule settings are found in code:"/etc/controller/rules/", then for a directory called code:"[directory]" and a Rule base name of code:"[base_name]", the resulting path would be: code:"/etc/controller/rules/[directory]/[base_name].rule"
-
- It is important to note that for any given code:"rule", execution within that code:"rule" may be internally asynchronous (even if the code:"rule" is synchronous).
- For example, a service that is often called a daemon will execute in the background.
- Until that execution succeeds and the daemon goes into the background the representing Rule will block.
- After the daemon goes into the background, then the representing Rule will no longer block and be fully executed.
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: open-standard-license-1.0-or-later
-# version 2024/07/02
-#
-# This file (assumed to be named packet.txt) can be more easily read using the following iki_read commands:
-# iki_read packet.txt +Q -w -W code '"' '"'
-#
-# To read the "Packet Documentation" section of this file, use this command sequence:
-# fss_basic_list_read packet.txt +Q -cn "Packet Documentation" | iki_read +Q -w -W code '"' '"'
-#
-
-Packet Documentation:
- Describes how a packet is designed and intended to be used.
-
- The code:"packet" is the general category in which multiple types of packets belong.
- This describes the different packets based on their code:"type".
-
- Each packet begins with a control block and a size block followed by a payload block.
-
- The control block\:
- The leading bit (starting from the left) designates the the format of the payload, which is 0 for string and 1 for binary.
- The second bit (starting from the left) designates the the byte order for the rest of the packet, which 0 is for little endian and 1 is for big endian.
- The remaining 6-bits are reserved for future use.
-
- The size block\:
- The size block represents the size of the entire packet (the control block, the size blocks, and the payload block).
- This number is a single 32-bit unsigned integer.
-
- Example packet structure\:
- block:"
- [ Control Block ] [ Size Block ] [ Payload Block ]
- [ 0b10000000 ] [ 0b00000000 0b00000000 0b00000100 0b11010010 ] [ size: 1229 (1234 - 5) ]
- "
-
- The payload block\:
- This block is represented by the code:"FSS-000E (Payload)" specification and its structure ad use is described in the next sections.
-
- The following types of payload are received or sent\:
- 1) controller payload.
- 2) error payload.
- 3) init payload.
-
- The controller payload\:
- Commands being sent to the controller and their respective responses utilize a code:"controller" payload.
- These are pre-defined commands to rules or the controller program itself.
- Commands such as starting or stopping some rule, for example.
- A controller payload is also sent in response to a controller payload request to represent a success.
-
- The code:"now" condition designates that the kexec, reboot, or shutdown is to begin immediately.
- The code:"at" condition designates that the kexec, reboot, or shutdown is to begin once a specific date and time is reached by the system clock.
- The code:"in" condition designates that the kexec, reboot, or shutdown is to begin once a specific amount of time is passed by the system clock since the execution of this command started.
-
- For these code:"time" conditions, different units of time should be supported, such as code:"seconds", code:"days", code:"years" as standard time, Time, or UNIX Time (Epoch Time).
-
- The normal code:"controller" payload commands are any valid Rule Action that performs some action.
- This does not include Actions that provide some setting or configuration (such as code:"with_pid").
- Some of the supported commands are: code:"freeze", code:"kill", code:"pause", code:"reload", code:"rerun", code:"restart", code:"resume", code:"start", code:"stop", or code:"thaw".
- Multiple commands may be sent multiple code:"action" headers.
- The code:"action" headers are order sensitive, executing from top to bottom, and one does not start until the previous successfully completes.
-
- Multiple code:"status" headers may exist in the response so long as they each match an code:"action" in the request.
-
- The code:"payload" is expected to be empty and have a length of 0 for a request.
- The code:"payload" may have an code:"FSS-0000 (Basic)" format containing a single Object code:"message" to represent a message associated with an action.
- Multiple code:"message" may exist in the response so long as they each match an code:"action" in the request.
-
- The error payload\:
- The error payload is intended to communicate some sort of failure.
- The error payload is only sent in response to some request (and not in response to another response).
- The control (the client) is not expected to send error payloads and the controller (the service) should send an error in response to an error payload or ignore it entirely.
- The code:"status" from the code:"header" designates the status code as either a status code name string or a status code number (where a number may have error and warning bits).
- The code:"payload" will contain a NULL terminated string representing the message used to describe the error.
-
- The init payload\:
- The init payload is intended exclusively for the code:"init" operation mode and is expected to only be available when running as code:"init".
- This is used to provide special actions, namely code:"kexec", code:"reboot", and code:"shutdown".
-
- The code:"kexec" is for booting into another kernel, which may effectively be the same as a code:"reboot" ("kexec" is currently neither supported nor implemented).
- The code:"reboot" is for rebooting the machine (currently not implemented).
- The code:"shutdown" is for shutting down the machine (currently not implemented).
- These three commands are configurable to fire off based on conditions.
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: open-standard-license-1.0-or-later
-# version 2024/07/02
-#
-# This file (assumed to be named rule.txt) can be more easily read using the following iki_read commands:
-# iki_read rule.txt +Q -r PID PID -w -W code '"' '"'
-#
-# To read the "Rule Documentation" section of this file, use this command sequence:
-# fss_basic_list_read rule.txt +Q -cn "Rule Documentation" | iki_read +Q -r PID PID -w -W code '"' '"'
-#
-
-Rule Documentation:
- This describes the intent and purpose of a Rule file.
-
- A Rule file, such as code:"ssh.rule", is intended to designate what to execute.
-
- The rule file is read top-down, except for the outer most list code:"settings", which is intended to store setting data for this rule.
- Multiple outer most list Objects may be specified and they are executed as provided, in a top-down manner.
-
- - The code:"settings" Rule Type has the following code:"FSS-0001 (Extended)" Content\:
- - code:"affinity": Define one or more processors to restrict this rule by with each number representing a specific processor by its id (starting at 0).
- - code:"capability": Define a set of capabilities in which to use, using the capability code:"text" format (such as code:"= cap_chown+ep").
- - code:"cgroup": Define a cgroup (control group) in which everything within this rule executes under.
- - code:"define": A single environment variable name and its associated value that is automatically exposed to processes executed within this rule.
- - code:"engine": An executable name of a script, such as code:"bash", to use for the code:"script" Rule Type (which likely defaults to code:"bash" if not specified).
- - code:"environment": A set of environment variables to expose to the processes executed within this rule (PATH is always exposed).
- - code:"group": A set of group names or IDs to execute as with the first group being the primary group and all remaining being supplementary groups.
- - code:"limit": Define a resource limit to use (multiple limits may be specified, but only once for each type).
- - code:"name": A name used to represent this rule, which is printed to the user, screen, logs, etc...
- - code:"nice": A single niceness value to run all processes executed within this rule as (-20 gets to be greediest in CPU usage and 19 being the nicest in CPU usage).
- - code:"on": Define a Rule Action in which a specified dependency is needed, wanted, or wished for.
- - code:"parameter": An IKI name and its associated value for use in this rule file.
- - code:"path": A single Content used to set a custom PATH environment variable value.
- - code:"scheduler": A valid name of a scheduler to use followed by an optional priority number.
- - code:"timeout": A set of timeouts to wait for in which to perform a set action or to consider failure.
- - code:"user": A single user name or ID to execute as.
-
- - The code:"capability" setting\:
- If the user the controller program is run as does not have the desired capabilities already, they cannot be added.
- This essentially maintains or reduces the capabilities already available.
- Due to capabilities only being a draft in the POSIX standard, one may expect code:"capabilities" support may not be available and in such a case this setting will do nothing.
- If the dependent project (f_capability) does not have libcap support enabled, then capabilities will be unsupported by the compilation of this project.
-
- - The code:"control" setting\:
- The first argument is either code:"existing" or code:"new", where for code:"existing" the process is run inside the existing control used by the parent and when code:"new" the process is executed within a new control group namespace entirely.
-
- - The code:"define" setting\:
- Use this to define an environment variable (this overwrites any existing environment variable with this name).
- A define is both exported as an environment variable as well as exposed as an IKI variable.
- Example IKI variable substitution: for code:"define PATH /bin:/sbin", the associated IKI variable would look like: define:"PATH".
-
- All environment variables, including those defined using this, must be in the code:"environment" list to be exported to the executed process.
- Environment variables added here that are not added to the environment are still exposed as an IKI variable.
-
- - The code:"engine" setting\:
- This engine is used for both code:"script" and code:"utility" Rule Types.
- The program that engine refers to must accept a standard input pipe to be supported.
- Additional parameters may be passed to the engine.
-
- - The code:"group" and code:"user" settings\:
- Only users and groups that the user the controller program is being run as is allowed to use may be used.
-
- - The code:"limit" setting\:
- The first parameter must be one of: code:"as", code:"core", code:"cpu", code:"data", code:"fsize", code:"locks", code:"memlock", code:"msgqueue", code:"nice", code:"nofile", code:"nproc", code:"rss", code:"rtprio", code:"rttime", code:"sigpending", or code:"stack".
- The second parameter represents the soft limit.
- The third parameter represents the hard limit.
- This may be specified multiply times, but only once for each type.
-
- - The code:"on" setting\:
- The first parameter represents the Action the dependency exists under and must be one of: code:"freeze", code:"kill", code:"pause", code:"reload", code:"restart", code:"resume", code:"start", code:"stop", or code:"thaw".
- The second parameter represents how the dependency is required and must be one of: code:"need", code:"want", or code:"wish".
- The third parameter is a partial path to the rule file.
- The fourth parameter represents the name of the rule file.
-
- - In the case of the second parameter\:
- - A code:"need" designates that the dependent rule is required to be executed (must exist and must succeed).
- - A code:"want" designates that the dependent rule is to be executed (may exist and if it does, then it must succeed).
- - A code:"wish" designates that the dependent rule is to be executed (may exist and if it does, but it does not need to succeed).
-
- In the case of code:"want" and code:"wish", if the desired rule is either not found or is otherwise disabled, then this will not fail or otherwise block the wanting or wishing rule.
-
- - The code:"path" setting\:
- When specified, the code:"PATH" environment variable is automatically added to the code:"environment" setting.
-
- - The code:"parameter" setting\:
- Use this to define an IKI variable name and value.
- These do not conflict with environment variables and are not exposed as environment variables.
- Example IKI variable substitution: for code:"parameter hello world", the associated IKI variable would look like: parameter:"hello".
-
- - The code:"scheduler" setting\:
- The valid range of the priority number is dependent on the scheduler.
- For example, non-real-time schedulers (such as code:"idle") only support a value of 0 whereas real-time schedulers (such as code:"fifo") only support an inclusive range of 1 to 99.
- Supported non-real-time schedulers are: code:"batch", code:"idle", and code:"other" (aka: normal/default).
- Supported real-time schedulers are: code:"deadline", code:"fifo", code:"round_robin".
-
- - The code:"timeout" setting\:
- (This is not currently implemented.)
- Provides settings for each of the three special situations: code:"kill", code:"start", and code:"stop".
- Each of these may only have a single one exist at a time (one code:"kill", one code:"start", and one code:"stop").
- Each successive code:"timeout" Item Action, specific to each Action Name (such as code:"start"), specified replaces the previously defined code:"timeout" Action (in a top-down manner).
- The second Content for each of these, when specified, may be a 0 or greater whole number representing the number of MegaTime (MT) (equivalent to milliseconds).
- For code:"kill", this represents the number of MegaTime to wait after stopping some Rule and that Rule has not yet stopped to forcefully stop the Rule (aka kill the Rule).
- For code:"start", this represents the number of MegaTime to wait after starting some Rule before assuming something went wrong and the Rule is returned as failed.
- For code:"stop", this represents the number of MegaTime to wait after stopping some Rule before assuming something went wrong and the Rule is returned as failed.
- If the second Content is not specified, then this disables the type (prevents the specified timeout action).
-
- There are four available Rule Types to choose from: code:"command", code:"service", code:"script", and code:"utility".
-
- The code:"command" Rule Type provides a simple command to run under the different circumstances: code:"start", code:"stop", code:"restart", and code:"reload".
- A code:"command" always operates in the foreground.
-
- The code:"service" Rule Type provides a code:"command" accompanied with a PID:"Process Identifier" file (Process Identifier file).
-
- The code:"script" Rule Type provides a series of lines to be executed by some engine, such as GNU Bash.
- This code:"script" operates in the foreground, but individual things done within the script may operate in foreground or background.
- The last return state is treated as an error, so be sure to finish the script with a return code of 0 to designate no error and any other whole number, such a 1, to designate an error.
- Therefore passing code:"exit 1" would return as an error and passing code:"exit 0" would return as a success.
- A code:"script" is assumed to be in GNU Bash, which is the default expected behavior, but the specification does not explicitly require this.
- Another scripting language can be used but changing this incurs the responsibility to ensure all rules are updated to the appropriate scripting language.
-
- The code:"utility" Rule Type provides a code:"script" accompanied with a PID:"Process Identifier" file (Process Identifier file).
-
- There are nine Rule Actions used to execute ("freeze", code:"kill", code:"pause", code:"reload", code:"restart", code:"resume", code:"start", code:"stop", and code:"thaw")\:
- When code:"restart" Object's Content is not provided, then code:"start" and code:"stop" is called when the rule is executed using the restart Action, if both code:"start" and code:"stop" are provided.
- When code:"reload", code:"start", or code:"stop" Object's Content are not provided, then no respective Action is performed.
-
- Commands are conditionally available depending on the presence of these, such as if code:"stop" is not provided then code:"stop" (and code:"restart") will not be available for the code:"control" program(s) to use.
-
- Thee are additional Rule Actions not used to execute ("pid_file", code:"rerun", and code:"with")\:
- - The code:"pid_file" Object's Content designates the path to the PID:"Process Identifier" file created by the called program.
-
- - The code:"rerun" Object's Content designates how to re-run a given execution Rule type.
- - The first Content represents the execution type, which may be one of: code:"freeze", code:"kill", code:"pause", code:"reload", code:"restart", code:"resume", code:"start", code:"stop", and code:"thaw".
-
- - The second Content represents when to run this re-run is triggered, which is either code:"success" (return code of 0) or code:"failure" (return code is not 0).
-
- - The third Content and more represent additional options for fine tuning how the re-run is Performed\:
- When code:"delay", followed by a number of MegaTime (MT) (equivalent to milliseconds) in which to wait before attempting the re-run.
- When code:"max", followed by a positive number or the number 0 designating the maximum number of re-runs to perform.
- When code:"reset", the code:"max" re-run counter is reset for the opposite re-run when this re-run is triggered, such as\:
- A code:"rerun start success reset" and a code:"rerun failure max 10", the failure counter would reset to 0 when the code:"success" re-run is performed and not when the code:"failure" re-run is performed.
-
- A code:"max" of 0 designates that the re-run will happen infinitely.
-
- - The code:"with" Object's Content designates special flags designating very specific behavior to be applied to any single Rule Type.
- The following flags are supported:
- - code:"full_path": Used only by Rule Types that execute something, wherein the entire full path is used for execution and is assigned as argument[0] (such as code:"/bin/bash").
- When not specified, the path provided is used and the argument[0] will be the base name (such as code:"bash").
- - code:"session_new": Execute in a new session setting the process group to the executed process' id (making the executed process a code:"controlling terminal").
- - code:"session_same": Execute in the same session where the process group is set to the parent process id.
-
- IKI Variables\:
- All Rule Actions support IKI variable substitution.
- The Rule Settings do not support IKI variable substitution.
-
- The following IKI variable names are supported\:
- - define
- - parameter
- - program
-
- The code:"define" IKI variables, such as define:"PATH", expand environment variables.
-
- The code:"parameter" IKI variables, such as parameter:"hello", expand IKI variables defined using the code:"parameter" Setting Rule Type.
-
- The code:"program" IKI variables, such as program:"verbose:option", expand program arguments (where code:"verbose:option" might expand into code:"-v" ).
-
- Only the following code:"program" IKI variables are supported\:
- - dark\:
- This variable holds the code:"dark" program parameters, such as code:"+d".
- This supports code:":option".
-
- - light\:
- This variable holds the code:"light" program parameters, such as code:"+l".
- This supports code:":option".
-
- - no_color\:
- This variable holds the code:"no_color" program parameters, such as code:"+n".
- This supports code:":option".
-
- - quiet\:
- This variable holds the code:"quiet" program parameters, such as code:"+Q".
- This supports code:":option".
-
- - error\:
- This variable holds the code:"error" program parameters, such as code:"+E".
- This supports code:":option".
-
- - normal\:
- This variable holds the code:"normal" program parameters, such as code:"+N".
- This supports code:":option".
-
- - verbose\:
- This variable holds the code:"verbose" program parameters, such as code:"+V".
- This supports code:":option".
-
- - debug\:
- This variable holds the code:"debug" program parameters, such as code:"+D".
- This supports code:":option".
-
- - cgroup\:
- This variable holds the code:"cgroup" program parameters, such as code:"-c /sys/fs/cgroup/".
- This supports both code:":option" and code:":value".
-
- - daemon\:
- This variable holds the code:"daemon" program parameters, such as code:"-d".
- This supports code:":option".
-
- - init\:
- This variable holds the code:"init" program parameters, such as code:"-I".
- This supports code:":option".
-
- - interruptible\:
- This variable holds the code:"interruptible" program parameters, such as code:"-i".
- This supports code:":option".
-
- - pid\:
- This variable holds the code:"pid" program parameters, such as code:"-p controller/run/default.pid".
- This supports both code:":option" and code:":value".
-
- - settings\:
- This variable holds the code:"settings" program parameters, such as code:"-s controller/".
- This supports both code:":option" and code:":value".
-
- - simulate\:
- This variable holds the code:"simulate" program parameters, such as code:"-S".
- This supports code:":option".
-
- - socket\:
- This variable holds the code:"socket" program parameters, such as code:"-k controller/run/default.socket".
- This supports both code:":option" and code:":value".
-
- - uninterruptible\:
- This variable holds the code:"uninterruptible" program parameters, such as code:"-U".
- This supports code:":option".
-
- - validate\:
- This variable holds the code:"validate" program parameters, such as code:"-v".
- This supports code:":option".
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: open-standard-license-1.0-or-later
-# version 2024/07/02
-#
-# This file (assumed to be named simulate.txt) can be more easily read using the following iki_read commands:
-# iki_read simulate.txt +Q -w -W code '"' '"'
-#
-# To read the "Simulate Documentation" section of this file, use this command sequence:
-# fss_basic_list_read simulate.txt +Q -cn "Simulate Documentation" | iki_read +Q -w -W code '"' '"'
-#
-
-Simulate Documentation:
- This describes the intent and purpose of the simulation and validation parameters.
-
- The code:"controller" program is designed to support being run as an alternative to an init program (such as Sysvinit or SystemD).
- To help prevent problems, simulation and validation functionality is provided.
-
- - The code:"validate" functionality\:
- By itself will simply check the syntax of the Entry and Rule files (for Rule files specified in the Entry or Exit file).
- Errors are reported and nothing is executed.
- The code:"controller" program will return 0 on validation success and 1 on validation failure.
-
- - The code:"simulate" functionality\:
- By itself will perform a simulated execution of all Rules designated by an Entry or Exit file.
- The simulation is not a true simulation in that no program is ever called to perform any operations.
- Furthermore, any code:"script" specified inside a Rule is only simulated as a whole and not its individual parts.
- Once the Entry file is finished executing, the code:"simulate" will continue to run waiting on code:"control" commands.
-
- - The code:"simulate" with code:"validate" functionality\:
- Will perform similar to code:"validate" functionality except that additional information of the Rules to be executed will be printed.
- There will be neither execution nor simulated execution of any Rule when both code:"simulate" and code:"validate" are used together.
-
- When a Rule is simulated, an empty script command (generally defaulting to code:"bash") is executed in place of the actual program being executed for each program or script in the Rule file that is to be executed.
- This allows for testing the designated permissions and other settings that would be applied when calling some program.
- Control Groups are not simulated but are actually created and the simulating process will actually be placed within the Control Group.
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: cc-by-sa-4.0
-# version 2024/07/02
-#
-# This file (assumed to be named time.txt) can be more easily read using the following iki_read commands:
-# iki_read time.txt +Q -r UTC UTC -w -WW character "'" "'" code '"' '"'
-#
-# To read the "Time Documentation" section of this file, use this command sequence:
-# fss_basic_list_read time.txt +Q -cn "Time Documentation" | iki_read +Q -r UTC UTC -w -WW character "'" "'" code '"' '"'
-#
-
-Time Documentation:
- This documents a unit of measurement called a bold:"Time", represented with uppercase bold:"T".
- For comparison, a unit of bold:"Time" is equivalent to a nanosecond, or 10^-9 seconds.
- A bold:"MegaTime (MT)" is therefore equivalent to a millisecond such that a millisecond is 10^-3 seconds.
-
- A unit of bold:"Time" is intended to represent some unit of bold:"Time" such that a single 64-bit integer may hold all units of bold:"Time" for a single calendar year.
- This unit of bold:"Time" does not and must not include bold:"Years" (unlike bold:"Unix time").
- To convert from bold:"Time" to bold:"Unix time", one must have a year (which could be assumed to be the current year) and then calculate all of those calendar oddities.
-
- A unit of bold:"Time" by default is assumed to be in UTC:"Coordinated Universal Time".
- - code:"1 (Earth) year ~= 31536000000000000 Time or 31536000 GT (GigaTime)".
- - code:"1 (Earth) day = 86400000000000 Time or 86400 GT (GigaTime)".
- - code:"1 (Earth) hour = 3600000000000 Time or 3600 GT (GigaTime)".
- - code:"1 (Earth) minute = 60000000000 Time or 60 GT (GigaTime)".
- - code:"1 (Earth) second = 1000000000 Time or 1 GT (GigaTime)".
-
- Consequentially, 1 day is easily represented in units of bold:"Time" as code:"86.4 TT (TeraTime)".
-
- The Time may be stored in its "year string format".
- In this format, a Year may be prepended to the Time followed by a single colon ':' to associate a year with the Time.
- This Year has no minimum or maximum but may not have decimals.
- For example, "2020:86400000000000" would represent: January 02, 2020 0:00 UTC.
- For example, "2020:86.4 TT" would represent: January 02, 2020 0:00 UTC.
-
- A second unit of bold:"Time", called bold:"EpochTime", works the same way as bold:"Time" except it represents seconds.
- This unit is designated code:"ET".
- The format is similar to bold:"Time", except there are two colons: code:"1970::1620874738" would represent: code:"May 13, 2021 2:58:58 UTC".
- When the year is not specified, then this is identical to bold:"UNIX Epoch".
-
- A unit of bold:"EpochTime" by default is assumed to be in UTC:"Coordinated Universal Time".
- - code:"1 (Earth) year ~= 31536000 EpochTime or 31.536 GE (GigaEpochTime)".
- - code:"1 (Earth) day = 86400 EpochTime".
- - code:"1 (Earth) hour = 3600 EpochTime".
- - code:"1 (Earth) minute = 60 EpochTime".
- - code:"1 (Earth) second = 1 EpochTime".
- - code:"1 GT (GigaTime) = 1 EpochTime".
-
- Consequentially, 1 day is easily represented in units of bold:"EpochTime" as code:"86.4 KE (KiloEpochTime)".
-
- See the specification file:"time.txt" for more precise technical details.
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: open-standard-license-1.0-or-later
-# version 2024/07/02
-#
-# This file (assumed to be named entry.txt) can be more easily read using the following iki_read commands:
-# iki_read entry.txt +Q -w -W code '"' '"'
-#
-# To read the "Entry Specification" section of this file, use this command sequence:
-# fss_basic_list_read entry.txt +Q -cn "Entry Specification" | iki_read +Q -w -W code '"' '"'
-#
-
-Entry Specification:
- The Entry files follow the code:"FSS-0005 (Somewhat Basic List)" format.
-
- An Entry file name is expected to have the file extension code:".entry".
-
- For each Entry file\:
- - The outer most part is a code:"FSS-0002 (Basic List)".
- - The Basic List Object is considered the code:"Item".
- - The Basic List Content are considered the code:"Actions".
- - The code:"Actions" are code:"FSS-0001 (Extended)".
- - Each Action Object is the code:"Action Name".
- - Each Action Content are the code:"Action Parameters".
-
- The Items\:
- - code:"main": required.
-
- - code:"settings": optional, Actions may be one of\:
- - code:"control": One to two Content.
- The first Content is a relative or absolute path to a socket file.
- The second Content an optional code:"readonly".
- - code:"control_group": Exactly one Content that is a group name or group id.
- - code:"control_mode": Exactly one Content that is a valid file mode.
- - code:"control_user": Exactly one Content that is a user name or user id.
- - code:"define": Two Content, the first Content must be a case-sensitive valid environment variable name (alpha-numeric or underscore, but no leading digits).
- - code:"mode": Exactly one Content that is one of code:"helper", code:"program", or code:"service".
- - code:"parameter": Two Content, the first Content must be a case-sensitive valid IKI name and the second being an IKI value.
- - code:"pid": Exactly one Content that is one of code:"disable", code:"require", or code:"ready".
- - code:"pid_file": Exactly one Content that is a relative or absolute path to a pid file.
- - code:"session": Exactly one Content that is one of code:"new" or code:"same".
- - code:"show": Exactly one Content that is one of code:"normal" or code:"init".
- - code:"timeout": One or two content with the first being one of code:"exit", code:"start", code:"stop", or code:"kill" and the (optional) second Content being a positive whole number or 0.
-
- The Entry file may have any other valid Item Objects, but only the above are reserved.
-
- The Actions\:
- - code:"consider": One or more Content.
- The first Content is the relative file path (without any leading/trailing slashes and without file extension).
- The second Content is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"execute": One or more Content.
- The first Content is the program name or full path to the program (the program may be a script).
- All remaining Content are passed as parameters to the program being executed.
-
- - code:"failsafe": One Content that is a valid Object name, except for the reserved code:"main".
-
- - code:"freeze": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"item": One Content that is a valid Object name, except for the reserved code:"main".
-
- - code:"kill": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"pause": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"ready": Zero or One Content.
- The first may only be one of\:
- - code:"wait"
-
- - code:"reload": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"restart": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"resume": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"start": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"stop": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"thaw": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"timeout": One or two Content.
- The first being one of\:
- - code:"exit"
- - code:"start"
- - code:"stop"
- - code:"kill"
- The (optional) second Content being a positive whole number or 0.
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: open-standard-license-1.0-or-later
-# version 2024/07/02
-#
-# This file (assumed to be named exit.txt) can be more easily read using the following iki_read commands:
-# iki_read exit.txt +Q -w -W code '"' '"'
-#
-# To read the "Exit Specification" section of this file, use this command sequence:
-# fss_basic_list_read exit.txt +Q -cn "Exit Specification" | iki_read +Q -w -W code '"' '"'
-#
-
-Exit Specification:
- The Exit files follow the code:"FSS-0005 (Somewhat Basic List)" format.
-
- An Exit file name is expected to have the file extension code:".exit".
-
- For each Exit file\:
- - The outer most part is a code:"FSS-0002 (Basic List)".
- - The Basic List Object is considered the code:"Item".
- - The Basic List Content are considered the code:"Actions".
- - The code:"Actions" are code:"FSS-0001 (Extended)".
- - Each Action Object is the code:"Action Name".
- - Each Action Content are the code:"Action Parameters".
-
- The Items\:
- - code:"main": required.
-
- - code:"settings": optional, Actions may be one of\:
- - code:"pid": Exactly one Content that is one of code:"disable", code:"require", or code:"ready".
- - code:"session": Exactly one Content that is one of code:"new" or code:"same".
- - code:"show": Exactly one Content that is one of code:"normal" or code:"init".
- - code:"timeout": One or Two content with the first being one of code:"exit", code:"start", code:"stop", or code:"kill" and the (optional) second Content being a positive whole number or 0.
-
- The Exit file may have any other valid Item Objects, but only the above are reserved.
-
- The Actions\:
- - code:"consider": One or more Content.
- The first Content that is the relative file path (without any leading/trailing slashes and without file extension).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"failsafe": One Content that is a valid Object name, except for the reserved code:"main".
-
- - code:"freeze": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"item": One Content that is a valid Object name, except for the reserved code:"main".
-
- - code:"kill": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"pause": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"ready": Zero or One Content.
- The first may only be one of\:
- - code:"wait"
-
- - code:"reload": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"restart": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"resume": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"start": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"stop": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"thaw": Two or more Content.
- The first Content that is the relative directory path (without any leading/trailing slashes).
- The second Content that is the basename for a rule file.
- The third and beyond may only be one of\:
- - code:"asynchronous"
- - code:"require"
- - code:"wait"
-
- - code:"timeout": Two Content.
- The first being one of\:
- - code:"exit"
- - code:"start"
- - code:"stop"
- - code:"kill"
- The (optional) second Content being a positive whole number or 0.
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: open-standard-license-1.0-or-later
-# version 2024/07/02
-#
-# This file (assumed to be named packet.txt) can be more easily read using the following iki_read commands:
-# iki_read packet.txt +Q -w -W code '"' '"'
-#
-# To read the "Packet Specification" section of this file, use this command sequence:
-# fss_basic_list_read packet.txt +Q -cn "Packet Specification" | iki_read +Q -w -W code '"' '"'
-#
-
-Packet Specification:
- The controller program communicates use the code:"FSS-000F (Packet)".
- This specification declares how the Payload Block, which is in code:"FSS-000E (Payload)" format, is required to be used.
-
- Only a single code:"header" is allowed.
- Only a single code:"payload" is allowed.
-
- Packet Structure\:
- Packet is grouped into the following blocks\:
- - code:"control": A single 1-byte block representing control codes.
- - code:"size": A single 4-byte block representing the size of the entire packet, including the control block.
-
- The code:"header" Object contains the following code:"FSS-0001 (Extended)" Objects (depending on code:"type")\:
- - code:"action": A valid action type: code:"freeze", code:"kexec", code:"kill", code:"pause", code:"reboot", code:"reload", code:"rerun", code:"restart", code:"resume", code:"shutdown", code:"start", code:"stop", or code:"thaw".
- - code:"length": A positive whole number inclusively between 0 and 4294965248 representing the length of the code:"payload" (may be in binary, octal, decimal, duodecimal, or hexidecimal).
- - code:"status": The status code name or number representing an FSS status code, such as F_okay, F_failure, or 200 (where a number may have error and warning bits and may be in binary, octal, decimal, duodecimal, or hexidecimal).
- - code:"type": The packet type that is one of code:"controller", code:"error", or code:"init".
-
- When there are multiple Objects of the same name inside the code:"header"\:
- - code:"action": The order represents the order in which the actions are performed.
- - code:"length": There may only be one length Object, all others after the first are ignored (may be in binary, octal, decimal, duodecimal, or hexidecimal).
- - code:"status": A status for each action, in the same order as the order of the action, such as F_okay, F_failure, or 200 (where a number may have error and warning bits and may be in binary, octal, decimal, duodecimal, or hexidecimal).
- - code:"type": The first represent the type and all others represents a sub-type.
-
- There are different headers and payload properties based on the code:"type".
-
- The code:"controller" type\:
- Supports the following headers: code:"action", code:"length", code:"status", and code:"type".
-
- Only a single code:"action" may be provided and must exist for request and response packets.
- Only a single code:"status" may be provided and must exist for response packets.
-
- The code:"payload" is dependent on the code:"action".
-
- The code:"error" type\:
- Supports the following headers: code:"length", code:"status", and code:"type".
-
- Only a single code:"status" may be provided and must exist for request and response packets.
-
- The code:"payload" is a NULL terminated string whose length is defined by the code:"length" code:"header" Content.
-
- There are different headers and payload properties based on the code:"type".
-
- The code:"init" type\:
- Supports the following headers: code:"action", code:"length", code:"status", and code:"type".
-
- Only a single code:"action" may be provided and must exist for request and response packets.
- Only a single code:"status" may be provided and must exist for response packets.
-
- The code:"payload" is dependent on the code:"action".
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: open-standard-license-1.0-or-later
-# version 2024/07/02
-#
-# This file (assumed to be named rule.txt) can be more easily read using the following iki_read commands:
-# iki_read rule.txt +Q -w -W code '"' '"'
-#
-# To read the "Rule Specification" section of this file, use this command sequence:
-# fss_basic_list_read rule.txt +Q -cn "Rule Specification" | iki_read +Q -w -W code '"' '"'
-#
-
-Rule Specification:
- The Rule files follow the code:"FSS-000D (Basic Rule)" format with bold:"IKI-0000 (Unrestricted)".
-
- A Rule file name is expected to have the file extension code:".rule".
-
- For each Rule file\:
- - The outer most part is a code:"FSS-0002 (Basic List)".
- - The Basic List Object is considered the code:"Rule Type".
- - The Basic List Content is determined by the specific code:"Rule Type".
- - The Content for each code:"Rule Type" is called the code:"Item".
- - Each Item Object is the code:"Item Name".
- - Each Item Content is either the code:"Action" or the code:"Setting".
- - Each Action Object is the code:"Action Name".
- - Each Action Content are the code:"Action Parameters".
- - Each Setting Object is the code:"Setting Name".
- - Each Setting Content are the code:"Setting Values".
-
- The Rule Types\:
- - code:"command": Follows either code:"FSS-0003 (Extended List)" or code:"FSS-0001 (Extended)".
- - code:"script": Follows either code:"FSS-0003 (Extended List)" or code:"FSS-0001 (Extended)".
- - code:"service": Follows either code:"FSS-0003 (Extended List)" or code:"FSS-0001 (Extended)".
- - code:"settings": Is required and follows either code:"FSS-0001 (Extended)".
- - code:"utility": Follows either code:"FSS-0003 (Extended List)" or code:"FSS-0001 (Extended)".
-
- For the above Rule Types, code:"settings" may be specified only once whereas the others may be specifed multiple times.
- The code:"settings" Rule Type is always processed first, regardless of position.
- The other Rule Types are processed top-down.
-
- The code:"settings" Rule Type has the following code:"FSS-0001 (Extended)"\:
- - code:"affinity": One or more Content, each must be a 0 or greater whole number.
- - code:"capability": One Content representing capabilities.
- - code:"cgroup": Two or more Content, the first Content being either code:"existing" or code:"new" and the remaining representing a valid cgroup (control group) name, must have at least 1 graph character (non white space printing character) (leading and trailing white space are trimmed off).
- - code:"define": Two Content, the first Content must be a case-sensitive valid environment variable name (alpha-numeric or underscore, but no leading digits).
- - code:"engine": One or more Content representing a valid program name or path (such as code:"bash" or code:"/bin/bash") and any optional arguments.
- - code:"environment": Zero or more Content, each must be a case-sensitive valid environment variable name (alpha-numeric or underscore, but no leading digits).
- - code:"group": One or more Content representing group names or group ids.
- - code:"limit": Three Content, with the first representing a valid resource type and the second and third being a valid resource limit number (positive whole number or 0).
- - code:"name": One Content, must have at least 1 graph character (non white space printing character) (leading and trailing white space are trimmed off).
- - code:"nice": One Content, must be a valid number for process code:"niceness" (Any whole number inclusively between -20 to 19).
- - code:"on": Four Content, the first being a Rule Action, the second being code:"need", code:"want", or code:"wish", the third being a partial path, and the fourth being a Rule file name without code:".rule" extension.
- - code:"parameter": Two Content, the first Content must be a case-sensitive valid IKI name and the second being an IKI value.
- - code:"path": One Content representing a valid code:"PATH" environment string (such as code:"/bin:/sbin:/usr/bin").
- - code:"scheduler": One or two Content representing a scheduler name and the optional numeric priority (Any whole number inclusively between 0 and 99).
- - code:"timeout": One or two content with the first being one of code:"exit", code:"start", code:"stop", or code:"kill" and the (optional) second Content being a positive whole number or 0.
- - code:"user": One Content representing a user name or user id.
-
- The code:"command" and code:"script" Rule Types allow the following the code:"FSS-0001 (Extended)"\:
- - code:"freeze": One or more Content representing a program being executed and its arguments.
- - code:"kill": One or more Content representing a program being executed and its arguments.
- - code:"pause": One or more Content representing a program being executed and its arguments.
- - code:"reload": One or more Content representing a program being executed and its arguments.
- - code:"rerun": Two or more Content representing a Rule type that executes and its properties.
- - code:"restart": One or more Content representing a program being executed and its arguments.
- - code:"resume": One or more Content representing a program being executed and its arguments.
- - code:"start": One or more Content representing a program being executed and its arguments.
- - code:"stop": One or more Content representing a program being executed and its arguments.
- - code:"thaw": One or more Content representing a program being executed and its arguments.
- - code:"with": One or more Content representing special options for the Rule Type.
-
- The code:"service" and code:"utility" Rule Types allow the following the code:"FSS-0001 (Extended)"\:
- - code:"pid_file": One Content representing the path to a PID file.
- - code:"rerun": Two or more Content representing a Rule type that executes and its properties.
- - code:"with": One or more Content being one of code:"full_path", code:"session_new", or code:"session_same".
-
- The code:"command" and code:"service" Rule Types allow the following the code:"FSS-0003 (Extended List)"\:
- - code:"freeze": A list repesenting multiple programs and their respective arguments to execute.
- - code:"kill": A list repesenting multiple programs and their respective arguments to execute.
- - code:"pause": A list repesenting multiple programs and their respective arguments to execute.
- - code:"reload": A list repesenting multiple programs and their respective arguments to execute.
- - code:"restart": A list repesenting multiple programs and their respective arguments to execute.
- - code:"resume": A list repesenting multiple programs and their respective arguments to execute.
- - code:"start": A list repesenting multiple programs and their respective arguments to execute.
- - code:"stop": A list repesenting multiple programs and their respective arguments to execute.
- - code:"thaw": A list repesenting multiple programs and their respective arguments to execute.
-
- The code:"script" and code:"utility" Rule Types allow the following the code:"FSS-0003 (Extended List)"\:
- - code:"freeze": A list repesenting the contents of a script, such as a GNU Bash shell.
- - code:"kill": A list repesenting the contents of a script, such as a GNU Bash shell.
- - code:"pause": A list repesenting the contents of a script, such as a GNU Bash shell.
- - code:"reload": A list repesenting the contents of a script, such as a GNU Bash shell.
- - code:"restart": A list repesenting the contents of a script, such as a GNU Bash shell.
- - code:"resume": A list repesenting the contents of a script, such as a GNU Bash shell.
- - code:"start": A list repesenting the contents of a script, such as a GNU Bash shell.
- - code:"stop": A list repesenting the contents of a script, such as a GNU Bash shell.
- - code:"thaw": A list repesenting the contents of a script, such as a GNU Bash shell.
-
- The code:"rerun" Rule Type Content has the following structure\:
- The first Content represents one of: code:"freeze", code:"kill", code:"pause", code:"reload", code:"restart", code:"resume", code:"start", code:"stop", or code:"thaw".
- The second Content represents one of: code:"success" or code:"failure".
- The third and more Content represents one of: code:"delay", code:"max", or code:"reset".
- Where code:"delay" and code:"max" must be followed by a positive number or the number 0.
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: open-standard-license-1.0-or-later
-# version 2024/07/02
-#
-# This file (assumed to be named task.txt) can be more easily read using the following iki_read commands:
-# iki_read task.txt +Q -w -W code '"' '"'
-#
-# To read the "Task Specification" section of this file, use this command sequence:
-# fss_basic_list_read task.txt +Q -cn "Task Specification" | iki_read +Q -w -W code '"' '"'
-#
-# A "Task" is not fully implemented but is provided as a proposal for consideration and is subject to completion or removal.
-#
-
-Task Specification:
+++ /dev/null
-# fss-0002 iki-0000
-#
-# license: open-standard-license-1.0-or-later
-# version 2024/07/02
-#
-# This file (assumed to be named time.txt) can be more easily read using the following iki_read commands:
-# iki_read time.txt +Q -r UTC UTC -w -WW character "'" "'" code '"' '"'
-#
-# To read the "Time Specification" section of this file, use this command sequence:
-# fss_basic_list_read time.txt +Q -cn "Time Specification" | iki_read +Q -r UTC UTC -w -WW character "'" "'" code '"' '"'
-#
-
-Time Specification:
- There are two units of bold:"Time", the first is simply called bold:"Time" and the second is called bold:"EpochTime".
-
- Both bold:"Time" and bold:"EpochTime" are measured without the year but may contain a year to designate the point in the counting begins.
- These are both represented by a single 64-bit (unsigned) integer.
- The default timezone is always UTC:"Coordinated Universal Time".
-
- The common form is intended as the non-technical form that is form common use.
- This may have a negative value or be more than 64-bit digits long.
- This is simply not expected to be interpreted as a unit of time on a computer (but nothing stops it from being interpreted).
-
- The technical forms are limit to 64-bit unsigned for technical use but should technology advance to a point where larger bits are needed then this allows for that.
- The systems should expect 64-bit and larger bits would have to become common before something larger than 64-bit is the expected or assumed default.
- Negative signs can be allowed but they must not prevent the full use of the 64-bit.
- The implementation of how this is done is left to the implementer except that the signs are immediately to the left of the digit.
- For example code:"2022:-5" would be 5 units after the start of the year 2022.
- Because the negative is allowed, so must the positive character (such as code:"2022:+5").
- A positive value is the default interpretation when no sign is valid.
-
- The unit of time called bold:"Time" is counted increments of a nanosecond, or 10^-9 seconds.
- A unit of bold:"Time" is, therefore, equivalent to a nanosecond.
- The default year for bold:"Time" is the current year.
-
- The unit of time called bold:"EpochTime" is counted increments of a second, or 10^-9 seconds.
- A unit of bold:"EpochTime" is, therefore, equivalent to a second.
- The default year for bold:"EpochTime" is the bold:"UNIX Epoch", sometimes called bold:"Unix time".
-
- The unit bold:"Time" has two technical forms and one common form, with the year and without the year.
-
- Key\:
- code:"\s" = White space.
- code:"\d" = The digits used to represent time (a digit).
- code:"*" = Zero or more occurrences.
- code:"+" = One or more occurrences.
- code:":" = A single colon character:":" (unicode:"U+003A").
- code:'"' = A single double-quote character:'"' (unicode:"U+003A").
-
- The common form of bold:"Time"\:
-
- Before Structure\:
- code:"".
-
- Structure\:
- code:"\s*\d+\s*\U*\s*".
-
- After Structure\:
- code:"".
-
- Example\:
- code:"86400".
- code:"86400 T".
- code:"86400 Time".
-
- The first technical form of bold:"Time"\:
-
- Before Structure\:
- code:"".
-
- Structure\:
- code:"\s*\d+:\d+\s*\U*\s*".
-
- After Structure\:
- code:"".
-
- Example\:
- code:"2022:86400".
- code:"2022:86400 T".
- code:"2022:86400 Time".
- code:"2022:86400 MT".
- code:"2022:86400 MegaTime".
-
- The second technical form of bold:"Time"\:
-
- Before Structure\:
- code:"".
-
- Structure\:
- code:"\s*:\d+\s*\U*\s*".
-
- After Structure\:
- code:"".
-
- Example\:
- code:":86400".
- code:":86400 T".
- code:":86400 Time".
- code:":86400 MT".
- code:":86400 MegaTime".
-
- The unit bold:"EpochTime" has two technical forms and one common form, with the year and without the year.
-
- The common form of bold:"Time"\:
-
- Before Structure\:
- code:"".
-
- Structure\:
- code:"\s*\d+\s*\U*\s*".
-
- After Structure\:
- code:"".
-
- Example\:
- code:"86400".
- code:"86400 ET".
- code:"86400 EpochTime".
- code:"86400 MET".
- code:"86400 MegaEpochTime".
-
- The first technical form of bold:"EpochTime"\:
-
- Before Structure\:
- code:"".
-
- Structure\:
- code:"\s*\d+::\d+\s*\U*\s*".
-
- After Structure\:
- code:"".
-
- Example\:
- code:"2022::86400".
- code:"2022::86400 ET".
- code:"2022::86400 EpochTime".
- code:"2022::86400 MET".
- code:"2022::86400 MegaEpochTime".
-
- The second technical form of bold:"Time"\:
-
- Before Structure\:
- code:"".
-
- Structure\:
- code:"\s*:\d+\s*\U*\s*".
-
- After Structure\:
- code:"".
-
- Example\:
- code:"::86400".
- code:"::86400 ET".
- code:"::86400 EpochTime".
- code:"::86400 MET".
- code:"::86400 MegaEpochTime".