]> Kevux Git Server - fll/commitdiff
Update: implement signal support, rewrite execute functions to accomodate signals...
authorKevin Day <thekevinday@gmail.com>
Sun, 13 Sep 2020 18:32:55 +0000 (13:32 -0500)
committerKevin Day <thekevinday@gmail.com>
Sun, 13 Sep 2020 18:32:55 +0000 (13:32 -0500)
42 files changed:
build/level_0/settings
build/monolithic/settings
build/scripts/bootstrap-example.sh
level_0/f_signal/c/signal.c [new file with mode: 0644]
level_0/f_signal/c/signal.h [new file with mode: 0644]
level_0/f_signal/data/build/defines [new file with mode: 0644]
level_0/f_signal/data/build/dependencies [new file with mode: 0644]
level_0/f_signal/data/build/settings [new file with mode: 0644]
level_0/f_socket/c/socket.c
level_0/f_socket/c/socket.h
level_0/f_status/c/status.h
level_1/fl_status/c/status.c
level_1/fl_status/c/status.h
level_2/fll_execute/c/execute.c
level_2/fll_execute/c/execute.h
level_2/fll_execute/data/build/dependencies
level_2/fll_execute/data/build/settings
level_2/fll_file/c/file.h
level_2/fll_status/c/status.c
level_3/fake/c/fake.c
level_3/fake/c/fake.h
level_3/fake/c/main.c
level_3/fake/c/private-build.c
level_3/fake/c/private-clean.c
level_3/fake/c/private-fake.c
level_3/fake/c/private-fake.h
level_3/fake/c/private-make.c
level_3/fake/c/private-skeleton.c
level_3/fake/data/build/dependencies
level_3/fake/data/build/settings
level_3/firewall/c/firewall.c
level_3/firewall/c/private-firewall.c
level_3/firewall/data/build/settings
level_3/fss_basic_list_read/data/build/settings
level_3/fss_basic_list_write/data/build/settings
level_3/fss_basic_read/data/build/settings
level_3/fss_basic_write/data/build/settings
level_3/fss_extended_list_read/data/build/settings
level_3/fss_extended_read/data/build/settings
level_3/fss_extended_write/data/build/settings
level_3/fss_status_code/data/build/settings
level_3/init/data/build/settings

index b8ad29bc9b27bfefb4984c25a85b405803bd877c..0bb23e680480ab9f4de3f0f2c240c0d5faa380f3 100644 (file)
@@ -20,9 +20,9 @@ build_indexer ar
 build_language c
 build_libraries -lc
 build_libraries-level
-build_sources_library account.c console.c conversion.c directory.c private-directory.c environment.c private-environment.c file.c private-file.c fss.c iki.c memory.c path.c private-path.c pipe.c print.c serialize.c private-serialize.c socket.c utf.c private-utf.c
+build_sources_library account.c console.c conversion.c directory.c private-directory.c environment.c private-environment.c file.c private-file.c fss.c iki.c memory.c path.c private-path.c pipe.c print.c serialize.c private-serialize.c signal.c socket.c utf.c private-utf.c
 build_sources_program
-build_sources_headers account.h color.h console.h conversion.h directory.h directory_type.h environment.h file.h fss.h fss-common.h fss-named.h fss-nest.h fss-quoted.h fss-set.h iki.h iki-common.h memory.h memory-structure.h path.h pipe.h print.h serialize.h socket.h status.h status_array.h string.h string_common.h string_dynamic.h string_map.h string_quantity.h string_range.h type.h type_array.h utf.h utf-common.h
+build_sources_headers account.h color.h console.h conversion.h directory.h directory_type.h environment.h file.h fss.h fss-common.h fss-named.h fss-nest.h fss-quoted.h fss-set.h iki.h iki-common.h memory.h memory-structure.h path.h pipe.h print.h serialize.h signal.h socket.h status.h status_array.h string.h string_common.h string_dynamic.h string_map.h string_quantity.h string_range.h type.h type_array.h utf.h utf-common.h
 build_sources_script
 build_sources_setting
 build_script yes
index 3bc7f4f52264f200c111b93d612f98369ffbab2d..393edfcc99bbee778dfdded04ac69f15c844072e 100644 (file)
@@ -20,9 +20,9 @@ build_indexer ar
 build_language c
 build_libraries -lc
 build_libraries-monolithic
-build_sources_library level_0/account.c level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/serialize.c level_0/private-serialize.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/path.c level_2/program.c level_2/status.c
+build_sources_library level_0/account.c level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/serialize.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/path.c level_2/program.c level_2/status.c
 build_sources_program
-build_sources_headers level_0/account.h level_0/color.h level_0/console.h level_0/conversion.h level_0/directory.h level_0/directory_type.h level_0/environment.h level_0/file.h level_0/fss.h level_0/fss-common.h level_0/fss-named.h level_0/fss-nest.h level_0/fss-quoted.h level_0/fss-set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory-structure.h level_0/path.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/socket.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string_common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/path.h level_2/program.h level_2/status.h
+build_sources_headers level_0/account.h level_0/color.h level_0/console.h level_0/conversion.h level_0/directory.h level_0/directory_type.h level_0/environment.h level_0/file.h level_0/fss.h level_0/fss-common.h level_0/fss-named.h level_0/fss-nest.h level_0/fss-quoted.h level_0/fss-set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory-structure.h level_0/path.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/signal.h level_0/socket.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string_common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/path.h level_2/program.h level_2/status.h
 build_sources_script
 build_sources_setting
 build_script yes
index 0e023971b80db088f200e9d3811d99cbc93b0da8..1d2c66ffc8ec95662541b51707e21aa58b20ba00 100644 (file)
@@ -23,7 +23,7 @@ if [[ $1 == "individual" ]] ; then
   bash build/scripts/package.sh build -i
 
   if [[ $? -eq 0 ]] ; then
-    for i in f_type f_status f_memory f_string f_utf f_account f_color f_console f_conversion f_directory f_environment f_file f_fss f_iki f_path f_pipe f_print f_serialize f_socket fl_color fl_console fl_conversion fl_directory fl_environment fl_fss fl_iki fl_print fl_status fl_string fl_utf fl_utf_file fll_execute fll_file fll_fss fll_path fll_program fll_status ; do
+    for i in f_type f_status f_memory f_string f_utf f_account f_color f_console f_conversion f_directory f_environment f_file f_fss f_iki f_path f_pipe f_print f_serialize f_signal f_socket fl_color fl_console fl_conversion fl_directory fl_environment fl_fss fl_iki fl_print fl_status fl_string fl_utf fl_utf_file fll_execute fll_file fll_fss fll_path fll_program fll_status ; do
       echo && echo "Processing $i." &&
 
       cd package/individual/$i-$2/ &&
diff --git a/level_0/f_signal/c/signal.c b/level_0/f_signal/c/signal.c
new file mode 100644 (file)
index 0000000..c47f06e
--- /dev/null
@@ -0,0 +1,237 @@
+#include "signal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_f_signal_close_
+  f_return_status f_signal_close(f_signal_t *signal) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!signal) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (!signal->id) {
+      return F_data_not;
+    }
+
+    if (close(signal->id) < 0) {
+      if (errno == EBADF) return F_status_set_error(F_descriptor);
+      if (errno == EDQUOT) return F_status_set_error(F_filesystem_quota_block);
+      if (errno == EINTR) return F_status_set_error(F_interrupted);
+      if (errno == EIO) return F_status_set_error(F_input_output);
+      if (errno == ENOSPC) return F_status_set_error(F_parameter);
+
+      return F_status_set_error(F_failure);
+    }
+
+    signal->id = 0;
+    return F_none;
+  }
+#endif // _di_f_signal_close_
+
+#ifndef _di_f_signal_open_
+  f_return_status f_signal_open(f_signal_t *signal) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!signal) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    int result = signalfd(-1, &signal->set, signal->flags);
+
+    if (result < 0) {
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+      if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max);
+      if (errno == ENFILE) return F_status_set_error(F_file_open_max);
+      if (errno == ENODEV) return F_status_set_error(F_device);
+      if (errno == ENOMEM) return F_status_set_error(F_memory_out);
+
+      return F_status_set_error(F_failure);
+    }
+
+    signal->id = result;
+    return F_none;
+  }
+#endif // _di_f_signal_open_
+
+#ifndef _di_f_signal_read_
+  f_return_status f_signal_read(const f_signal_t signal, struct signalfd_siginfo *information) {
+
+    if (!signal.id) {
+      return F_data_not;
+    }
+
+    struct pollfd data_poll;
+    memset(&data_poll, 0, sizeof(struct pollfd));
+
+    data_poll.fd = signal.id;
+    data_poll.events = POLLIN;
+
+    struct pollfd polls[] = { data_poll };
+
+    const int result = poll(polls, 1, 0);
+
+    if (result < 0) {
+      if (errno == EFAULT) return F_status_set_error(F_buffer);
+      if (errno == EINTR) return F_status_set_error(F_interrupted);
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+      if (errno == ENOMEM) return F_status_set_error(F_memory_out);
+
+      return F_status_set_error(F_failure);
+    }
+    else if (result) {
+      const ssize_t total = read(signal.id, information, sizeof(struct signalfd_siginfo));
+
+      if (total < 0) {
+        if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block);
+        if (errno == EBADF) return F_status_set_error(F_descriptor);
+        if (errno == EFAULT) return F_status_set_error(F_buffer);
+        if (errno == EINTR) return F_status_set_error(F_interrupted);
+        if (errno == EINVAL) return F_status_set_error(F_parameter);
+        if (errno == EIO) return F_status_set_error(F_input_output);
+        if (errno == EISDIR) return F_status_set_error(F_file_type_directory);
+
+        return F_status_set_error(F_failure);
+      }
+
+      return F_signal;
+    }
+
+    return F_none;
+  }
+#endif // _di_f_signal_read_
+
+#ifndef _di_f_signal_set_add_
+  f_return_status f_signal_set_add(const int signal, sigset_t *set) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!set) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (sigaddset(set, signal) < 0) {
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+
+      return F_status_set_error(F_failure);
+    }
+
+    return F_none;
+  }
+#endif // _di_f_signal_set_add_
+
+#ifndef _di_f_signal_set_delete_
+  f_return_status f_signal_set_delete(const int signal, sigset_t *set) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!set) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (sigdelset(set, signal) < 0) {
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+
+      return F_status_set_error(F_failure);
+    }
+
+    return F_none;
+  }
+#endif // _di_f_signal_set_delete_
+
+#ifndef _di_f_signal_set_empty_
+  f_return_status f_signal_set_empty(sigset_t *set) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!set) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (sigemptyset(set) < 0) {
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+
+      return F_status_set_error(F_failure);
+    }
+
+    return F_none;
+  }
+#endif // _di_f_signal_set_empty_
+
+#ifndef _di_f_signal_set_fill_
+  f_return_status f_signal_set_fill(sigset_t *set) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!set) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (sigfillset(set) < 0) {
+      if (errno == EFAULT) return F_status_set_error(F_buffer);
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+
+      return F_status_set_error(F_failure);
+    }
+
+    return F_none;
+  }
+#endif // _di_f_signal_set_fill_
+
+#ifndef _di_f_signal_set_get_
+  f_return_status f_signal_set_get(sigset_t *set) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!set) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    #ifdef _threadsafe_f_signal_handle
+      #define f_macro_signal_set_get_sigmask pthread_sigmask
+    #else
+      #define f_macro_signal_set_get_sigmask sigprocmask
+    #endif
+
+    if (f_macro_signal_set_get_sigmask(0, NULL, set) < 0) {
+      if (errno == EFAULT) return F_status_set_error(F_buffer);
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+
+      return F_status_set_error(F_failure);
+    }
+
+    #undef f_macro_signal_set_get_sigmask
+
+    return F_none;
+  }
+#endif // _di_f_signal_set_get_
+
+#ifndef _di_f_signal_set_handle_
+  f_return_status f_signal_set_handle(const int how, const sigset_t *set) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!set) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    #ifdef _threadsafe_f_signal_handle
+      #define f_macro_signal_set_get_sigmask pthread_sigmask
+    #else
+      #define f_macro_signal_set_get_sigmask sigprocmask
+    #endif
+
+    if (f_macro_signal_set_get_sigmask(how, set, NULL) < 0) {
+      if (errno == EFAULT) return F_status_set_error(F_buffer);
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+
+      return F_status_set_error(F_failure);
+    }
+
+    #undef f_macro_signal_set_get_sigmask
+
+    return F_none;
+  }
+#endif // _di_f_signal_set_handle_
+
+#ifndef _di_f_signal_set_has_
+  f_return_status f_signal_set_has(const int signal, const sigset_t *set) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!set) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    const int result = sigismember(set, signal);
+
+    if (result < 0) {
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+
+      return F_status_set_error(F_failure);
+    }
+
+    return result ? F_true : F_false;
+  }
+#endif // _di_f_signal_set_has_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_signal/c/signal.h b/level_0/f_signal/c/signal.h
new file mode 100644 (file)
index 0000000..14b8b6c
--- /dev/null
@@ -0,0 +1,271 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Signal
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * Provides signal processing functionality, such as signal variable handling.
+ */
+#ifndef _F_signal_h
+#define _F_signal_h
+
+// libc includes
+#include <poll.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/signalfd.h>
+#include <unistd.h>
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This holds a signal type.
+ *
+ * flags: The signal flags associated with this.
+ * id:    The signal descriptor.
+ * set:   The signal set.
+ */
+#ifndef _di_f_signal_t_
+  typedef struct {
+    int flags;
+    int id;
+    sigset_t set;
+  } f_signal_t;
+
+  #define f_signal_t_initialize {0, 0, { 0 } }
+
+  #define f_macro_signal_t_initialize(flags, id, set) { flags, id, set }
+#endif // _di_f_signal_t_
+
+/**
+ * This holds a set of signals to block and a set of signals to unblock.
+ *
+ * block:     The signal flags to block.
+ * block_not: The signal flags to unblock.
+ */
+#ifndef _di_f_signal_how_t_
+  typedef struct {
+    sigset_t block;
+    sigset_t block_not;
+  } f_signal_how_t;
+
+  #define f_signal_how_t_initialize { { 0 } , { 0 } }
+
+  #define f_macro_signal_how_t_initialize(block, block_not) { block, block_not }
+#endif // _di_f_signal_how_t_
+
+/**
+ * Close an open signal descriptor.
+ *
+ * The signal.id is set to 0 on success.
+ *
+ * @param signal
+ *   The signal settings.
+ *
+ * @return
+ *   F_none on success.
+ *   F_data_not on success, but no descriptor was provided to close.
+ *   F_descriptor (with error bit) if id is an invalid descriptor.
+ *   F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted.
+ *   F_input_output (with error bit) if an I/O error occurred.
+ *   F_interrupted (with error bit) when program received an interrupt signal, halting operation.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see close()
+ */
+#ifndef _di_f_signal_close_
+  extern f_return_status f_signal_close(f_signal_t *signal);
+#endif // _di_f_signal_close_
+
+/**
+ * Open a signal descriptor, listening for the given set of signals.
+ *
+ * The signal.id is assigned with the signal descriptor on success.
+ *
+ * @param signal
+ *   The signal settings.
+ *
+ * @return
+ *   F_none on success but no signal found.
+ *   F_device (with error bit) if could not mount the internal inode device.
+ *   F_file_descriptor_max (with error bit) if max file descriptors was reached.
+ *   F_memory_out (with error bit) if out of memory.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see signalfd()
+ */
+#ifndef _di_f_signal_open_
+  extern f_return_status f_signal_open(f_signal_t *signal);
+#endif // _di_f_signal_open_
+
+/**
+ * Read a current process signal, if one exists, in a non-blocking manner.
+ *
+ * @param signal
+ *   The signal settings.
+ * @param information
+ *   The signal data to be populated if a signal is found during read.
+ *
+ * @return
+ *   F_none on success but no signal found.
+ *   F_data_not on success, but no descriptor was provided to read.
+ *   F_signal on success and signal found.
+ *   F_block (with error bit) if file descriptor is set to non-block and the read would result in a blocking operation.
+ *   F_buffer (with error bit) if the buffer is invalid.
+ *   F_descriptor (with error bit) if the signal descriptor is invalid.
+ *   F_interrupted (with error bit) if interrupt was received.
+ *   F_memory_out (with error bit) on out of memory.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_input_output (with error bit) on I/O error.
+ *   F_file_type_directory (with error bit) if file descriptor represents a directory.
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see poll()
+ * @see read()
+ */
+#ifndef _di_f_signal_read_
+  extern f_return_status f_signal_read(const f_signal_t signal, struct signalfd_siginfo *information);
+#endif // _di_f_signal_read_
+
+/**
+ * Add a signal to the given set of signals.
+ *
+ * @param signal
+ *   The signal to add.
+ * @param set
+ *   The set of signals to add to.
+ *
+ * @return
+ *   F_none on success but no signal found.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see sigaddset()
+ */
+#ifndef _di_f_signal_set_add_
+  extern f_return_status f_signal_set_add(const int signal, sigset_t *set);
+#endif // _di_f_signal_set_add_
+
+/**
+ * Delete a signal from a given set of signals.
+ *
+ * @param signal
+ *   The signal to add.
+ * @param set
+ *   The set of signals to delete from.
+ *
+ * @return
+ *   F_none on success but no signal found.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see sigdelset()
+ */
+#ifndef _di_f_signal_set_delete_
+  extern f_return_status f_signal_set_delete(const int signal, sigset_t *set);
+#endif // _di_f_signal_set_delete_
+
+/**
+ * Clear a given set of signals.
+ *
+ * @param set
+ *   The set of signals to clear.
+ *
+ * @return
+ *   F_none on success but no signal found.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see sigemptyset()
+ */
+#ifndef _di_f_signal_set_empty_
+  extern f_return_status f_signal_set_empty(sigset_t *set);
+#endif // _di_f_signal_set_empty_
+
+/**
+ * Add all known signals to a given set of signals.
+ *
+ * @param set
+ *   The set of signals to fully populate.
+ *
+ * @return
+ *   F_none on success but no signal found.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see sigfillset()
+ */
+#ifndef _di_f_signal_set_fill_
+  extern f_return_status f_signal_set_fill(sigset_t *set);
+#endif // _di_f_signal_set_fill_
+
+/**
+ * Get the current signal set in use.
+ *
+ * @param set
+ *   The current set of signals being handled.
+ *
+ * @return
+ *   F_none on success but no signal found.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see pthread_sigmask()
+ */
+#ifndef _di_f_signal_set_get_
+  extern f_return_status f_signal_set_get(sigset_t *set);
+#endif // _di_f_signal_set_get_
+
+/**
+ * Designate how to handle or not handle a set of signals designated by the set.
+ *
+ * @param how
+ *   How to process the signal, such as SIG_BLOCK, SIG_UNBLOCK, or SIG_SETMASK.
+ * @param set
+ *   The set of signals to handle.
+ *
+ * @return
+ *   F_none on success but no signal found.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see pthread_sigmask()
+ */
+#ifndef _di_f_signal_set_handle_
+  extern f_return_status f_signal_set_handle(const int how, const sigset_t *set);
+#endif // _di_f_signal_set_handle_
+
+/**
+ * Check to see if the given signal set has a given signal.
+ *
+ * @param signal
+ *   The signal to search for.
+ * @param set
+ *   The set of signals to search in.
+ *
+ * @return
+ *   F_true if signal is found.
+ *   F_false if signal is not found.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see sigismember()
+ */
+#ifndef _di_f_signal_set_has_
+  extern f_return_status f_signal_set_has(const int signal, const sigset_t *set);
+#endif // _di_f_signal_set_has_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _F_signal_h
diff --git a/level_0/f_signal/data/build/defines b/level_0/f_signal/data/build/defines
new file mode 100644 (file)
index 0000000..3f4bf61
--- /dev/null
@@ -0,0 +1,3 @@
+# fss-0000
+
+_threadsafe_f_signal_handle Enable use of pthread_sigmask() instead of sigprocmask() in appropriate f_signal_*() functions.
diff --git a/level_0/f_signal/data/build/dependencies b/level_0/f_signal/data/build/dependencies
new file mode 100644 (file)
index 0000000..d9c4b77
--- /dev/null
@@ -0,0 +1,4 @@
+# fss-0000
+
+f_type
+f_status
diff --git a/level_0/f_signal/data/build/settings b/level_0/f_signal/data/build/settings
new file mode 100644 (file)
index 0000000..e198b2c
--- /dev/null
@@ -0,0 +1,56 @@
+# fss-0001
+
+project_name f_signal
+
+version_major 0
+version_minor 5
+version_micro 0
+version_target major
+
+environment
+
+process_pre
+process_post
+
+modes individual
+modes_default individual
+
+build_compiler gcc
+build_indexer ar
+build_language c
+build_libraries -lc
+build_libraries-individual
+build_sources_library signal.c
+build_sources_program
+build_sources_headers signal.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+path_headers level_0
+path_library_script script
+path_library_shared shared
+path_library_static static
+path_program_script script
+path_program_shared shared
+path_program_static static
+path_sources
+path_standard yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+defines_all
+#defines_all -D_threadsafe_f_signal_handle
+defines_static
+defines_shared
+
+flags_all -z now -g
+#flags_all -z now -g -pthread
+flags_shared
+flags_static
+flags_library -fPIC
+flags_program -fPIE
index f61d5845d7911af459c905dea7be34acb970685d..603c319c551c0679736d3cfbd642bd5f13f2ed2a 100644 (file)
@@ -6,22 +6,24 @@ extern "C"{
 
 #ifndef _di_f_socket_file_bind_
   f_return_status f_socket_file_bind(const f_string_t path, const int id, struct sockaddr_un *address) {
+
     memset(&address, 0, sizeof(struct sockaddr_un));
     address->sun_family = AF_UNIX;
+
     strncpy(address->sun_path, path, sizeof(address->sun_path) - 1);
 
     if (bind(id, (struct sockaddr *) address, sizeof(struct sockaddr_un)) < 0) {
       if (errno == EACCES) return F_status_set_error(F_access_denied);
-      else if (errno == EADDRINUSE) return F_status_set_error(F_busy_address);
-      else if (errno == EADDRNOTAVAIL) return F_status_set_error(F_unavailable_address);
-      else if (errno == EFAULT) return F_status_set_error(F_buffer);
-      else if (errno == EINVAL) return F_status_set_error(F_busy_socket);
-      else if (errno == ELOOP) return F_status_set_error(F_loop);
-      else if (errno == ENAMETOOLONG) return F_status_set_error(F_string_too_large);
-      else if (errno == ENOENT) return F_status_set_error(F_file_found_not);
-      else if (errno == ENOMEM) return F_status_set_error(F_memory_out);
-      else if (errno == ENOTDIR) return F_status_set_error(F_directory_found_not);
-      else if (errno == ENOTSOCK) return F_status_set_error(F_descriptor);
+      if (errno == EADDRINUSE) return F_status_set_error(F_busy_address);
+      if (errno == EADDRNOTAVAIL) return F_status_set_error(F_unavailable_address);
+      if (errno == EFAULT) return F_status_set_error(F_buffer);
+      if (errno == EINVAL) return F_status_set_error(F_busy_socket);
+      if (errno == ELOOP) return F_status_set_error(F_loop);
+      if (errno == ENAMETOOLONG) return F_status_set_error(F_string_too_large);
+      if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+      if (errno == ENOMEM) return F_status_set_error(F_memory_out);
+      if (errno == ENOTDIR) return F_status_set_error(F_directory_found_not);
+      if (errno == ENOTSOCK) return F_status_set_error(F_descriptor);
 
       return F_status_set_error(F_failure);
     }
@@ -35,9 +37,9 @@ extern "C"{
 
     if (listen(id, max_backlog) < 0) {
       if (errno == EADDRINUSE) return F_status_set_error(F_busy_address);
-      else if (errno == EBADF) return F_status_set_error(F_file_descriptor);
-      else if (errno == ENOTSOCK) return F_status_set_error(F_descriptor);
-      else if (errno == EOPNOTSUPP) return F_status_set_error(F_unsupported);
+      if (errno == EBADF) return F_status_set_error(F_file_descriptor);
+      if (errno == ENOTSOCK) return F_status_set_error(F_descriptor);
+      if (errno == EOPNOTSUPP) return F_status_set_error(F_unsupported);
 
       return F_status_set_error(F_failure);
     }
@@ -48,33 +50,29 @@ extern "C"{
 
 #ifndef _di_f_socket_close_client_
   f_return_status f_socket_close_client(const int id, const unsigned short action) {
-    unsigned int error_code = 0;
+    int result = 0;
 
     if (action == f_socket_close_fast) {
-      if (close(id) < 0) {
-        error_code = errno;
-      }
+      result = close(id);
     }
     else {
       if (action == f_socket_close_read || action == f_socket_close_write || action == f_socket_close_read_write) {
-        if (shutdown(id, action) < 0) {
-          error_code = errno;
-        }
+        result = shutdown(id, action);
       }
       else {
         return F_status_set_error(F_unsupported);
       }
     }
 
-    if (error_code > 0) {
-      if (error_code == EBADF) return F_status_set_error(F_file_descriptor);
-      else if (error_code == EDQUOT) return F_status_set_error(F_filesystem_quota_block);
-      else if (error_code == EINTR) return F_status_set_error(F_interrupted);
-      else if (error_code == EINVAL) return F_status_set_error(F_value);
-      else if (error_code == EIO) return F_status_set_error(F_input_output);
-      else if (error_code == ENOTCONN) return F_connected_not;
-      else if (error_code == ENOTSOCK) return F_status_set_error(F_descriptor);
-      else if (error_code == ENOSPC) return F_status_set_error(F_parameter);
+    if (result < 0) {
+      if (errno == EBADF) return F_status_set_error(F_file_descriptor);
+      if (errno == EDQUOT) return F_status_set_error(F_filesystem_quota_block);
+      if (errno == EINTR) return F_status_set_error(F_interrupted);
+      if (errno == EINVAL) return F_status_set_error(F_value);
+      if (errno == EIO) return F_status_set_error(F_input_output);
+      if (errno == ENOTCONN) return F_connected_not;
+      if (errno == ENOTSOCK) return F_status_set_error(F_descriptor);
+      if (errno == ENOSPC) return F_status_set_error(F_parameter);
 
       return F_status_set_error(F_failure);
     }
index 2bbe77e49362d19386fd825c4756b4b31cb9473f..b6d01f18a417d2c9581a549103b2d10f642b231d 100644 (file)
@@ -65,6 +65,7 @@ extern "C"{
  *   F_name (with error bit) on path name error.
  *   F_string_too_large (with error bit) if string is too large to store in the buffer.
  *   F_unavailable_address (with error bit) if address is unavailable (is non-existent or not local).
+ *   F_failure (with error bit) for any other error.
  *
  * @see bind()
  */
@@ -87,6 +88,7 @@ extern "C"{
  *   F_descriptor (with error bit) if the id is not a socket descriptor.
  *   F_file_descriptor (with error bit) if id is an invalid descriptor.
  *   F_unsupported (with error bit) if this socket does not support the listen() operation.
+ *   F_failure (with error bit) for any other error.
  *
  * @see listen()
  */
@@ -115,6 +117,7 @@ extern "C"{
  *   F_parameter (with error bit) if a parameter is invalid.
  *   F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached).
  *   F_unsupported (with error bit) if this socket does not support the listen() operation.
+ *   F_failure (with error bit) for any other error.
  *
  * @see close()
  * @see shutdown()
index 325d537a778acf6b94aea6f0638ab3e496fcf74c..4424e30e49f3a424f191f3ba853bcbc6730b4d9f 100644 (file)
@@ -161,6 +161,7 @@ extern "C" {
       F_exist_not,
       F_failure,
       F_fork,
+      F_found,
       F_incomplete,
       F_input,
       F_input_output,
@@ -183,6 +184,8 @@ extern "C" {
       F_recurse,
       F_relative,
       F_search,
+      F_signal,
+      F_space,
       F_space_not,
       F_stop,
       F_syntax,
index f65cd3cc004e62963c7580932d21a4ad7238b581..ac6992ab8ad218f4c7320cdcc6dec0bec7073d59 100644 (file)
@@ -269,6 +269,9 @@ extern "C" {
         case F_fork:
           *string = FL_status_string_fork;
           break;
+        case F_found:
+          *string = FL_status_string_found;
+          break;
         case F_incomplete:
           *string = FL_status_string_incomplete;
           break;
@@ -335,6 +338,12 @@ extern "C" {
         case F_search:
           *string = FL_status_string_search;
           break;
+        case F_signal:
+          *string = FL_status_string_signal;
+          break;
+        case F_space:
+          *string = FL_status_string_space;
+          break;
         case F_space_not:
           *string = FL_status_string_space_not;
           break;
index 7678d1a096b7b8718cb03d511840b343155b81b2..a1c0e615488b1e596bb018bb1957a5a444b6886d 100644 (file)
@@ -181,6 +181,7 @@ extern "C" {
     #define FL_status_string_exist_not        "F_exist_not"
     #define FL_status_string_failure          "F_failure"
     #define FL_status_string_fork             "F_fork"
+    #define FL_status_string_found            "F_found"
     #define FL_status_string_incomplete       "F_incomplete"
     #define FL_status_string_input            "F_input"
     #define FL_status_string_input_output     "F_input_output"
@@ -203,6 +204,8 @@ extern "C" {
     #define FL_status_string_recurse          "F_recurse"
     #define FL_status_string_relative         "F_relative"
     #define FL_status_string_search           "F_search"
+    #define FL_status_string_signal           "F_signal"
+    #define FL_status_string_space            "F_space"
     #define FL_status_string_space_not        "F_space_not"
     #define FL_status_string_stop             "F_stop"
     #define FL_status_string_syntax           "F_syntax"
@@ -232,6 +235,7 @@ extern "C" {
     #define FL_status_string_exist_not_length        11
     #define FL_status_string_failure_length          9
     #define FL_status_string_fork_length             6
+    #define FL_status_string_found_length            7
     #define FL_status_string_incomplete_length       12
     #define FL_status_string_input_length            7
     #define FL_status_string_input_output_length     14
@@ -254,6 +258,8 @@ extern "C" {
     #define FL_status_string_recurse_length          9
     #define FL_status_string_relative_length         10
     #define FL_status_string_search_length           8
+    #define FL_status_string_signal_length           8
+    #define FL_status_string_space_length            7
     #define FL_status_string_space_not_length        11
     #define FL_status_string_stop_length             6
     #define FL_status_string_syntax_length           8
index 5ec39ecdb5ad70a652aff7b2a878ca6cb8c56398..a9fc21c6e7bad053db27ad9fedcc3b47ccce1cc7 100644 (file)
@@ -186,7 +186,7 @@ extern "C" {
 #endif // _di_fll_execute_arguments_dynamic_add_set_
 
 #ifndef _di_fll_execute_path_
-  f_return_status fll_execute_path(const f_string_t program_path, const f_string_statics_t arguments, int *result) {
+  f_return_status fll_execute_path(const f_string_t program_path, const f_string_statics_t arguments, const f_signal_how_t *signals, int *result) {
     #ifndef _di_level_2_parameter_checking_
       if (result == 0) return F_status_set_error(F_parameter);
       if (arguments.used > arguments.size) return F_status_set_error(F_parameter);
@@ -202,8 +202,6 @@ extern "C" {
 
     f_status_t status = F_none;
 
-    memset(&fixed_arguments, 0, sizeof(f_string_t) * (arguments.used + 2));
-
     last_slash = strrchr(program_path, '/');
 
     if (last_slash == 0) {
@@ -248,8 +246,8 @@ extern "C" {
       fixed_arguments[i + 1] = arguments.array[i].string;
     } // for
 
-    // insert the required array terminated
-    fixed_arguments[arguments.used + 2] = 0;
+    // insert the required array terminated.
+    fixed_arguments[arguments.used + 1] = 0;
 
     status = f_file_exists(program_path);
     if (F_status_is_error(status)) {
@@ -273,16 +271,20 @@ extern "C" {
       return F_status_set_error(F_fork);
     }
 
-    // child
+    // child process.
     if (process_id == 0) {
-      execv(program_path, fixed_arguments);
+      if (signals) {
+        f_signal_set_handle(SIG_BLOCK, &signals->block);
+        f_signal_set_handle(SIG_UNBLOCK, &signals->block_not);
+      }
 
-      // according to manpages, calling _exit() is safer and should be called here instead of exit()
-      _exit(-1);
+      const int code = execv(program_path, fixed_arguments);
+
+      exit(code);
     }
 
     // have the parent wait for the child process to finish
-    waitpid(process_id, result, 0);
+    waitpid(process_id, result, WUNTRACED | WCONTINUED);
 
     if (name_size > 0) f_macro_string_t_delete_simple(program_name, name_size);
 
@@ -293,7 +295,7 @@ extern "C" {
 #endif // _di_fll_execute_path_
 
 #ifndef _di_fll_execute_path_environment_
-  f_return_status fll_execute_path_environment(const f_string_t program_path, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, int *result) {
+  f_return_status fll_execute_path_environment(const f_string_t program_path, const f_string_statics_t arguments, const f_signal_how_t *signals, const f_string_statics_t names, const f_string_statics_t values, int *result) {
     #ifndef _di_level_2_parameter_checking_
       if (result == 0) return F_status_set_error(F_parameter);
       if (arguments.used > arguments.size) return F_status_set_error(F_parameter);
@@ -312,8 +314,6 @@ extern "C" {
 
     f_status_t status = F_none;
 
-    memset(&fixed_arguments, 0, sizeof(f_string_t) * (arguments.used + 2));
-
     last_slash = strrchr(program_path, '/');
 
     if (last_slash == 0) {
@@ -358,8 +358,8 @@ extern "C" {
       fixed_arguments[i + 1] = arguments.array[i].string;
     } // for
 
-    // insert the required array terminated
-    fixed_arguments[arguments.used + 2] = 0;
+    // insert the required array terminated.
+    fixed_arguments[arguments.used + 1] = 0;
 
     status = f_file_exists(program_path);
 
@@ -384,33 +384,43 @@ extern "C" {
       return F_status_set_error(F_fork);
     }
 
-    // child
+    // child process.
     if (process_id == 0) {
+      if (signals) {
+        f_signal_set_handle(SIG_BLOCK, &signals->block);
+        f_signal_set_handle(SIG_UNBLOCK, &signals->block_not);
+      }
+
       clearenv();
 
       for (f_array_length_t i = 0; i < names.used; i++) {
         f_environment_set_dynamic(names.array[i], values.array[i], F_true);
       } // for
 
-      execv(program_path, fixed_arguments);
+      const int code = execv(program_path, fixed_arguments);
 
-      // according to manpages, calling _exit() is safer and should be called here instead of exit()
-      _exit(-1);
+      exit(code);
     }
 
-    // have the parent wait for the child process to finish
-    waitpid(process_id, result, 0);
+    // have the parent wait for the child process to finish.
+    waitpid(process_id, result, WUNTRACED | WCONTINUED);
 
     if (name_size > 0) f_macro_string_t_delete_simple(program_name, name_size);
 
-    if (result != 0 && *result != 0) return F_status_set_error(F_failure);
+    if (result != 0) {
+      if (WIFEXITED(*result)) {
+        return F_none;
+      }
+
+      return F_status_set_error(F_failure);
+    }
 
     return F_none;
   }
 #endif // _di_fll_execute_path_environment_
 
 #ifndef _di_fll_execute_program_
-  f_return_status fll_execute_program(const f_string_t program_name, const f_string_statics_t arguments, int *result) {
+  f_return_status fll_execute_program(const f_string_t program_name, const f_string_statics_t arguments, const f_signal_how_t *signals, int *result) {
     #ifndef _di_level_2_parameter_checking_
       if (result == 0) return F_status_set_error(F_parameter);
       if (arguments.used > arguments.size) return F_status_set_error(F_parameter);
@@ -419,7 +429,6 @@ extern "C" {
     // create a string array that is compatible with execv() calls.
     f_string_t fixed_arguments[arguments.used + 2];
 
-    memset(&fixed_arguments, 0, sizeof(f_string_t) * (arguments.used + 2));
     fixed_arguments[0] = program_name;
 
     f_status_t status = F_none;
@@ -429,8 +438,8 @@ extern "C" {
       fixed_arguments[i + 1] = arguments.array[i].string;
     } // for
 
-    // insert the required array terminated
-    fixed_arguments[arguments.used + 2] = 0;
+    // insert the required array terminated.
+    fixed_arguments[arguments.used + 1] = 0;
 
     pid_t process_id = 0;
 
@@ -440,16 +449,20 @@ extern "C" {
       return F_status_set_error(F_fork);
     }
 
-    // child
+    // child process.
     if (process_id == 0) {
-      execvp(program_name, fixed_arguments);
+      if (signals) {
+        f_signal_set_handle(SIG_BLOCK, &signals->block);
+        f_signal_set_handle(SIG_UNBLOCK, &signals->block_not);
+      }
 
-      // according to manpages, calling _exit() is safer and should be called here instead of exit()
-      _exit(-1);
+      const int code = execvp(program_name, fixed_arguments);
+
+      exit(code);
     }
 
     // have the parent wait for the child process to finish
-    waitpid(process_id, result, 0);
+    waitpid(process_id, result, WUNTRACED | WCONTINUED);
 
     if (result != 0 && *result != 0) return F_status_set_error(F_failure);
 
@@ -458,7 +471,7 @@ extern "C" {
 #endif // _di_fll_execute_program_
 
 #ifndef _di_fll_execute_program_environment_
-  f_return_status fll_execute_program_environment(const f_string_t program_name, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, int *result) {
+  f_return_status fll_execute_program_environment(const f_string_t program_name, const f_string_statics_t arguments, const f_signal_how_t *signals, const f_string_statics_t names, const f_string_statics_t values, int *result) {
     #ifndef _di_level_2_parameter_checking_
       if (result == 0) return F_status_set_error(F_parameter);
       if (arguments.used > arguments.size) return F_status_set_error(F_parameter);
@@ -470,7 +483,6 @@ extern "C" {
     // create a string array that is compatible with execv() calls.
     f_string_t fixed_arguments[arguments.used + 2];
 
-    memset(&fixed_arguments, 0, sizeof(f_string_t) * (arguments.used + 2));
     fixed_arguments[0] = program_name;
 
     f_status_t status = F_none;
@@ -480,8 +492,8 @@ extern "C" {
       fixed_arguments[i + 1] = arguments.array[i].string;
     } // for
 
-    // insert the required array terminated
-    fixed_arguments[arguments.used + 2] = 0;
+    // insert the required array terminated.
+    fixed_arguments[arguments.used + 1] = 0;
 
     f_string_dynamic_t path = f_string_dynamic_t_initialize;
     f_string_dynamics_t paths = f_string_dynamics_t_initialize;
@@ -572,22 +584,26 @@ extern "C" {
       return F_status_set_error(F_fork);
     }
 
-    // child
+    // child process.
     if (process_id == 0) {
+      if (signals) {
+        f_signal_set_handle(SIG_BLOCK, &signals->block);
+        f_signal_set_handle(SIG_UNBLOCK, &signals->block_not);
+      }
+
       clearenv();
 
       for (i = 0; i < names.used; i++) {
         f_environment_set_dynamic(names.array[i], values.array[i], F_true);
       }
 
-      execvp(program_path, fixed_arguments);
+      const int code = execvp(program_path, fixed_arguments);
 
-      // according to manpages, calling _exit() is safer and should be called here instead of exit()
-      _exit(-1);
+      exit(code);
     }
 
     // have the parent wait for the child process to finish
-    waitpid(process_id, result, 0);
+    waitpid(process_id, result, WUNTRACED | WCONTINUED);
 
     if (result != 0 && *result != 0) return F_status_set_error(F_failure);
 
index f84ca308e53e564641e0f4bf8920b2c894397d1a..3197e5fd3e599112b4e14b0304b827c263e4aa22 100644 (file)
@@ -13,6 +13,7 @@
 // libc includes
 #include <memory.h>
 #include <signal.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -26,6 +27,7 @@
 #include <level_0/environment.h>
 #include <level_0/file.h>
 #include <level_0/path.h>
+#include <level_0/signal.h>
 
 // fll-1 includes
 #include <level_1/environment.h>
@@ -291,6 +293,9 @@ extern "C" {
  *   The entire path to the program.
  * @param arguments
  *   An array of strings representing the arguments.
+ * @param set_signal
+ *   (optional) A pointer to the set of signals.
+ *   Set to 0 to disable.
  * @param result
  *   The code returned after finishing execution of program_path.
  *
@@ -312,7 +317,7 @@ extern "C" {
  * @see execv()
  */
 #ifndef _di_fll_execute_path_
-  extern f_return_status fll_execute_path(const f_string_t program_path, const f_string_statics_t arguments, int *result);
+  extern f_return_status fll_execute_path(const f_string_t program_path, const f_string_statics_t arguments, const f_signal_how_t *signals, int *result);
 #endif // _di_fll_execute_path_
 
 /**
@@ -330,6 +335,9 @@ extern "C" {
  *   An array of strings representing the environment variable names.
  *   At most names.used variables are created.
  *   Duplicate names are overwritten.
+ * @param set_signal
+ *   (optional) A pointer to the set of signals.
+ *   Set to 0 to disable.
  * @param values
  *   An array of strings representing the environment variable names.
  *   The values.used must be of at least names.used.
@@ -355,7 +363,7 @@ extern "C" {
  * @see execv()
  */
 #ifndef _di_fll_execute_path_environment_
-  f_return_status fll_execute_path_environment(const f_string_t program_path, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, int *result);
+  f_return_status fll_execute_path_environment(const f_string_t program_path, const f_string_statics_t arguments, const f_signal_how_t *signals, const f_string_statics_t names, const f_string_statics_t values, int *result);
 #endif // _di_fll_execute_path_environment_
 
 /**
@@ -367,6 +375,9 @@ extern "C" {
  *   The name of the program.
  * @param arguments
  *   An array of strings representing the arguments.
+ * @param set_signal
+ *   (optional) A pointer to the set of signals.
+ *   Set to 0 to disable.
  * @param result
  *   The code returned after finishing execution of program.
  *
@@ -383,7 +394,7 @@ extern "C" {
  * @see execvp()
  */
 #ifndef _di_fll_execute_program_
-  extern f_return_status fll_execute_program(const f_string_t program_name, const f_string_statics_t arguments, int *result);
+  extern f_return_status fll_execute_program(const f_string_t program_name, const f_string_statics_t arguments, const f_signal_how_t *signals, int *result);
 #endif // _di_fll_execute_program_
 
 /**
@@ -403,6 +414,9 @@ extern "C" {
  *   An array of strings representing the environment variable names.
  *   At most names.used variables are created.
  *   Duplicate names are overwritten.
+ * @param set_signal
+ *   (optional) A pointer to the set of signals.
+ *   Set to 0 to disable.
  * @param values
  *   An array of strings representing the environment variable names.
  *   The values.used must be of at least names.used.
@@ -430,7 +444,7 @@ extern "C" {
  * @see execvpe()
  */
 #ifndef _di_fll_execute_program_environment_
-  extern f_return_status fll_execute_program_environment(const f_string_t program_name, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, int *result);
+  extern f_return_status fll_execute_program_environment(const f_string_t program_name, const f_string_statics_t arguments, const f_signal_how_t *signals, const f_string_statics_t names, const f_string_statics_t values, int *result);
 #endif // _di_fll_execute_program_environment_
 
 #ifdef __cplusplus
index 6c62d3b049d94e03a961afa6bd386c51ba2e9886..b94e28a4594322d63a91862cdd2c149aad53fcf5 100644 (file)
@@ -7,5 +7,6 @@ f_string
 f_environment
 f_file
 f_path
+f_signal
 fl_environment
 fl_string
index 224c3a00f85ff2f70e6dced4b011dd573cd277a0..b7fe9d5fe7896d96e3f468d6ca51944729a7bc18 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfl_string -lfl_environment -lf_utf -lf_path -lf_file -lf_environment -lf_memory
+build_libraries-individual -lfl_string -lfl_environment -lf_utf -lf_signal -lf_path -lf_file -lf_environment -lf_memory
 build_sources_library execute.c private-execute.c
 build_sources_program
 build_sources_headers execute.h
index 66d70c82b27ba68b850eb37b675614d1d8cbcdb4..4511d7f39213a4e86d9b12509858aa0aa793db5a 100644 (file)
@@ -20,6 +20,7 @@
 #include <level_0/string.h>
 #include <level_0/directory.h>
 #include <level_0/file.h>
+#include <level_0/signal.h>
 
 // fll-1 includes
 #include <level_1/color.h>
index 63d17bfd150a98b0726ee0a8e1dc4f3775c12412..7a68545952bb8c8cb95951cde2f260ff624cef0a 100644 (file)
@@ -451,6 +451,11 @@ extern "C" {
         return F_none;
       }
 
+      if (fl_string_compare(string, FL_status_string_found, length, FL_status_string_found_length) == F_equal_to) {
+        *code = F_found;
+        return F_none;
+      }
+
       if (fl_string_compare(string, FL_status_string_incomplete, length, FL_status_string_incomplete_length) == F_equal_to) {
         *code = F_incomplete;
         return F_none;
@@ -561,6 +566,16 @@ extern "C" {
         return F_none;
       }
 
+      if (fl_string_compare(string, FL_status_string_signal, length, FL_status_string_signal_length) == F_equal_to) {
+        *code = F_signal;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_space, length, FL_status_string_space_length) == F_equal_to) {
+        *code = F_space;
+        return F_none;
+      }
+
       if (fl_string_compare(string, FL_status_string_space_not, length, FL_status_string_space_not_length) == F_equal_to) {
         *code = F_space_not;
         return F_none;
index 08e95951214cb1a02310a4226793a06e7ef2c12a..807f379f34cac1856f30b000efb819a2a352a73f 100644 (file)
@@ -267,7 +267,7 @@ extern "C" {
             validate_parameter_directories = F_false;
           }
 
-          if (F_status_is_not_error(status)) {
+          if (F_status_is_not_error(status) && status != F_signal) {
             f_string_static_t stub = f_string_static_t_initialize;
 
             status = fake_build_operate(*data, stub);
@@ -279,7 +279,7 @@ extern "C" {
             validate_parameter_directories = F_false;
           }
 
-          if (F_status_is_not_error(status)) {
+          if (F_status_is_not_error(status) && status != F_signal) {
             status = fake_clean_operate(*data);
           }
         }
@@ -289,7 +289,7 @@ extern "C" {
             validate_parameter_directories = F_false;
           }
 
-          if (F_status_is_not_error(status)) {
+          if (F_status_is_not_error(status) && status != F_signal) {
             status = fake_make_operate(*data);
           }
         }
@@ -297,7 +297,10 @@ extern "C" {
           status = fake_skeleton_operate(*data);
         }
 
-        if (F_status_is_error(status)) {
+        if (status == F_signal || fake_signal_received(*data)) {
+          break;
+        }
+        else if (F_status_is_error(status)) {
           if (data->verbosity != fake_verbosity_quiet) {
             fprintf(f_type_error, "%c", f_string_eol[0]);
             fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: The operation '");
@@ -311,7 +314,7 @@ extern "C" {
 
       // ensure a newline is always put at the end of the program execution, unless in quite mode.
       if (data->verbosity != fake_verbosity_quiet) {
-        if (F_status_is_error(status)) {
+        if (F_status_is_error(status) || status == F_signal) {
           fprintf(f_type_error, "%c", f_string_eol[0]);
         }
         else {
index 269d4636fa925b40892e2e18206bab21886d3a20..f5527d586f0718aed302f6a224bbd796ec01f6e8 100644 (file)
@@ -43,6 +43,7 @@
 #ifndef _fake_h
 
 // libc includes
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -53,6 +54,7 @@
 #include <level_0/status.h>
 #include <level_0/type_array.h>
 #include <level_0/memory.h>
+#include <level_0/signal.h>
 #include <level_0/string.h>
 #include <level_0/utf.h>
 #include <level_0/account.h>
@@ -374,6 +376,7 @@ extern "C" {
     f_string_lengths_t remaining;
     bool process_pipe;
     mode_t umask;
+    f_signal_t signal;
 
     uint8_t operation;
     uint8_t verbosity;
@@ -440,6 +443,7 @@ extern "C" {
       f_string_lengths_t_initialize, \
       F_false, \
       0, \
+      f_signal_t_initialize, \
       0, \
       fake_verbosity_normal, \
       f_string_dynamics_t_initialize, \
@@ -508,6 +512,13 @@ extern "C" {
  *
  * Be sure to call fake_delete_data() after executing this.
  *
+ * If data.signal is non-zero, then this blocks and handles the following signals:
+ * - F_signal_abort
+ * - F_signal_hangup
+ * - F_signal_interrupt
+ * - F_signal_quit
+ * - F_signal_termination
+ *
  * @param arguments
  *   The parameters passed to the process.
  * @param data
@@ -515,6 +526,7 @@ extern "C" {
  *
  * @return
  *   F_none on success.
+ *   F_status if one of the above signals is received.
  *
  *   Status codes (with error bit) are returned on any problem.
  *
index d7f51a9fff67eaaf0c0160ba664ce69cb07aee6c..b0bc9bd6f121ecfff193a0a7e5918f1f63f609ae 100644 (file)
@@ -1,16 +1,50 @@
 #include "fake.h"
 
+/**
+ * Standard entry point for fake program.
+ *
+ * @param argc
+ *   The number of arguments.
+ * @param argv
+ *   The array of arguments.
+ *
+ * @return
+ *   0 on success.
+ *   1 on error.
+ */
 int main(const unsigned long argc, const f_string_t *argv) {
   const f_console_arguments_t arguments = { argc, argv };
   fake_data_t data = fake_data_t_initialize;
 
+  f_status_t status = F_none;
+
+  {
+    f_signal_set_empty(&data.signal.set);
+    f_signal_set_add(F_signal_abort, &data.signal.set);
+    f_signal_set_add(F_signal_hangup, &data.signal.set);
+    f_signal_set_add(F_signal_interrupt, &data.signal.set);
+    f_signal_set_add(F_signal_quit, &data.signal.set);
+    f_signal_set_add(F_signal_termination, &data.signal.set);
+    f_signal_set_handle(SIG_BLOCK, &data.signal.set);
+
+    status = f_signal_open(&data.signal);
+
+    // if there is an error opening a signal descriptor, then do not handle signals.
+    if (F_status_is_error(status)) {
+      f_signal_set_handle(SIG_UNBLOCK, &data.signal.set);
+      f_signal_close(&data.signal);
+    }
+  }
+
   // @fixme: bad design in POSIX where there is no get umask without setting it.
   data.umask = umask(0);
 
   // restore umask.
   umask(data.umask);
 
-  f_status_t status = fake_main(arguments, &data);
+  status = fake_main(arguments, &data);
+
+  f_signal_close(&data.signal);
 
   if (F_status_is_error(status)) {
     return 1;
index 010ddae73d0a31b64b47be1271cb582fbb1bc38d..2d8a4d9ad2529add137b4eca5721bf59e0f01bf8 100644 (file)
@@ -158,6 +158,11 @@ extern "C" {
   void fake_build_copy(const fake_data_t data, const f_mode_t mode, const f_string_t label, const f_string_static_t source, const f_string_static_t destination, const f_string_statics_t files, const f_string_static_t file_stage, f_status_t *status) {
     if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return;
 
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+      return;
+    }
+
     f_directory_statuss_t failures = f_directory_statuss_t_initialize;
     f_string_dynamic_t path_source = f_string_dynamic_t_initialize;
     f_string_dynamic_t destination_file = f_string_dynamic_t_initialize;
@@ -203,7 +208,18 @@ extern "C" {
         break;
       }
 
+      if (fake_signal_received(data)) {
+        *status = F_status_set_error(F_signal);
+        break;
+      }
+
       if ((*status = f_directory_is(path_source.string)) == F_true) {
+
+        if (fake_signal_received(data)) {
+          *status = F_status_set_error(F_signal);
+          break;
+        }
+
         *status = fl_directory_copy_content(path_source.string, destination.string, path_source.used, destination.used, mode, recurse);
 
         if (F_status_is_error(*status)) {
@@ -240,6 +256,11 @@ extern "C" {
           break;
         }
 
+        if (fake_signal_received(data)) {
+          *status = F_status_set_error(F_signal);
+          break;
+        }
+
         *status = f_file_copy(path_source.string, destination_file.string, mode, f_file_default_read_size, F_false);
 
         if (F_status_is_error(*status)) {
@@ -273,6 +294,11 @@ extern "C" {
   void fake_build_skeleton(const fake_data_t data, const fake_build_data_t data_build, const mode_t mode, const f_string_static_t file_stage, f_status_t *status) {
     if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return;
 
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+      return;
+    }
+
     f_string_static_t path_headers = f_string_static_t_initialize;
     f_string_length_t directory_headers_length = data.path_build_includes.used + data_build.setting.path_headers.used;
 
@@ -320,8 +346,14 @@ extern "C" {
     }
 
     for (uint8_t i = 0; i < 15; i++) {
+
       if (directorys[i]->used == 0) continue;
 
+      if (fake_signal_received(data)) {
+        *status = F_status_set_error(F_signal);
+        return;
+      }
+
       *status = f_directory_create(directorys[i]->string, mode);
 
       if (F_status_is_error(*status)) {
@@ -348,6 +380,11 @@ extern "C" {
     if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return;
     if (process_script.used == 0) return;
 
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+      return;
+    }
+
     f_string_dynamics_t arguments = f_string_dynamics_t_initialize;
 
     *status = fll_execute_arguments_add(fake_other_operation_build, fake_other_operation_build_length, &arguments);
@@ -523,30 +560,46 @@ extern "C" {
       }
     }
 
-    {
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+
+      f_macro_string_dynamic_t_delete_simple(path);
+      f_macro_string_dynamics_t_delete_simple(arguments);
+    }
+    else {
       int result = 0;
 
-      *status = fll_execute_path_environment(path.string, arguments, data_build.environment.names, data_build.environment.values, &result);
+      // child processes should receive all signals, without blocking.
+      f_signal_how_t signals = f_signal_how_t_initialize;
+      f_signal_set_empty(&signals.block);
+      f_signal_set_fill(&signals.block_not);
+
+      *status = fll_execute_path_environment(path.string, arguments, &signals, data_build.environment.names, data_build.environment.values, &result);
 
       f_macro_string_dynamics_t_delete_simple(arguments);
-    }
 
-    if (F_status_is_error(*status)) {
-      if (F_status_set_fine(*status) == F_failure) {
-        if (data.verbosity != fake_verbosity_quiet) {
-          fprintf(f_type_error, "%c", f_string_eol[0]);
-          fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: Failed to execute script: ");
-          fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", path.string);
-          fl_color_print_line(f_type_error, data.context.error, data.context.reset, ".");
-        }
+      if (fake_signal_received(data)) {
+        *status = F_status_set_error(F_signal);
       }
       else {
-        fake_print_error(data, F_status_set_fine(*status), "fll_execute_path_environment", F_true);
+        if (F_status_is_error(*status)) {
+          if (F_status_set_fine(*status) == F_failure) {
+            if (data.verbosity != fake_verbosity_quiet) {
+              fprintf(f_type_error, "%c", f_string_eol[0]);
+              fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: Failed to execute script: ");
+              fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", path.string);
+              fl_color_print_line(f_type_error, data.context.error, data.context.reset, ".");
+            }
+          }
+          else {
+            fake_print_error(data, F_status_set_fine(*status), "fll_execute_path_environment", F_true);
+          }
+        }
+        else {
+          fake_build_touch(data, file_stage, status);
+        }
       }
     }
-    else {
-      fake_build_touch(data, file_stage, status);
-    }
 
     f_macro_string_dynamic_t_delete_simple(path);
   }
@@ -785,7 +838,9 @@ extern "C" {
 
     f_macro_string_dynamics_t_delete_simple(arguments);
 
-    if (F_status_is_error(*status)) return;
+    if (F_status_is_error(*status)) {
+      return;
+    }
 
     if (data_build.setting.version_target != fake_build_version_type_micro) {
       f_string_length_t parameter_file_path_length = data.path_build_libraries_shared.used;
@@ -810,6 +865,12 @@ extern "C" {
 
       parameter_file_path[parameter_file_path_length] = 0;
 
+
+      if (fake_signal_received(data)) {
+        *status = F_status_set_error(F_signal);
+        return;
+      }
+
       *status = f_file_link(parameter_file_name_micro, parameter_file_path);
 
       if (F_status_is_fine(*status) && data.verbosity == fake_verbosity_verbose) {
@@ -837,6 +898,11 @@ extern "C" {
 
       parameter_file_path[parameter_file_path_length] = 0;
 
+      if (fake_signal_received(data)) {
+        *status = F_status_set_error(F_signal);
+        return;
+      }
+
       if (data_build.setting.version_target == fake_build_version_type_major) {
         *status = f_file_link(parameter_file_name_major, parameter_file_path);
       }
@@ -937,14 +1003,16 @@ extern "C" {
         *status = fake_build_get_file_name_without_extension(data, data_build.setting.build_sources_library.array[i], &file_name);
         if (F_status_is_error(*status)) {
           fake_print_error(data, F_status_set_fine(*status), "fake_build_get_file_name_without_extension", F_true);
+          break;
+        }
 
-          f_macro_string_dynamic_t_delete_simple(file_name);
-          f_macro_string_dynamic_t_delete_simple(source_path);
-          f_macro_string_dynamics_t_delete_simple(arguments);
-          return;
+        if (fake_signal_received(data)) {
+          *status = F_status_set_error(F_signal);
+          break;
         }
 
         *status = f_file_name_directory(data_build.setting.build_sources_library.array[i].string, data_build.setting.build_sources_library.array[i].used, &source_path);
+
         if (F_status_is_error(*status)) {
           fake_print_error(data, F_status_set_fine(*status), "f_file_name_directory", F_true);
           break;
@@ -991,20 +1059,17 @@ extern "C" {
         source[source_length] = 0;
 
         *status = fll_execute_arguments_add(source, source_length, &arguments);
-        if (F_status_is_error(*status)) break;
-      } // for
-
-      if (F_status_is_error(*status)) {
-        fake_print_error(data, F_status_set_fine(*status), "fll_execute_arguments_add", F_true);
 
-        f_macro_string_dynamic_t_delete_simple(file_name);
-        f_macro_string_dynamic_t_delete_simple(source_path);
-        f_macro_string_dynamics_t_delete_simple(arguments);
-        return;
-      }
+        if (F_status_is_error(*status)) {
+          fake_print_error(data, F_status_set_fine(*status), "fll_execute_arguments_add", F_true);
+          break;
+        }
+      } // for
     }
 
-    fake_execute(data, data_build.environment, data_build.setting.build_indexer, arguments, status);
+    if (F_status_is_fine(*status)) {
+      fake_execute(data, data_build.environment, data_build.setting.build_indexer, arguments, status);
+    }
 
     f_macro_string_dynamic_t_delete_simple(file_name);
     f_macro_string_dynamic_t_delete_simple(source_path);
@@ -1035,6 +1100,7 @@ extern "C" {
       };
 
       f_macro_string_dynamics_new(*status, names, 2);
+
       if (F_status_is_error(*status)) {
         fake_print_error(data, F_status_set_fine(*status), "f_macro_string_dynamics_new", F_true);
 
@@ -1045,6 +1111,7 @@ extern "C" {
       f_string_dynamic_t part = f_string_dynamic_t_initialize;
 
       for (uint8_t i = 0; i < 2; i++) {
+
         *status = fl_string_append(variables_name[i], variables_length[i], &part);
         if (F_status_is_error(*status)) break;
 
@@ -1075,6 +1142,7 @@ extern "C" {
           }
 
           f_macro_string_dynamics_resize(*status, names, names.used + data_build.setting.environment.used);
+
           if (F_status_is_error(*status)) {
             fake_print_error(data, F_status_set_fine(*status), "f_macro_string_dynamics_resize", F_true);
 
@@ -1085,6 +1153,7 @@ extern "C" {
         }
 
         for (f_string_length_t i = 0; i < data_build.setting.environment.used; i++) {
+
           *status = fl_string_dynamic_append_nulless(data_build.setting.environment.array[i], &part);
           if (F_status_is_error(*status)) break;
 
@@ -1112,7 +1181,14 @@ extern "C" {
     f_string_dynamic_t variable_value = f_string_dynamic_t_initialize;
 
     for (f_string_length_t i = 0; i < names.used; i++) {
+
+      if (fake_signal_received(data)) {
+        *status = F_status_set_error(F_signal);
+        break;
+      }
+
       *status = f_environment_get_dynamic(names.array[i], &variable_value);
+
       if (F_status_is_error(*status)) {
         if (F_status_set_fine(*status) == F_memory_reallocation) {
           function = "f_macro_string_dynamics_resize";
@@ -1170,7 +1246,7 @@ extern "C" {
     f_macro_string_dynamic_t_delete_simple(variable_name);
     f_macro_string_dynamic_t_delete_simple(variable_value);
 
-    if (F_status_is_error(*status)) {
+    if (F_status_is_error(*status) && F_status_set_fine(*status) != F_signal) {
       fake_print_error(data, *status, function, F_true);
     }
   }
@@ -1180,6 +1256,11 @@ extern "C" {
   void fake_build_load_setting(const fake_data_t data, const f_string_static_t setting_file, fake_build_setting_t *setting, f_status_t *status) {
     if (F_status_is_error(*status)) return;
 
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+      return;
+    }
+
     char path_file[data.path_data_build.used + setting_file.used + 1];
 
     {
@@ -1200,17 +1281,22 @@ extern "C" {
         *status = fake_file_buffer(data, data.file_data_build_settings.string, &buffer);
       }
 
-      if (F_status_is_error(*status)) return;
+      if (fake_signal_received(data)) {
+        *status = F_status_set_error(F_signal);
+      }
+      else if (F_status_is_fine(*status)) {
+        f_string_range_t range = f_macro_string_range_initialize(buffer.used);
 
-      f_string_range_t range = f_macro_string_range_initialize(buffer.used);
+        *status = fll_fss_extended_read(&buffer, &range, &objects, &contents, 0, 0);
 
-      *status = fll_fss_extended_read(&buffer, &range, &objects, &contents, 0, 0);
-      if (F_status_is_error(*status)) {
-        fake_print_error_fss(data, *status, "fll_fss_extended_read", data.file_data_build_settings.string, range, F_true);
+        if (F_status_is_error(*status)) {
+          fake_print_error_fss(data, F_status_set_fine(*status), "fll_fss_extended_read", data.file_data_build_settings.string, range, F_true);
+        }
+        else {
+          fake_build_load_setting_process(data, setting_file.used ? path_file : data.file_data_build_settings.string, buffer, objects, contents, setting, status);
+        }
       }
 
-      fake_build_load_setting_process(data, setting_file.used ? path_file : data.file_data_build_settings.string, buffer, objects, contents, setting, status);
-
       f_macro_string_dynamic_t_delete_simple(buffer);
       f_macro_fss_objects_t_delete_simple(objects);
       f_macro_fss_contents_t_delete_simple(contents);
@@ -1255,6 +1341,11 @@ extern "C" {
   void fake_build_load_setting_process(const fake_data_t data, const f_string_t path_file, const f_string_static_t buffer, const f_fss_objects_t objects, const f_fss_contents_t contents, fake_build_setting_t *setting, f_status_t *status) {
     if (F_status_is_error(*status) && buffer.used) return;
 
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+      return;
+    }
+
     bool error_printed = F_false;
 
     const f_string_t settings_name[] = {
@@ -1517,7 +1608,7 @@ extern "C" {
         fake_print_error(data, F_status_set_fine(*status), function, F_true);
       }
     }
-    else {
+    else if (!fake_signal_received(data)) {
       const f_string_t settings_single_name[] = {
         fake_build_setting_name_build_compiler,
         fake_build_setting_name_build_indexer,
@@ -1858,6 +1949,11 @@ extern "C" {
   void fake_build_load_setting_defaults(const fake_data_t data, fake_build_setting_t *setting, f_status_t *status) {
     if (F_status_is_error(*status)) return;
 
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+      return;
+    }
+
     {
       f_string_t sources[] = {
         fake_build_setting_default_version,
@@ -1998,6 +2094,10 @@ extern "C" {
         *status = F_status_set_error(F_failure);
       }
     }
+
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+    }
   }
 #endif // _di_fake_build_load_setting_defaults_
 
@@ -2005,6 +2105,10 @@ extern "C" {
   void fake_build_load_stage(const fake_data_t data, const f_string_static_t settings_file, fake_build_stage_t *stage, f_status_t *status) {
     if (F_status_is_error(*status)) return;
 
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+    }
+
     const f_string_t names[] = {
       fake_build_stage_libraries_script,
       fake_build_stage_libraries_shared,
@@ -2170,11 +2274,12 @@ extern "C" {
       *status = fake_build_get_file_name_without_extension(data, data_build.setting.build_sources_library.array[i], &file_name);
       if (F_status_is_error(*status)) {
         fake_print_error(data, F_status_set_fine(*status), "fake_build_get_file_name_without_extension", F_true);
+        break;
+      }
 
-        f_macro_string_dynamic_t_delete_simple(file_name);
-        f_macro_string_dynamic_t_delete_simple(destination_path);
-        f_macro_string_dynamics_t_delete_simple(arguments);
-        return;
+      if (fake_signal_received(data)) {
+        *status = F_status_set_error(F_signal);
+        break;
       }
 
       *status = f_file_name_directory(data_build.setting.build_sources_library.array[i].string, data_build.setting.build_sources_library.array[i].used, &destination_path);
@@ -2202,6 +2307,11 @@ extern "C" {
           break;
         }
 
+        if (fake_signal_received(data)) {
+          *status = F_status_set_error(F_signal);
+          break;
+        }
+
         *status = f_directory_exists(destination_path.string);
 
         if (*status == F_false) {
@@ -2291,9 +2401,10 @@ extern "C" {
       }
 
       fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status);
-      if (F_status_is_error(*status)) break;
 
       f_macro_string_dynamics_t_delete_simple(arguments);
+
+      if (F_status_is_error(*status)) break;
     } // for
 
     f_macro_string_dynamic_t_delete_simple(file_name);
@@ -2308,6 +2419,11 @@ extern "C" {
 
 #ifndef _di_fake_build_operate_
   f_return_status fake_build_operate(const fake_data_t data, const f_string_static_t setting_file) {
+
+    if (fake_signal_received(data)) {
+      return F_signal;
+    }
+
     if (data.verbosity != fake_verbosity_quiet) {
       printf("%c", f_string_eol[0]);
       fl_color_print_line(f_type_output, data.context.important, data.context.reset, "Building project.");
@@ -2409,6 +2525,11 @@ extern "C" {
     fake_macro_build_data_delete_simple(data_build);
     fake_macro_build_stage_t_delete_simple(stage);
 
+    // signal is set with error code only to prevent further execution above, return without the error bit set.
+    if (status == F_status_set_error(F_signal)) {
+      return F_signal;
+    }
+
     return status;
   }
 #endif // _di_fake_build_operate_
@@ -2645,6 +2766,11 @@ extern "C" {
 
     f_macro_mode_t_set_default_umask(mode, data.umask);
 
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+      return;
+    }
+
     *status = f_file_touch(file.string, mode.regular, F_false);
 
     if (F_status_is_error(*status)) {
index 24e1d4df31e49efdc2cd116a21ba1db90a74e1a3..a5a6d3f3eadf5ba746418e1a199141deaf41394e 100644 (file)
@@ -20,6 +20,10 @@ extern "C" {
       fl_color_print_line(f_type_output, data.context.important, data.context.reset, "'.");
     }
 
+    if (fake_signal_received(data)) {
+      return F_signal;
+    }
+
     if (data.verbosity == fake_verbosity_verbose) {
       status = f_directory_remove_custom(data.path_build.string, f_directory_descriptors_max, F_true, fake_clean_remove_recursively_verbosely);
     }
index 8573e526b994d558859cc2cb46c7dc1e031f87f1..e429bc305f7d8334e8730b8c3d8619a657616646 100644 (file)
@@ -27,10 +27,26 @@ extern "C" {
       fflush(f_type_output);
     }
 
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+      return 0;
+    }
+
     int return_code = 0;
 
     if (program.used) {
-      *status = fll_execute_program_environment(program.string, arguments, environment.names, environment.values, &return_code);
+
+      // child processes should receive all signals, without blocking.
+      f_signal_how_t signals = f_signal_how_t_initialize;
+      f_signal_set_empty(&signals.block);
+      f_signal_set_fill(&signals.block_not);
+
+      *status = fll_execute_program_environment(program.string, arguments, &signals, environment.names, environment.values, &return_code);
+
+      if (fake_signal_received(data)) {
+        *status = F_status_set_error(F_signal);
+        return 0;
+      }
     }
     else {
       *status = F_status_set_error(F_file_found_not);
@@ -65,6 +81,10 @@ extern "C" {
     f_string_t name_function = "f_file_exists";
     f_status_t status = F_none;
 
+    if (fake_signal_received(data)) {
+      return F_status_set_error(F_signal);
+    }
+
     status = f_file_exists(path_file);
 
     if (status == F_true) {
@@ -94,6 +114,14 @@ extern "C" {
       name_function = "f_file_open";
       status = f_file_open(path_file, 0, &file);
 
+      if (fake_signal_received(data)) {
+        if (file.id) {
+          f_file_close(&file.id);
+        }
+
+        return F_status_set_error(F_signal);
+      }
+
       if (F_status_is_not_error(status)) {
         name_function = "f_file_read";
         status = f_file_read(file, buffer);
@@ -877,8 +905,49 @@ extern "C" {
   }
 #endif // _di_fake_process_console_parameters_
 
+#ifndef _di_fake_signal_read_
+  f_return_status fake_signal_received(const fake_data_t data) {
+
+    if (!data.signal.id) {
+      return F_false;
+    }
+
+    f_status_t status = F_none;
+
+    struct signalfd_siginfo information;
+
+    memset(&information, 0, sizeof(struct signalfd_siginfo));
+
+    status = f_signal_read(data.signal, &information);
+
+    if (status == F_signal) {
+      switch (information.ssi_signo) {
+        case F_signal_abort:
+        case F_signal_hangup:
+        case F_signal_interrupt:
+        case F_signal_quit:
+        case F_signal_termination:
+
+          if (data.verbosity != fake_verbosity_quiet) {
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+            fl_color_print_line(f_type_error, data.context.error, data.context.reset, "ALERT: An appropriate exit signal has been received, now aborting.");
+          }
+
+          return F_true;
+      }
+    }
+
+    return F_false;
+  }
+#endif // _di_fake_signal_read_
+
 #ifndef _di_fake_validate_directories_
   f_return_status fake_validate_parameter_directories(const f_console_arguments_t arguments, const fake_data_t data) {
+
+    if (fake_signal_received(data)) {
+      return F_signal;
+    }
+
     const f_string_t parameters_name[] = {
       fake_long_path_build,
       fake_long_path_data,
@@ -913,6 +982,11 @@ extern "C" {
     f_status_t status = F_none;
 
     for (uint8_t i = 0; i < 3; i++) {
+
+      if (fake_signal_received(data)) {
+        return F_status_set_error(F_signal);
+      }
+
       if (parameters_value[i]->used > 0) {
         memset(&directory_stat, 0, sizeof(struct stat));
 
index eed761fc57b42f0905500710c9afe55961b55645..83f2d491305c48ce2a041a9c84e9d21f85d38b7e 100644 (file)
@@ -135,6 +135,22 @@ extern "C" {
 #endif // _di_validate_console_parameters_
 
 /**
+ * Check to see if a termination signal has been received.
+ *
+ * @param data
+ *   The program data.
+ *
+ * @return
+ *   F_true if a termination signal is received.
+ *   F_false if no termination signal is received.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_fake_signal_read_
+  extern f_return_status fake_signal_received(const fake_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_signal_read_
+
+/**
  * Validate directories and print any relating error messages.
  *
  * This should not be called for skeleton as in that case the directories probably do not exist.
index 214a3dd177719dd9937887745ed47e42dc1dcf04..6225af7d8f2f4525c0ee731ce972273c263cd796 100644 (file)
@@ -174,9 +174,19 @@ extern "C" {
   void fake_make_load_fakefile(const fake_data_t data, fake_make_data_t *data_make, f_status_t *status) {
     if (F_status_is_error(*status)) return;
 
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+      return;
+    }
+
     *status = fake_file_buffer(data, data.file_data_build_fakefile.string, &data_make->buffer);
     if (F_status_is_error(*status)) return;
 
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+      return;
+    }
+
     if (!data_make->buffer.used) {
       if (data.verbosity == fake_verbosity_verbose) {
         fprintf(f_type_error, "%c", f_string_eol[0]);
@@ -195,6 +205,7 @@ extern "C" {
       f_string_range_t range = f_macro_string_range_initialize(data_make->buffer.used);
 
       *status = fll_fss_basic_list_read(&data_make->buffer, &range, &list_objects, &list_contents);
+
       if (F_status_is_error(*status)) {
         fake_print_error_fss(data, *status, "fll_fss_basic_list_read", data.file_data_build_fakefile.string, range, F_true);
 
@@ -217,6 +228,7 @@ extern "C" {
       const f_string_range_t name_main_range = f_macro_string_range_initialize(fake_make_section_main_length);
 
       f_macro_fss_nameds_t_new((*status), data_make->fakefile, list_objects.used);
+
       if (F_status_is_error(*status)) {
         fake_print_error(data, F_status_set_fine(*status), "f_macro_fss_nameds_t_new", F_true);
 
@@ -230,6 +242,12 @@ extern "C" {
         f_string_range_t content_range = f_string_range_initialize;
 
         for (f_array_length_t i = 0; i < list_objects.used; i++) {
+
+          if (fake_signal_received(data)) {
+            *status = F_status_set_error(F_signal);
+            break;
+          }
+
           if (fl_string_dynamic_partial_compare(name_settings, data_make->buffer, name_settings_range, list_objects.array[i]) == F_equal_to) {
             if (!missing_settings) {
               fake_print_warning_settings_object_multiple(data, data.file_data_build_fakefile.string, "list", name_settings.string);
@@ -239,13 +257,11 @@ extern "C" {
             content_range = list_contents.array[i].array[0];
 
             *status = fll_fss_extended_read(&data_make->buffer, &content_range, &settings.objects, &settings.contents, 0, 0);
+
             if (F_status_is_error(*status)) {
               fake_print_error_fss(data, *status, "fll_fss_extended_read", data.file_data_build_fakefile.string, content_range, F_true);
 
-              f_macro_fss_set_t_delete_simple(settings);
-              f_macro_fss_objects_t_delete_simple(list_objects);
-              f_macro_fss_contents_t_delete_simple(list_contents);
-              return;
+              break;
             }
 
             missing_settings = F_false;
@@ -266,13 +282,11 @@ extern "C" {
           content_range = list_contents.array[i].array[0];
 
           *status = fll_fss_extended_read(&data_make->buffer, &content_range, &data_make->fakefile.array[data_make->fakefile.used].objects, &data_make->fakefile.array[data_make->fakefile.used].contents, 0, &data_make->fakefile.array[data_make->fakefile.used].quotedss);
+
           if (F_status_is_error(*status)) {
             fake_print_error_fss(data, *status, "fll_fss_extended_read", data.file_data_build_fakefile.string, content_range, F_true);
 
-            f_macro_fss_set_t_delete_simple(settings);
-            f_macro_fss_objects_t_delete_simple(list_objects);
-            f_macro_fss_contents_t_delete_simple(list_contents);
-            return;
+            break;
           }
 
           data_make->fakefile.used++;
@@ -282,6 +296,12 @@ extern "C" {
       f_macro_fss_objects_t_delete_simple(list_objects);
       f_macro_fss_contents_t_delete_simple(list_contents);
 
+      if (F_status_is_error(*status)) {
+        f_macro_fss_set_t_delete_simple(settings);
+
+        return;
+      }
+
       if (missing_main) {
         if (data.verbosity != fake_verbosity_quiet) {
           fprintf(f_type_error, "%c", f_string_eol[0]);
@@ -327,7 +347,7 @@ extern "C" {
         }
 
         if (F_status_is_error(*status)) {
-          fake_print_error(data, *status, function_name, F_true);
+          fake_print_error(data, F_status_set_fine(*status), function_name, F_true);
 
           f_macro_fss_set_t_delete_simple(settings);
           return;
@@ -346,6 +366,7 @@ extern "C" {
         bool unmatched_load = F_true;
 
         for (f_array_length_t i = 0; i < settings.objects.used; i++) {
+
           if (fl_string_dynamic_partial_compare_string(fake_make_setting_compiler, data_make->buffer, fake_make_setting_compiler_length, settings.objects.array[i]) == F_equal_to) {
             if (range_compiler) {
               fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_compiler);
@@ -373,20 +394,14 @@ extern "C" {
 
               *status = fl_string_dynamic_partial_append_nulless(data_make->buffer, settings.contents.array[i].array[j], &name_define);
               if (F_status_is_error(*status)) {
-                fake_print_error(data, *status, "fl_string_dynamic_partial_append_nulless", F_true);
-
-                f_macro_string_dynamic_t_delete_simple(name_define);
-                f_macro_fss_set_t_delete_simple(settings);
-                return;
+                fake_print_error(data, F_status_set_fine(*status), "fl_string_dynamic_partial_append_nulless", F_true);
+                break;
               }
 
               *status = fl_string_dynamic_terminate_after(&name_define);
               if (F_status_is_error(*status)) {
-                fake_print_error(data, *status, "fl_string_dynamic_terminate_after", F_true);
-
-                f_macro_string_dynamic_t_delete_simple(name_define);
-                f_macro_fss_set_t_delete_simple(settings);
-                return;
+                fake_print_error(data, F_status_set_fine(*status), "fl_string_dynamic_terminate_after", F_true);
+                break;
               }
 
               if (fake_make_operate_validate_define_name(name_define) == F_true) {
@@ -401,11 +416,8 @@ extern "C" {
                     *status = fl_string_dynamics_size_increase(f_memory_default_allocation_step, &data_make->setting_build.environment);
 
                     if (F_status_is_error(*status)) {
-                      fake_print_error(data, *status, "fl_string_lengths_size_increase", F_true);
-
-                      f_macro_string_dynamic_t_delete_simple(name_define);
-                      f_macro_fss_set_t_delete_simple(settings);
-                      return;
+                      fake_print_error(data, F_status_set_fine(*status), "fl_string_lengths_size_increase", F_true);
+                      break;
                     }
                   }
 
@@ -414,11 +426,8 @@ extern "C" {
 
                   *status = fl_string_dynamic_append(name_define, &data_make->setting_build.environment.array[data_make->setting_build.environment.used]);
                   if (F_status_is_error(*status)) {
-                    fake_print_error(data, *status, "fl_string_dynamic_append", F_true);
-
-                    f_macro_string_dynamic_t_delete_simple(name_define);
-                    f_macro_fss_set_t_delete_simple(settings);
-                    return;
+                    fake_print_error(data, F_status_set_fine(*status), "fl_string_dynamic_append", F_true);
+                    break;
                   }
 
                   // Ensure that the terminating NULL is after the end of the string used size.
@@ -442,6 +451,11 @@ extern "C" {
               name_define.used = 0;
             } // for
 
+            if (F_status_is_error(*status)) {
+              f_macro_string_dynamic_t_delete_simple(name_define);
+              break;
+            }
+
             *status = F_none;
             f_macro_string_dynamic_t_delete_simple(name_define);
           }
@@ -543,12 +557,14 @@ extern "C" {
                     }
 
                     if (F_status_is_error(*status)) {
-                      fake_print_error(data, *status, function_name, F_true);
-
-                      f_macro_fss_set_t_delete_simple(settings);
-                      return;
+                      fake_print_error(data, F_status_set_fine(*status), function_name, F_true);
+                      break;
                     }
                   } // for
+
+                  if (F_status_is_error(*status)) {
+                    break;
+                  }
                 }
               }
             }
@@ -557,21 +573,33 @@ extern "C" {
             }
           }
         } // for
+
+        if (F_status_is_error(*status)) {
+          f_macro_fss_set_t_delete_simple(settings);
+
+          return;
+        }
       }
 
-      if (data_make->setting_make.load_build) {
+      if (fake_signal_received(data)) {
+        *status = F_status_set_error(F_signal);
+      }
+
+      if (F_status_is_fine(*status) && data_make->setting_make.load_build) {
         f_string_static_t stub = f_string_static_t_initialize;
 
         fake_build_load_setting(data, stub, &data_make->setting_build, status);
 
-        if (F_status_is_error(*status)) {
-          fake_print_error(data, *status, "fake_build_load_setting", F_true);
-
-          f_macro_fss_set_t_delete_simple(settings);
-          return;
+        if (F_status_is_error(*status) && *status != F_status_set_error(F_signal)) {
+          fake_print_error(data, F_status_set_fine(*status), "fake_build_load_setting", F_true);
         }
       }
 
+      if (F_status_is_error(*status)) {
+        f_macro_fss_set_t_delete_simple(settings);
+        return;
+      }
+
       // if either compiler or linker is specified, each will replace any existing build_compiler or build_indexer, respectively.
       if (range_compiler) {
         data_make->setting_build.build_compiler.used = 0;
@@ -584,7 +612,7 @@ extern "C" {
       }
 
       if (F_status_is_error(*status)) {
-        fake_print_error(data, *status, "fl_string_dynamic_partial_append", F_true);
+        fake_print_error(data, F_status_set_fine(*status), "fl_string_dynamic_partial_append", F_true);
 
         f_macro_fss_set_t_delete_simple(settings);
         return;
@@ -592,7 +620,12 @@ extern "C" {
 
       f_string_map_multis_t define = f_string_map_multis_t_initialize;
 
-      fake_build_load_setting_process(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects, settings.contents, &data_make->setting_build, status);
+      if (fake_signal_received(data)) {
+        *status = F_status_set_error(F_signal);
+      }
+      else {
+        fake_build_load_setting_process(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects, settings.contents, &data_make->setting_build, status);
+      }
 
       if (F_status_is_not_error(*status) && settings.objects.used) {
         const f_string_t settings_name[] = {
@@ -611,6 +644,7 @@ extern "C" {
         };
 
         *status = fll_fss_snatch_map_apart(data_make->buffer, settings.objects, settings.contents, settings_name, settings_length, 2, settings_value, 0);
+
         if (F_status_is_error(*status)) {
           fake_print_error(data, F_status_set_fine(*status), "fll_fss_snatch_map_apart", F_true);
 
@@ -631,9 +665,11 @@ extern "C" {
             combined.used = 0;
 
             for (f_array_length_t j = 0; j < define.array[i].value.used; j++) {
+
               *status = fl_string_dynamic_mash(" ", 1, define.array[i].value.array[j], &combined);
+
               if (F_status_is_error(*status)) {
-                fake_print_error(data, *status, "fl_string_dynamic_mash_nulless", F_true);
+                fake_print_error(data, F_status_set_fine(*status), "fl_string_dynamic_mash_nulless", F_true);
                 break;
               }
             } // for
@@ -642,7 +678,12 @@ extern "C" {
 
             *status = fl_string_dynamic_terminate_after(&combined);
             if (F_status_is_error(*status)) {
-              fake_print_error(data, *status, "fl_string_dynamic_terminate_after", F_true);
+              fake_print_error(data, F_status_set_fine(*status), "fl_string_dynamic_terminate_after", F_true);
+              break;
+            }
+
+            if (fake_signal_received(data)) {
+              *status = F_status_set_error(F_signal);
               break;
             }
 
@@ -679,6 +720,11 @@ extern "C" {
 
 #ifndef _di_fake_make_operate_
   f_return_status fake_make_operate(const fake_data_t data) {
+
+    if (fake_signal_received(data)) {
+      return F_signal;
+    }
+
     if (data.verbosity != fake_verbosity_quiet) {
       printf("%c", f_string_eol[0]);
       fl_color_print_line(f_type_output, data.context.important, data.context.reset, "Making project.");
@@ -691,12 +737,19 @@ extern "C" {
     fake_make_data_t data_make = fake_make_data_t_initialize;
 
     f_macro_string_dynamics_new(status, data_make.path.stack, f_memory_default_allocation_step);
+
     if (F_status_is_error(status)) {
       fake_print_error(data, F_status_set_fine(status), "f_macro_string_dynamics_new", F_true);
       return status;
     }
 
+    if (fake_signal_received(data)) {
+      fake_macro_make_data_t_delete_simple(data_make);
+      return F_signal;
+    }
+
     status = f_path_current(F_true, &data_make.path.stack.array[0]);
+
     if (F_status_is_error(status)) {
       fake_print_error(data, F_status_set_fine(status), "f_path_current", F_true);
 
@@ -705,6 +758,7 @@ extern "C" {
     }
 
     status = f_directory_open(data_make.path.stack.array[0].string, F_false, &data_make.path.top);
+
     if (F_status_is_error(status)) {
       fake_print_error(data, F_status_set_fine(status), "f_directory_open", F_true);
 
@@ -718,6 +772,17 @@ extern "C" {
 
     fake_make_load_fakefile(data, &data_make, &status);
 
+    if (F_status_is_error(status)) {
+      fake_macro_make_data_t_delete_simple(data_make);
+
+      // signal is set with error code only to prevent further execution above, return without the error bit set.
+      if (F_status_set_fine(status) == F_signal) {
+        return F_signal;
+      }
+
+      return status;
+    }
+
     if (data_make.setting_make.fail == fake_make_operation_fail_type_exit) {
       data_make.print.prefix = fake_make_print_error;
       data_make.print.context = data.context.error;
@@ -756,6 +821,11 @@ extern "C" {
     f_macro_string_lengths_t_delete_simple(section_stack);
     fake_macro_make_data_t_delete_simple(data_make);
 
+    // signal is set with error code only to prevent further execution above, return without the error bit set.
+    if (status == F_status_set_error(F_signal)) {
+      return F_signal;
+    }
+
     return status;
   }
 #endif // _di_fake_make_operate_
@@ -1394,6 +1464,11 @@ extern "C" {
   void fake_make_operate_section(const fake_data_t data, const f_array_length_t id_section, fake_make_data_t *data_make, f_string_lengths_t *section_stack, f_status_t *status) {
     if (F_status_is_error(*status)) return;
 
+    if (fake_signal_received(data)) {
+      *status = F_status_set_error(F_signal);
+      return;
+    }
+
     if (id_section > data_make->fakefile.used) {
       *status = F_status_set_error(F_parameter);
 
@@ -1556,6 +1631,11 @@ extern "C" {
       operation = 0;
       operation_name = 0;
 
+      if (fake_signal_received(data)) {
+        *status = F_status_set_error(F_signal);
+        break;
+      }
+
       for (j = 0; j < fake_make_operation_total; j++) {
         if (fl_string_dynamic_partial_compare(operations_name[j], data_make->buffer, operations_range[j], section->objects.array[i]) == F_equal_to) {
           operation = operations_type[j];
@@ -1646,6 +1726,10 @@ extern "C" {
         }
       }
 
+      if (*status == F_status_set_error(F_signal)) {
+        break;
+      }
+
       if (operation_if == fake_make_operation_if_type_else_true || operation_if == fake_make_operation_if_type_else_false) {
         // No else condition provided, so clear the operation_if state.
         if (operation != fake_make_operation_type_else) {
@@ -1712,7 +1796,16 @@ extern "C" {
       }
     } // for
 
+    if (*status == F_status_set_error(F_signal)) {
+      for (i = 0; i < section->objects.used; i++) {
+        f_macro_string_dynamics_t_delete_simple(arguments[i]);
+      } // for
+
+      return;
+    }
+
     if (i == section->objects.used && (operation_if == fake_make_operation_if_type_true_next || operation_if == fake_make_operation_if_type_false_next || operation_if == fake_make_operation_if_type_else_true || operation_if == fake_make_operation_if_type_else_false)) {
+
       if (data.verbosity != fake_verbosity_quiet && data_make->print.to) {
         const char *type_name = 0;
 
@@ -1787,6 +1880,11 @@ extern "C" {
 
       *status = fake_build_operate(data, arguments.used ? arguments.array[0] : stub);
 
+      if (F_status_set_fine(*status) == F_signal) {
+        *status = F_status_set_error(F_signal);
+        return;
+      }
+
       fake_make_operate_process_return(data, 0, data_make, status);
       return;
     }
@@ -1794,6 +1892,11 @@ extern "C" {
     if (operation == fake_make_operation_type_clean) {
       *status = fake_clean_operate(data);
 
+      if (F_status_set_fine(*status) == F_signal) {
+        *status = F_status_set_error(F_signal);
+        return;
+      }
+
       fake_make_operate_process_return(data, 0, data_make, status);
       return;
     }
@@ -2968,6 +3071,11 @@ extern "C" {
     if (operation == fake_make_operation_type_skeleton) {
       *status = fake_skeleton_operate(data);
 
+      if (F_status_set_fine(*status) == F_signal) {
+        *status = F_status_set_error(F_signal);
+        return;
+      }
+
       fake_make_operate_process_return(data, 0, data_make, status);
       return;
     }
@@ -3106,6 +3214,11 @@ extern "C" {
 
 #ifndef _di_fake_make_operate_process_execute_
   f_return_status fake_make_operate_process_execute(const fake_data_t data, const f_string_static_t program, const f_string_statics_t arguments, const bool as_shell, fake_make_data_t *data_make) {
+
+    if (fake_signal_received(data)) {
+      return F_status_set_error(F_signal);
+    }
+
     f_status_t status = F_none;
 
     // reset the environment.
@@ -3169,11 +3282,20 @@ extern "C" {
 
     int result = 0;
 
+    // child processes should receive all signals, without blocking.
+    f_signal_how_t signals = f_signal_how_t_initialize;
+    f_signal_set_empty(&signals.block);
+    f_signal_set_fill(&signals.block_not);
+
     if (as_shell) {
-      status = fll_execute_path_environment(program.string, arguments, data_make->environment.names, data_make->environment.values, &result);
+      status = fll_execute_path_environment(program.string, arguments, &signals, data_make->environment.names, data_make->environment.values, &result);
     }
     else {
-      status = fll_execute_program_environment(program.string, arguments, data_make->environment.names, data_make->environment.values, &result);
+      status = fll_execute_program_environment(program.string, arguments, &signals, data_make->environment.names, data_make->environment.values, &result);
+    }
+
+    if (status == F_status_set_error(F_signal)) {
+      return status;
     }
 
     if (F_status_is_error(status)) {
index 95eedaacd4311d08f632fff1b974f4cd9107bc9f..f997fa2e2dc4faf7c658a107de6b8f8fb13baf5b 100644 (file)
@@ -11,6 +11,11 @@ extern "C" {
 
 #ifndef _di_fake_skeleton_operate_
   f_return_status fake_skeleton_operate(const fake_data_t data) {
+
+    if (fake_signal_received(data)) {
+      return F_signal;
+    }
+
     f_status_t status = F_none;
 
     if (data.verbosity != fake_verbosity_quiet) {
@@ -43,6 +48,11 @@ extern "C" {
       };
 
       for (uint8_t i = 0; i < 20; i++) {
+
+        if (fake_signal_received(data)) {
+          return F_status_set_error(F_signal);
+        }
+
         status = fake_skeleton_operate_directory_create(data, *parameters_value[i]);
 
         if (F_status_is_error(status)) {
@@ -56,6 +66,10 @@ extern "C" {
     f_string_dynamic_t file_data_build_process_pre = f_string_dynamic_t_initialize;
     f_string_dynamic_t content = f_string_dynamic_t_initialize;
 
+    if (fake_signal_received(data)) {
+      status = F_status_set_error(F_signal);
+    }
+
     if (F_status_is_not_error(status)) {
       content.string = fake_make_skeleton_content_defines;
       content.used = fake_make_skeleton_content_defines_length;
@@ -74,14 +88,26 @@ extern "C" {
       status = fake_skeleton_operate_file_create(data, data.file_data_build_dependencies, F_false, content);
 
       content.used = 0;
+
+      if (fake_signal_received(data)) {
+        status = F_status_set_error(F_signal);
+      }
     }
 
     if (F_status_is_not_error(status)) {
       status = fake_skeleton_operate_file_create(data, file_data_build_process_post, F_true, content);
+
+      if (fake_signal_received(data)) {
+        status = F_status_set_error(F_signal);
+      }
     }
 
     if (F_status_is_not_error(status)) {
       status = fake_skeleton_operate_file_create(data, file_data_build_process_pre, F_true, content);
+
+      if (fake_signal_received(data)) {
+        status = F_status_set_error(F_signal);
+      }
     }
 
     if (F_status_is_not_error(status)) {
@@ -92,10 +118,18 @@ extern "C" {
       status = fake_skeleton_operate_file_create(data, data.file_data_build_settings, F_false, content);
 
       content.used = 0;
+
+      if (fake_signal_received(data)) {
+        status = F_status_set_error(F_signal);
+      }
     }
 
     if (F_status_is_not_error(status)) {
       status = fake_skeleton_operate_file_create(data, data.file_documents_readme, F_false, content);
+
+      if (fake_signal_received(data)) {
+        status = F_status_set_error(F_signal);
+      }
     }
 
     if (F_status_is_not_error(status)) {
@@ -106,6 +140,10 @@ extern "C" {
       status = fake_skeleton_operate_file_create(data, data.file_data_build_fakefile, F_false, content);
 
       content.used = 0;
+
+      if (fake_signal_received(data)) {
+        status = F_status_set_error(F_signal);
+      }
     }
 
     if (F_status_is_error(status)) {
index 5e41660f8592bddda7900934986a26490ebae222..990498cd3c644ccef608c95cd0002c633ee095d4 100644 (file)
@@ -16,6 +16,7 @@ f_file
 f_iki
 f_path
 f_print
+f_signal
 fl_color
 fl_console
 fl_conversion
index c7f85cbb5c74db700f8cae2fa03180224c7e3778..748278dac7bd354071a6cd4b808361e9477e4a8e 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_program -lfll_path -lfll_file -lfll_execute -lfl_environment -lfll_fss -lfl_utf -lfl_string -lfl_status -lfl_iki -lfl_fss -lfl_directory -lfl_conversion -lfl_console -lfl_color -lf_print -lf_path -lf_iki -lf_file -lf_fss -lf_environment -lf_directory -lf_conversion -lf_console -lf_account -lf_utf -lf_memory
+build_libraries-individual -lfll_program -lfll_path -lfll_file -lfll_execute -lfl_environment -lfll_fss -lfl_utf -lfl_string -lfl_status -lfl_iki -lfl_fss -lfl_directory -lfl_conversion -lfl_console -lfl_color -lf_signal -lf_print -lf_path -lf_iki -lf_file -lf_fss -lf_environment -lf_directory -lf_conversion -lf_console -lf_account -lf_utf -lf_memory
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library fake.c private-fake.c private-clean.c private-build.c private-make.c private-print.c private-skeleton.c
index b620a6ed6c6eaade5e5d7abf28adc32c59367fdd..f4e3f77c10fe7a44b9a9bd681989fe49d755bc95 100644 (file)
@@ -209,7 +209,7 @@ extern "C" {
             parameters.array[4].used = 9;
             parameters.array[5].used = 6;
 
-            status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, &results);
+            status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, &results);
 
             fprintf(f_type_output, "\n");
             fflush(f_type_output);
@@ -237,7 +237,7 @@ extern "C" {
             parameters.array[4].used = 9;
             parameters.array[5].used = 6;
 
-            status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, &results);
+            status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, &results);
 
             fprintf(f_type_output, "\n");
             fflush(f_type_output);
@@ -261,7 +261,7 @@ extern "C" {
             parameters.array[2].used = 9;
             parameters.array[3].used = 6;
 
-            status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, &results);
+            status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, &results);
 
             fprintf(f_type_output, "\n");
             fflush(f_type_output);
index a5059f3ca038c3f3027c3bc2342062a83c31befa..628422e99b2c94f4ab6ec9529d9605c8983ec822 100644 (file)
@@ -743,7 +743,7 @@ f_return_status firewall_perform_commands(const firewall_local_data_t local, con
                       }
                     #endif // _en_firewall_debug_
 
-                    status = fll_execute_program((f_string_t) current_tool, arguments, &results);
+                    status = fll_execute_program((f_string_t) current_tool, arguments, 0, &results);
 
                     if (status == F_failure) {
                       fl_color_print_line(f_type_error, data.context.error, data.context.reset, "ERROR: Failed to perform requested %s operation:", current_tool);
@@ -813,7 +813,7 @@ f_return_status firewall_perform_commands(const firewall_local_data_t local, con
             }
           #endif // _en_firewall_debug_
 
-          status = fll_execute_program(current_tool, arguments, &results);
+          status = fll_execute_program(current_tool, arguments, 0, &results);
 
           if (status == F_failure) {
             fl_color_print_line(f_type_error, data.context.error, data.context.reset, "ERROR: Failed to perform requested %s operation:", current_tool);
@@ -1054,7 +1054,7 @@ f_return_status firewall_create_custom_chains(firewall_reserved_chains_t *reserv
         #endif // _en_firewall_debug_
 
         tool = firewall_program_iptables;
-        status = fll_execute_program((f_string_t) firewall_tool_iptables, arguments, &results);
+        status = fll_execute_program((f_string_t) firewall_tool_iptables, arguments, 0, &results);
 
         if (F_status_is_not_error(status)) {
           // print command when debugging.
@@ -1073,7 +1073,7 @@ f_return_status firewall_create_custom_chains(firewall_reserved_chains_t *reserv
           #endif // _en_firewall_debug_
 
           tool = firewall_program_ip6tables;
-          status = fll_execute_program((f_string_t) firewall_tool_ip6tables, arguments, &results);
+          status = fll_execute_program((f_string_t) firewall_tool_ip6tables, arguments, 0, &results);
         }
 
         if (F_status_is_error(status)) {
@@ -1159,7 +1159,7 @@ f_return_status firewall_delete_chains(const firewall_data_t data) {
       }
     #endif // _en_firewall_debug_
 
-    status = fll_execute_program(tools[i], arguments, &results);
+    status = fll_execute_program(tools[i], arguments, 0, &results);
 
     if (F_status_is_error(status)) {
       status = F_status_set_fine(status);
@@ -1217,7 +1217,7 @@ f_return_status firewall_delete_chains(const firewall_data_t data) {
       }
     #endif // _en_firewall_debug_
 
-    status = fll_execute_program(tools[i], arguments, &results);
+    status = fll_execute_program(tools[i], arguments, 0, &results);
 
     if (F_status_is_error(status)) {
       status = F_status_set_fine(status);
@@ -1296,7 +1296,7 @@ f_return_status firewall_default_lock(const firewall_data_t data) {
         }
       #endif // _en_firewall_debug_
 
-      status = fll_execute_program(tools[j], arguments, &results);
+      status = fll_execute_program(tools[j], arguments, 0, &results);
 
       if (F_status_is_error(status)) {
         status = F_status_set_fine(status);
index 3be19a6f724fe25180476c3ba9c5126558df656c..a6634b32c01366783340c9ab4c7ccbe4041680ba 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_program -lfll_fss -lfll_execute -lfl_environment -lfl_string -lfl_status -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_path -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
+build_libraries-individual -lfll_program -lfll_fss -lfll_execute -lfl_environment -lf_signal -lfl_string -lfl_status -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_path -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library firewall.c private-firewall.c
index 9e1c17247d3155e85985c20fb23617bba580e7a8..db4e095d5d96d3062e2bb1aba09608167845ddf2 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_path -lfl_string -lfl_status -lfl_print -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
+build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_signal -lf_path -lfl_string -lfl_status -lfl_print -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library fss_basic_list_read.c private-fss_basic_list_read.c
index faa203325dbda8aad2de2a2e00474800e07d6801..47c75399bf069890415b9969710df2a0bc223c4d 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_path -lfl_string -lfl_status -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
+build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_signal -lf_path -lfl_string -lfl_status -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library fss_basic_list_write.c
index 26fc8353b96e1a5ff2bf13d513117025d6422212..27898e639f644aeb2323c786f4afe32587c25c80 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_path -lfl_string -lfl_status -lfl_print -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
+build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_signal -lf_path -lfl_string -lfl_status -lfl_print -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library fss_basic_read.c private-fss_basic_read.c
index eca01fa10f36aaddd1dda83177a78f111389f8d1..88a2637e378ba2a9464180bb0fbfd45c095b9e4c 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_path -lfl_string -lfl_status -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
+build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_signal -lf_path -lfl_string -lfl_status -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library fss_basic_write.c
index 64681a5dafae8515dd17518942d565cda6106563..3e9841cd65c6472002e84009d6718175e8e4c948 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_path -lfl_string -lfl_status -lfl_print -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
+build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_signal -lf_path -lfl_string -lfl_status -lfl_print -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library fss_extended_list_read.c private-fss_extended_list_read.c
index 96c18879a66d72f1ce7029b92a737c8410376abc..43b509ee783a65d3bbde2a961b18c54021826e17 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_path -lfl_string -lfl_status -lfl_print -lfl_fss -lfl_console -lfl_conversion -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
+build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_signal -lf_path -lfl_string -lfl_status -lfl_print -lfl_fss -lfl_console -lfl_conversion -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library fss_extended_read.c private-fss_extended_read.c
index b53d020a54db07606a30ee85efc9cb7f196bda03..d133118ec314906b623cd8a6458c55967ca1a80b 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_path -lfl_string -lfl_status -lfl_fss -lfl_conversion -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
+build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_signal -lf_path -lfl_string -lfl_status -lfl_fss -lfl_conversion -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library fss_extended_write.c
index 8c9f7cbacf84ae4a93e4b5760e5bf23163e74651..f7faa47c3965894ad9db7bf38cea9d518a8b2e04 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_status -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_path -lfl_utf -lfl_string -lfl_status -lfl_fss -lfl_conversion -lfl_console -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_conversion -lf_console -lf_utf -lf_memory
+build_libraries-individual -lfll_status -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_signal -lf_path -lfl_utf -lfl_string -lfl_status -lfl_fss -lfl_conversion -lfl_console -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_conversion -lf_console -lf_utf -lf_memory
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library fss_status_code.c private-fss_status_code.c
index a897a6de3a9f9eb8e9f11d258e2308901644c18a..e94cfd2454ec39c4fcd4631b0a76eb0cd2204184 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_program -lfll_fss -lfl_conversion -lfll_execute -lfl_environment -lf_path -lfl_string -lfl_status -lfl_fss -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
+build_libraries-individual -lfll_program -lfll_fss -lfl_conversion -lfll_execute -lfl_environment -lf_signal -lf_path -lfl_string -lfl_status -lfl_fss -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library init.c private-init.c