]> Kevux Git Server - controller/commitdiff
Progress: Continue migrating the project.
authorKevin Day <kevin@kevux.org>
Wed, 17 Apr 2024 02:01:12 +0000 (21:01 -0500)
committerKevin Day <kevin@kevux.org>
Wed, 17 Apr 2024 02:01:12 +0000 (21:01 -0500)
27 files changed:
data/build/defines
data/build/settings
sources/c/controller/controller.h
sources/c/controller/main.c
sources/c/init/init.h
sources/c/init/main.c
sources/c/main/common.c
sources/c/main/common.h
sources/c/main/common/enumeration.h
sources/c/main/common/print.c
sources/c/main/common/print.h
sources/c/main/common/string.h
sources/c/main/common/type/process.h
sources/c/main/common/type/rule.h
sources/c/main/common/type/thread.c
sources/c/main/common/type/thread.h
sources/c/main/controller.h
sources/c/main/path.c [new file with mode: 0644]
sources/c/main/path.h [new file with mode: 0644]
sources/c/main/print/debug.c
sources/c/main/print/debug.h
sources/c/main/print/error.c
sources/c/main/print/error.h
sources/c/main/print/lock.c [new file with mode: 0644]
sources/c/main/print/lock.h [new file with mode: 0644]
sources/c/main/print/message.c
sources/c/main/thread.h

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