]> Kevux Git Server - controller/commitdiff
Progress: Initial setup for granting init program the ability to handle shutdown...
authorKevin Day <Kevin@kevux.org>
Thu, 31 Jul 2025 02:51:02 +0000 (21:51 -0500)
committerKevin Day <Kevin@kevux.org>
Thu, 31 Jul 2025 03:22:39 +0000 (22:22 -0500)
The standard shutdown/reboot/ctrl-alt-delete process actually operates via interrupts.
Make the init program interruptible by default and add notes in the help.

Add additional callbacks.
The help callback is added to print additional information specific to the init program.
The process thread signal is going to be a new callback that the init program can use to define custom behavior.
This custom behavior will utilize the special shutdown/reboot/ctrl-alt-delete signals.
The init program will be handling more signals than the controller program.
(I may want to consider looking into supporting more signals for the controller program as well.)

19 files changed:
data/build/settings.init
data/build/stand_alone/config.h
data/build/stand_alone/settings.init
sources/c/program/controller/controller/main.c
sources/c/program/controller/init/init.h
sources/c/program/controller/init/main.c
sources/c/program/controller/init/print.c [new file with mode: 0644]
sources/c/program/controller/init/print.h [new file with mode: 0644]
sources/c/program/controller/init/signal.c [new file with mode: 0644]
sources/c/program/controller/init/signal.h [new file with mode: 0644]
sources/c/program/controller/main/common/type.h
sources/c/program/controller/main/controller.h
sources/c/program/controller/main/print/message.c
sources/c/program/controller/main/print/message.h
sources/c/program/controller/main/print/output/entry/setting.c
sources/c/program/controller/main/print/output/rule/validate.c
sources/c/program/controller/main/process.c
sources/c/program/controller/main/process.h
sources/c/program/controller/main/thread/signal.c

index 43b2bc26a2832e4421276975a92f64cef5731383..5deb3c758dce36201f28b0870b88dc12137bf22c 100644 (file)
@@ -52,9 +52,9 @@ build_libraries_static-individual_thread -l:libf_thread.a
 build_libraries_static-level -l:libfll_2.a -l:libfll_1.a -l:libfll_0.a -l:libcap.a
 build_libraries_static-monolithic -l:libfll.a -l:libcap.a
 
-build_sources_program config.c main.c init.c string.c
+build_sources_program config.c main.c init.c print.c signal.c string.c
 
-build_sources_headers init.h string.h
+build_sources_headers init.h print.h signal.h string.h
 
 build_sources_documentation man
 
index 64ca67fb42fbfa68b63f3494b339e07238e7e899..d7287a01211d23152f7c4f681025e94e116757ed 100644 (file)
 //#define _di_fll_program_standard_set_down_
 //#define _di_fll_program_standard_set_up_
 //#define _di_fll_program_standard_signal_handle_
-//#define _di_fll_program_standard_signal_received_
+#define _di_fll_program_standard_signal_received_
 //#define _di_fll_program_standard_signal_received_wait_
 #define _di_private_inline_f_print_to_error_
 #define _di_private_inline_private_f_print_to_error_
index 7357eee5091d89e9c0a232b7cd2295fae4dbfbf1..7639b49d5fd9a2afda4ee2c6ce9c2c7655e4368f 100644 (file)
@@ -108,7 +108,7 @@ build_sources_program program/controller/main/signal.c program/controller/main/s
 build_sources_program program/controller/main/thread.c program/controller/main/thread/cleanup.c program/controller/main/thread/control.c program/controller/main/thread/entry.c program/controller/main/thread/instance.c program/controller/main/thread/is.c program/controller/main/thread/rule.c program/controller/main/thread/signal.c
 build_sources_program program/controller/main/validate.c
 
-build_sources_program program/controller/init/config.c program/controller/init/main.c program/controller/init/init.c program/controller/init/string.c
+build_sources_program program/controller/init/config.c program/controller/init/main.c program/controller/init/init.c program/controller/init/print.c program/controller/init/signal.c program/controller/init/string.c
 
 build_sources_documentation man
 
index aa68c3d04a33142d1932fa93396832422bc4db08..987872db6ac08e3ee8f53ace8fdc2b3e41bf7ee8 100644 (file)
@@ -17,6 +17,10 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
 
   f_console_parameter_t parameters[] = controller_console_parameter_t_initialize;
 
+  data.callback.print_message_help = 0;
+  data.callback.process_entry_setup = 0;
+  data.callback.process_thread_signal = &controller_thread_signal;
+
   data.program.parameters.array = parameters;
   data.program.parameters.used = controller_parameter_total_d;
   data.program.environment = envp;
index 52bf80dc0cf495cfb227b15a48305f802928b8b4..08aad9b2e1e566e4b47ecc22917559c66bf68383 100644 (file)
@@ -12,6 +12,8 @@
 
 // Controller includes.
 #include <program/controller/main/controller.h>
+#include <program/controller/init/print.h>
+#include <program/controller/init/signal.h>
 #include <program/controller/init/string.h>
 
 #ifdef __cplusplus
index c9d77a3ea41b3afc934f7bef811c87a63630bf52..02650d5d6e9d2b44c9f6831e8e3178082fdb913a 100644 (file)
@@ -25,13 +25,16 @@ 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.callback.print_message_help = &controller_init_print_message_help;
   data.callback.process_entry_setup = &controller_init_process_entry_setup;
+  data.callback.process_thread_signal = &controller_init_signal_thread;
+
   data.process.entry.pid = controller_entry_pid_disable_e;
   data.process.entry.show = controller_entry_show_init_e;
   data.process.mode = controller_process_mode_service_e;
-  data.setting.flag &= ~controller_main_flag_interruptible_d;
+  data.setting.flag |= controller_main_flag_interruptible_d;
 
-  fll_program_standard_set_up(&data.program);
+  controller_init_signal_set_up(&data);
 
   f_file_umask_get(&data.program.umask);
 
diff --git a/sources/c/program/controller/init/print.c b/sources/c/program/controller/init/print.c
new file mode 100644 (file)
index 0000000..fead7cc
--- /dev/null
@@ -0,0 +1,33 @@
+#include "init.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_controller_init__print_message_help_
+  f_status_t controller_init_print_message_help(fl_print_t * const print) {
+
+    if (!print) return F_status_set_error(F_output_not);
+
+    f_file_stream_lock(print->to);
+
+    controller_print_message_help_standard(print);
+
+    controller_print_message_help_note_simulate(print);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
+
+    controller_print_message_help_note_interrupt(print);
+    fl_print_format("  Using the %[%r%r%] parameter may prevent the init program from receiving reboot and shutdown commands via signals.%r%r", print->to, print->set->notable, f_console_symbol_long_normal_s, controller_long_uninterruptible_s, print->set->notable, f_string_eol_s, f_string_eol_s);
+
+    controller_print_message_help_note_pid(print);
+
+    f_file_stream_flush(print->to);
+    f_file_stream_unlock(print->to);
+
+    return F_okay;
+  }
+#endif // _di_controller_init__print_message_help_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/controller/init/print.h b/sources/c/program/controller/init/print.h
new file mode 100644 (file)
index 0000000..06f3408
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Controller
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides print functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _controller_init_print_h
+#define _controller_init_print_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print help specific to the Init program.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This requires print.custom to be controller_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 setting is NULL.
+ */
+#ifndef _di_controller_init__print_message_help_
+  extern f_status_t controller_init_print_message_help(fl_print_t * const print);
+#endif // _di_controller_init__print_message_help_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _controller_init_print_h
diff --git a/sources/c/program/controller/init/signal.c b/sources/c/program/controller/init/signal.c
new file mode 100644 (file)
index 0000000..0ff5693
--- /dev/null
@@ -0,0 +1,111 @@
+#include "init.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_controller_init_signal_set_up_
+  f_status_t controller_init_signal_set_up(controller_t * const main) {
+
+    if (!main) return F_status_set_error(F_parameter);
+
+    f_signal_set_empty(&main->program.signal.set);
+    f_signal_set_add(F_signal_abort, &main->program.signal.set);
+    f_signal_set_add(F_signal_broken_pipe, &main->program.signal.set);
+    f_signal_set_add(F_signal_child, &main->program.signal.set);
+    f_signal_set_add(F_signal_continue, &main->program.signal.set);
+    f_signal_set_add(F_signal_hangup, &main->program.signal.set);
+    f_signal_set_add(F_signal_interrupt, &main->program.signal.set);
+    f_signal_set_add(F_signal_keyboard_stop, &main->program.signal.set);
+    f_signal_set_add(F_signal_power_failure, &main->program.signal.set);
+    f_signal_set_add(F_signal_quit, &main->program.signal.set);
+    f_signal_set_add(F_signal_stop, &main->program.signal.set);
+    f_signal_set_add(F_signal_termination, &main->program.signal.set);
+    f_signal_set_add(F_signal_user_1, &main->program.signal.set);
+    f_signal_set_add(F_signal_user_2, &main->program.signal.set);
+
+    f_status_t status = f_signal_mask(SIG_BLOCK, &main->program.signal.set, 0);
+    if (F_status_is_error(status)) return status;
+
+    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(status)) {
+      f_signal_mask(SIG_UNBLOCK, &main->program.signal.set, 0);
+      f_signal_close(&main->program.signal);
+
+      return status;
+    }
+
+    // Unblock all other signals.
+    memset(&main->program.signal.set, 0, sizeof(sigset_t));
+
+    f_signal_set_fill(&main->program.signal.set);
+    f_signal_set_delete(F_signal_abort, &main->program.signal.set);
+    f_signal_set_delete(F_signal_broken_pipe, &main->program.signal.set);
+    f_signal_set_delete(F_signal_child, &main->program.signal.set);
+    f_signal_set_delete(F_signal_continue, &main->program.signal.set);
+    f_signal_set_delete(F_signal_hangup, &main->program.signal.set);
+    f_signal_set_delete(F_signal_interrupt, &main->program.signal.set);
+    f_signal_set_delete(F_signal_keyboard_stop, &main->program.signal.set);
+    f_signal_set_delete(F_signal_power_failure, &main->program.signal.set);
+    f_signal_set_delete(F_signal_quit, &main->program.signal.set);
+    f_signal_set_delete(F_signal_stop, &main->program.signal.set);
+    f_signal_set_delete(F_signal_termination, &main->program.signal.set);
+    f_signal_set_delete(F_signal_user_1, &main->program.signal.set);
+    f_signal_set_delete(F_signal_user_2, &main->program.signal.set);
+
+    status = f_signal_mask(SIG_UNBLOCK, &main->program.signal.set, 0);
+    if (F_status_is_error(status)) return status;
+
+    return F_okay;
+  }
+#endif // _di_controller_init_signal_set_up_
+
+#ifndef _di_controller_init_signal_thread_
+  void controller_init_signal_thread(controller_t * const main, const uint8_t is_normal) {
+
+    if (!main) return;
+    if (!controller_thread_is_enabled(&main->thread, is_normal)) return;
+    if (!(main->setting.flag & controller_main_flag_interruptible_d)) return;
+
+    siginfo_t information;
+    f_time_spec_t time = f_time_spec_t_initialize;
+
+    while (controller_thread_is_enabled(&main->thread, is_normal)) {
+
+      memset((void *) &information, 0, sizeof(siginfo_t));
+
+      controller_time_now(controller_thread_timeout_exit_ready_seconds_d, controller_thread_timeout_exit_ready_nanoseconds_d, &time);
+
+      // Allow thread to be interrupted and auto-cancelled while sleeping.
+      f_thread_cancel_state_set(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+
+      if (f_signal_wait_until(&main->program.signal.set, &time, &information) == F_time_out) continue;
+
+      // Prevent thread from being interrupted and auto-cancelled.
+      f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+
+      // Reap zombie processes.
+      if (information.si_signo == F_signal_child) {
+        // @todo verify that this process id is a valid child process.
+        // @todo send F_signal_terminate first?
+        // @todo a waitpid() needs to be performed to check to see how to handle the child signal.
+        //f_signal_send(F_signal_kill, information.si_pid);
+        // @todo move this to a function and identify any pid files and clear it from the process array (see calls like: status = controller_file_pid_read(instance->path_pids.array[j], &pid););
+      }
+
+      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) {
+        main->thread.signal = information.si_signo;
+
+        controller_thread_instance_cancel(main, is_normal, controller_thread_cancel_signal_e);
+
+        break;
+      }
+    } // while
+  }
+#endif // _di_controller_init_signal_thread_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/controller/init/signal.h b/sources/c/program/controller/init/signal.h
new file mode 100644 (file)
index 0000000..02b7e86
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Controller
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides signal functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _controller_init_signal_h
+#define _controller_init_signal_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform standard setup with custom signals.
+ *
+ * This is a modified version of fll_program_standard_set_up().
+ *
+ * @param main
+ *   The main program data.
+ *
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_signal_mask().
+ *   Errors (with error bit) from: f_signal_open().
+ *
+ * @see f_signal_mask()
+ * @see f_signal_open()
+ * @see f_signal_set_add()
+ * @see f_signal_set_delete()
+ * @see f_signal_set_empty()
+ * @see f_signal_set_fill()
+ */
+#ifndef _di_controller_init_signal_set_up_
+  extern f_status_t controller_init_signal_set_up(controller_t * const main);
+#endif // _di_controller_init_signal_set_up_
+
+/**
+ * Thread for handling signals/interrupts for the init program.
+ *
+ * @param main
+ *   The main program data.
+ *
+ *   Must not be NULL.
+ * @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 an Exit operation.
+ */
+#ifndef _di_controller_init_signal_thread_
+  extern void controller_init_signal_thread(controller_t * const main, const uint8_t is_normal);
+#endif // _di_controller_init_signal_thread_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _controller_init_signal_h
index 44fe04f8c21caef6283ada4b0ebc850f99c338e0..1799e175dc50c570a8c01bb4fd768afb356f9e5a 100644 (file)
@@ -51,16 +51,23 @@ extern "C" {
  * The Controller callbacks.
  *
  * Properties:
- *   - process_entry_setup: Perform any optional initialization on the entry.
+ *   - print_message_help:    Callback for printing the help message.
+ *   - process_entry_setup:   Perform any optional initialization on the entry.
+ *   - process_thread_signal: Handle signals for threaded operation.
  */
 #ifndef _di_controller_t_
   typedef struct {
+    f_status_t (*print_message_help)(fl_print_t * const print);
+
     f_status_t (*process_entry_setup)(controller_t * const main, controller_entry_t * const entry);
+    void (*process_thread_signal)(controller_t * const main, const uint8_t is_normal);
   } controller_callback_t;
 
   #define controller_callback_t_initialize \
     { \
       0, \
+      0, \
+      0, \
     }
 #endif // _di_controller_t_
 
index d02031485a27b7b3fb76274d3843ca1ddaf8eb5a..272e9c84ba8331be9bd69d5711f55b874d219ec7 100644 (file)
 #include <program/controller/main/print/warning/rule/action.h>
 #include <program/controller/main/print/warning/rule/item.h>
 #include <program/controller/main/print/warning/rule/setting.h>
-#include <program/controller/main/signal.h>
 #include <program/controller/main/status.h>
 #include <program/controller/main/time.h>
 #include <program/controller/main/thread/cleanup.h>
index 4b58787bece927c2fdaf591bb76a189f84636b18..8de44ad5d2d5c8e322a3adf464cc4ad01b9ded22 100644 (file)
@@ -5,12 +5,68 @@ extern "C" {
 #endif
 
 #ifndef _di_controller_print_message_help_
-  f_status_t controller_print_message_help(fl_print_t * const print, const uint8_t uninterrupt) {
+  f_status_t controller_print_message_help(fl_print_t * const print) {
 
     if (!print) return F_status_set_error(F_output_not);
 
     f_file_stream_lock(print->to);
 
+    controller_print_message_help_standard(print);
+
+    controller_print_message_help_note_simulate(print);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
+
+    controller_print_message_help_note_interrupt(print);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
+
+    controller_print_message_help_note_pid(print);
+
+    f_file_stream_flush(print->to);
+    f_file_stream_unlock(print->to);
+
+    return F_okay;
+  }
+#endif // _di_controller_print_message_help_
+
+#ifndef _di_controller_print_message_help_note_interrupt_
+  f_status_t controller_print_message_help_note_interrupt(fl_print_t * const print) {
+
+    if (!print) return F_status_set_error(F_output_not);
+
+    fl_print_format("  The default interrupt behavior is to operate as if the %[%r%r%] parameter is passed.%r", print->to, print->set->notable, f_console_symbol_long_normal_s, controller_long_interruptible_s, print->set->notable, f_string_eol_s);
+
+    return F_okay;
+  }
+#endif // _di_controller_print_message_help_note_interrupt_
+
+#ifndef _di_controller_print_message_help_note_pid_
+  f_status_t controller_print_message_help_note_pid(fl_print_t * const print) {
+
+    if (!print) return F_status_set_error(F_output_not);
+
+    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);
+
+    return F_okay;
+  }
+#endif // _di_controller_print_message_help_note_pid_
+
+#ifndef _di_controller_print_message_help_note_simulate_
+  f_status_t controller_print_message_help_note_simulate(fl_print_t * const print) {
+
+    if (!print) return F_status_set_error(F_output_not);
+
+    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", print->to, print->set->notable, f_console_symbol_long_normal_s, controller_long_validate_s, print->set->notable, f_string_eol_s);
+
+    return F_okay;
+  }
+#endif // _di_controller_print_message_help_note_simulate_
+
+#ifndef _di_controller_print_message_help_standard_
+  f_status_t controller_print_message_help_standard(fl_print_t * const print) {
+
+    if (!print) return F_status_set_error(F_output_not);
+
     fll_program_print_help_header(print, controller_program_name_long_s, controller_program_version_s);
 
     fll_program_print_help_option_standard(print);
@@ -31,19 +87,9 @@ extern "C" {
 
     fll_program_print_help_usage(print, controller_program_name_s, 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, uninterrupt ? 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_
+#endif // _di_controller_print_message_help_standard_
 
 #ifdef __cplusplus
 } // extern "C"
index a6ac3ead96e4e2aeb147825c177954dc482b7b86..75c2961c89533143450650dff33f4ee873897a1a 100644 (file)
@@ -25,9 +25,6 @@ extern "C" {
  *   This requires print.custom to be controller_t.
  *
  *   This does not alter print.custom.setting.state.status.
- * @param uninterrupt
- *   Set to F_true to print that the default behavior is uninterruptible.
- *   Otherwise, print that the default behavior is interruptible.
  *
  * @return
  *   F_okay on success.
@@ -36,9 +33,97 @@ extern "C" {
  *   F_output_not (with error bit) if setting is NULL.
  */
 #ifndef _di_controller_print_message_help_
-  extern f_status_t controller_print_message_help(fl_print_t * const print, const uint8_t uninterrupt);
+  extern f_status_t controller_print_message_help(fl_print_t * const print);
 #endif // _di_controller_print_message_help_
 
+/**
+ * Print interrupt note help.
+ *
+ * This expects the output to be already locked.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This requires print.custom to be controller_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 setting is NULL.
+ */
+#ifndef _di_controller_print_message_help_note_interrupt_
+  extern f_status_t controller_print_message_help_note_interrupt(fl_print_t * const print);
+#endif // _di_controller_print_message_help_note_interrupt_
+
+/**
+ * Print PID note help.
+ *
+ * This expects the output to be already locked.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This requires print.custom to be controller_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 setting is NULL.
+ */
+#ifndef _di_controller_print_message_help_note_pid_
+  extern f_status_t controller_print_message_help_note_pid(fl_print_t * const print);
+#endif // _di_controller_print_message_help_note_pid_
+
+/**
+ * Print simulate note help.
+ *
+ * This expects the output to be already locked.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This requires print.custom to be controller_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 setting is NULL.
+ */
+#ifndef _di_controller_print_message_help_note_simulate_
+  extern f_status_t controller_print_message_help_note_simulate(fl_print_t * const print);
+#endif // _di_controller_print_message_help_note_simulate_
+
+/**
+ * Print standard help parameters and usage without the additional notes.
+ *
+ * This expects the output to be already locked.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This requires print.custom to be controller_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 setting is NULL.
+ */
+#ifndef _di_controller_print_message_help_standard_
+  extern f_status_t controller_print_message_help_standard(fl_print_t * const print);
+#endif // _di_controller_print_message_help_standard_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 59e6153b3589e50a39519cb75160c3785b29e235..3b43b0cc5d2f72a2c0cd3cf23256fec99c073fe0 100644 (file)
@@ -78,7 +78,7 @@ extern "C" {
       fl_print_format(" %r", print->to, *string);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Session.
@@ -98,7 +98,7 @@ extern "C" {
       fl_print_format(" %r", print->to, *string, f_string_eol_s);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Show.
@@ -118,7 +118,7 @@ extern "C" {
       fl_print_format(" %r", print->to, *string, f_string_eol_s);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Pid.
@@ -141,7 +141,7 @@ extern "C" {
       fl_print_format(" %r", print->to, *string);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Pid File.
@@ -151,7 +151,7 @@ extern "C" {
       fl_print_format(" %r", print->to, main->process.path_pid);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Control.
@@ -161,7 +161,7 @@ extern "C" {
       fl_print_format(" %Q", print->to, main->process.path_control);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Control Has.
@@ -171,7 +171,7 @@ extern "C" {
       fl_print_format(" %r", print->to, controller_readonly_s);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Control User.
@@ -181,7 +181,7 @@ extern "C" {
       fl_print_format(" %u", print->to, (unsigned int) main->process.control.user);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Control Group.
@@ -191,7 +191,7 @@ extern "C" {
       fl_print_format(" %u", print->to, (unsigned int) main->process.control.group);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Control Mode.
@@ -203,7 +203,7 @@ extern "C" {
       }
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Timeout: Exit.
@@ -213,7 +213,7 @@ extern "C" {
       fl_print_format(" %ul", print->to, entry->timeout_exit, f_string_eol_s);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Timeout: Kill.
@@ -223,7 +223,7 @@ extern "C" {
       fl_print_format(" %ul", print->to, entry->timeout_kill, f_string_eol_s);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Timeout: Start.
@@ -233,7 +233,7 @@ extern "C" {
       fl_print_format(" %ul", print->to, entry->timeout_start, f_string_eol_s);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Timeout: Stop.
@@ -243,7 +243,7 @@ extern "C" {
       fl_print_format(" %ul", print->to, entry->timeout_stop, f_string_eol_s);
     }
 
-    fl_print_format("%r", print->to, f_string_eol_s);
+    f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
     // Define.
@@ -382,7 +382,7 @@ extern "C" {
             }
           }
 
-          fl_print_format("%r", print->to, f_string_eol_s);
+          f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
           // Parameters.
@@ -393,7 +393,7 @@ extern "C" {
               fl_print_format(" %Q", print->to, action->parameters.array[0], f_string_eol_s);
             }
 
-            fl_print_format("%r", print->to, f_string_eol_s);
+            f_print_dynamic_raw(f_string_eol_s, print->to);
           }
           else if (raw) {
             for (k = 0; k < action->parameters.used; ++k) {
@@ -409,7 +409,7 @@ extern "C" {
               fl_print_format(" %Q", print->to, action->parameters.array[0], f_string_eol_s);
             }
 
-            fl_print_format("%r", print->to, f_string_eol_s);
+            f_print_dynamic_raw(f_string_eol_s, print->to);
 
 
             // Parameter, File.
@@ -419,7 +419,7 @@ extern "C" {
               fl_print_format(" %Q", print->to, action->parameters.array[1], f_string_eol_s);
             }
 
-            fl_print_format("%r", print->to, f_string_eol_s);
+            f_print_dynamic_raw(f_string_eol_s, print->to);
           }
 
           fl_print_format("  }%r", print->to, f_string_eol_s);
index 76dd0eb782039d3a77a037ee2a50ff71a7c9d589..72bbd81fe1408f2523e17e605749c2fb0f094dee 100644 (file)
@@ -150,7 +150,7 @@ extern "C" {
         }
       } // for
 
-      fl_print_format("%r", print->to, f_string_eol_s);
+      f_print_dynamic_raw(f_string_eol_s, print->to);
     }
     else {
       fl_print_format("  %[%r%] %Q%r", print->to, print->set->important, controller_engine_s, print->set->important, rule->engine, f_string_eol_s);
index c9dc186426aceecd747a54bb751b410c01adb9fb..7ce4b081a9c329bc6cc39fae2d1d3205983ca2fb 100644 (file)
@@ -13,7 +13,12 @@ extern "C" {
 
     if (main->setting.flag & controller_main_flag_version_copyright_help_d) {
       if (main->setting.flag & controller_main_flag_help_d) {
-        controller_print_message_help(&main->program.message, F_false);
+        if (main->callback.print_message_help) {
+          main->callback.print_message_help(&main->program.message);
+        }
+        else {
+          controller_print_message_help(&main->program.message);
+        }
       }
       else if (main->setting.flag & controller_main_flag_version_d) {
         fll_program_print_version(&main->program.message, controller_program_version_s);
index 9d974f2dcacd96f4d9329511524d343a5374f4b7..5ef9a44eabf871fb092a0c11d14d6c976fb6b8ba 100644 (file)
@@ -19,7 +19,8 @@ extern "C" {
 /**
  * Execute main program process, starting all threads, waiting on threads, and handling requests.
  *
- * If main.signal is non-zero, then this blocks and handles the following signals:
+ * If main.signal is non-zero, then this blocks and handles the signals defined in the main.program.signal.set.
+ * The standard signals are (see the init program for its modifications on main.program.signal.set):
  *   - F_signal_abort
  *   - F_signal_broken_pipe
  *   - F_signal_hangup
index 842e1f2cfb5d9af4c338a111dfb0dde4fb1a2d54..7a5974115fd01b57d479b7900eb1d31cc90c31ae 100644 (file)
@@ -84,7 +84,9 @@ extern "C" {
 
     f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
 
-    controller_thread_signal((controller_t *) argument, F_true);
+    if (argument && ((controller_t *) argument)->callback.process_thread_signal) {
+      ((controller_t *) argument)->callback.process_thread_signal((controller_t *) argument, F_true);
+    }
 
     return 0;
   }
@@ -95,7 +97,9 @@ extern "C" {
 
     f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
 
-    controller_thread_signal((controller_t *) argument, F_false);
+    if (argument && ((controller_t *) argument)->callback.process_thread_signal) {
+      ((controller_t *) argument)->callback.process_thread_signal((controller_t *) argument, F_false);
+    }
 
     return 0;
   }