]> Kevux Git Server - fll/commitdiff
Progress: controller program and execute "as" additions.
authorKevin Day <thekevinday@gmail.com>
Mon, 21 Dec 2020 01:04:56 +0000 (19:04 -0600)
committerKevin Day <thekevinday@gmail.com>
Mon, 21 Dec 2020 01:04:56 +0000 (19:04 -0600)
The execute "as" additions are very much incomplete as of this commit.

17 files changed:
level_0/f_status/c/status.h
level_1/fl_execute/c/execute-common.h
level_1/fl_execute/c/execute.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/c/private-execute.c
level_2/fll_execute/c/private-execute.h
level_2/fll_status/c/status.c
level_3/controller/c/private-rule.c
level_3/controller/c/private-rule.h
level_3/fake/c/private-build.c
level_3/fake/c/private-fake.c
level_3/fake/c/private-make.c
level_3/firewall/c/firewall.c
level_3/firewall/c/private-firewall.c

index 055413d9c7bd0502e73a57312647ff9185fdfa25..7a9e7c68d7cbae5a1987a508875ef542004df7af 100644 (file)
@@ -153,12 +153,16 @@ extern "C" {
       F_block_not,
       F_bound,
       F_bound_not,
+      F_capability,
+      F_capability_not,
       F_child,
       F_child_not,
       F_complete,
       F_complete_not,
       F_connected,
       F_connected_not,
+      F_container,
+      F_container_not,
       F_critical,
       F_critical_not,
       F_deadlock,
@@ -185,6 +189,10 @@ extern "C" {
       F_fork_not,
       F_found,
       F_found_not,
+      F_group,
+      F_group_not,
+      F_ignore,
+      F_ignore_not,
       F_input,
       F_input_not,
       F_input_output,
@@ -208,6 +216,8 @@ extern "C" {
       F_mount_not,
       F_name,
       F_name_not,
+      F_nice,
+      F_nice_not,
       F_optional,
       F_optional_not,
       F_output,
@@ -239,6 +249,8 @@ extern "C" {
       F_resource_not,
       F_search,
       F_search_not,
+      F_schedule,
+      F_schedule_not,
       F_signal,
       F_signal_not,
       F_space,
@@ -253,6 +265,8 @@ extern "C" {
       F_supported_not,
       F_syntax,
       F_syntax_not,
+      F_user,
+      F_user_not,
       F_utf,
       F_utf_not,
       F_valid,
@@ -263,6 +277,8 @@ extern "C" {
       F_wait_not,
       F_warn,
       F_warn_not,
+      F_world,
+      F_world_not,
       F_write,
       F_write_not,
       F_write_only,
index 3efb1b7d8877809bcf760f422321914df1d071ec..3a5610c0b9bd74919bef393df97efb48f8571706 100644 (file)
@@ -51,6 +51,90 @@ extern "C" {
     set.data = 0;
 #endif // _di_fl_execute_parameter_t_
 
+/**
+ * A structure representing an array of group ids.
+ *
+ * groups: a pointer to an array of groups.
+ * size:   the length of the array of groups.
+ */
+#ifndef _di_fl_execute_groups_t_
+  typedef struct {
+    gid_t *groups;
+    f_array_length_t size;
+  } fl_execute_groups_t;
+
+  #define fl_execute_groups_t_initialize { 0, 0 }
+
+  #define fl_macro_execute_groups_t_initialize(groups, size) { groups, size }
+
+  #define fl_execute_groups_t_clear(structure) \
+    structure.groups = 0; \
+    structure.size = 0;
+#endif // _di_fl_execute_groups_t_
+
+/**
+ * A structure representing a scheduler and its parameters for execution.
+ *
+ * policy:    the scheduler policy.
+ * parameter: a pointer to the scheduler parameters;
+ */
+#ifndef _di_fl_execute_scheduler_t_
+  typedef struct {
+    int policy;
+    const struct sched_param *parameter;
+  } fl_execute_scheduler_t;
+
+  #define fl_execute_scheduler_t_initialize { 0, 0 }
+
+  #define fl_macro_execute_scheduler_t_initialize(policy, parameter) { policy, parameter }
+
+  #define fl_execute_scheduler_t_clear(scheduler) \
+    scheduler.policy = 0; \
+    scheduler.parameter = 0;
+#endif // _di_fl_execute_scheduler_t_
+
+/**
+ * A structure for containing identity and access related parameters for the execute functions that call the execv() family of functions.
+ *
+ * There are likely many more identity and access related things that can be done but this focuses on a small core set of those.
+ *
+ * Note: Containers, or cgroups, exist here as a full file path in which the PID of a child process is to be written to.
+ *       This may change as more is learned about using cgroups, but it is not known if there are any functions available like set_cgroup(..).
+ *
+ * nice:       the niceness value to assign the child process to, set to 0 to not use.
+ * id_user:    the id of the user to assign the child process to, set to 0 to not use.
+ * id_group:   the id of the group to assign the child process to, set to 0 to not use.
+ * capability: all of the capabilities to assign the child process to, set to 0 to not use.
+ * ids_group:  the ids of each supplemental group to assign the child process to, set to 0 to not use.
+ * scheduler:  the scheduler to assign the child process to, set to 0 to not use.
+ * containers: an array of cgroups (container groups) to assign the child PID to, set to 0 to not use.
+ */
+#ifndef _di_fl_execute_as_t_
+  typedef struct {
+    const int *nice;
+    const uid_t *id_user;
+    const gid_t *id_group;
+    //const cap_t *capability; // @todo
+
+    const fl_execute_groups_t *ids_group;
+    const fl_execute_scheduler_t *scheduler;
+    const f_string_dynamics_t *containers;
+  } fl_execute_as_t;
+
+  #define fl_execute_as_t_initialize { 0, 0, 0, /*0,*/ fl_execute_groups_t_initialize, fl_execute_scheduler_t_initialize, f_string_dynamics_t_initialize }
+
+  #define fl_macro_execute_as_t_initialize(nice, id_user, id_group, /*capability,*/ id_groups, scheduler, containers) { nice, id_user, id_group, /*capability,*/ id_groups, scheduler, containers }
+
+  #define fl_execute_as_t_clear(as) \
+    as.nice = 0; \
+    as.id_user = 0; \
+    as.id_group = 0; \
+    /*as.capability = 0;*/ \
+    as.id_groups = 0; \
+    as.scheduler = 0; \
+    as.containers = 0;
+#endif // _di_fl_execute_as_t_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index ed970c08d53d881f5e3aa5018b05b1b9bb5a13bc..cd5e08e4a8600773f902a4e0fdd62e3c6fd16d1d 100644 (file)
@@ -6,11 +6,18 @@
  * Licenses: lgplv2.1
  *
  * Provides execute processing functionality.
+ *
+ * This utilizes setgroups() to set multiple supplementary groups.
+ * It appears that POSIX failed to provide this (despite providing getgroups()).
+ * There may be compatibility issues as a result of supporting setgroups().
  */
 #ifndef _FL_execute_h
 #define _FL_execute_h
 
 // libc includes
+#include <grp.h>
+#include <sched.h>
+//#include <sys/capability.h> // @todo
 
 // fll-0 includes
 #include <level_0/type.h>
index 3eb1a232e56d8ee5d3775d5165d7b6e463d92207..14bb0b3892207f8d8a42303cf0bb4a8c7cdeae7b 100644 (file)
@@ -242,6 +242,12 @@ extern "C" {
         case F_bound_not:
           *string = FL_status_string_bound_not;
           break;
+        case F_capability:
+          *string = FL_status_string_capability;
+          break;
+        case F_capability_not:
+          *string = FL_status_string_capability_not;
+          break;
         case F_child:
           *string = FL_status_string_child;
           break;
@@ -260,6 +266,12 @@ extern "C" {
         case F_connected_not:
           *string = FL_status_string_connected_not;
           break;
+        case F_container:
+          *string = FL_status_string_container;
+          break;
+        case F_container_not:
+          *string = FL_status_string_container_not;
+          break;
         case F_critical:
           *string = FL_status_string_critical;
           break;
@@ -338,6 +350,18 @@ extern "C" {
         case F_found_not:
           *string = FL_status_string_found_not;
           break;
+        case F_group:
+          *string = FL_status_string_group;
+          break;
+        case F_group_not:
+          *string = FL_status_string_group_not;
+          break;
+        case F_ignore:
+          *string = FL_status_string_ignore;
+          break;
+        case F_ignore_not:
+          *string = FL_status_string_ignore_not;
+          break;
         case F_input:
           *string = FL_status_string_input;
           break;
@@ -407,6 +431,12 @@ extern "C" {
         case F_name_not:
           *string = FL_status_string_name_not;
           break;
+        case F_nice:
+          *string = FL_status_string_nice;
+          break;
+        case F_nice_not:
+          *string = FL_status_string_nice_not;
+          break;
         case F_optional:
           *string = FL_status_string_optional;
           break;
@@ -500,6 +530,12 @@ extern "C" {
         case F_search_not:
           *string = FL_status_string_search_not;
           break;
+        case F_schedule:
+          *string = FL_status_string_schedule;
+          break;
+        case F_schedule_not:
+          *string = FL_status_string_schedule_not;
+          break;
         case F_signal:
           *string = FL_status_string_signal;
           break;
@@ -548,6 +584,12 @@ extern "C" {
         case F_supported_not:
           *string = FL_status_string_supported_not;
           break;
+        case F_user:
+          *string = FL_status_string_user;
+          break;
+        case F_user_not:
+          *string = FL_status_string_user_not;
+          break;
         case F_utf:
           *string = FL_status_string_utf;
           break;
@@ -572,6 +614,12 @@ extern "C" {
         case F_warn_not:
           *string = FL_status_string_warn_not;
           break;
+        case F_world:
+          *string = FL_status_string_world;
+          break;
+        case F_world_not:
+          *string = FL_status_string_world_not;
+          break;
         case F_write:
           *string = FL_status_string_write;
           break;
index 0f09466aa789fa97893bfe1fdddc3bc6fa6d243e..4fb4c29c50145a91434c31ffb73c4bd2f9a31b6c 100644 (file)
@@ -172,12 +172,16 @@ extern "C" {
     #define FL_status_string_block_not        "F_block_not"
     #define FL_status_string_bound            "F_bound"
     #define FL_status_string_bound_not        "F_bound_not"
+    #define FL_status_string_capability       "F_capability"
+    #define FL_status_string_capability_not   "F_capability_not"
     #define FL_status_string_child            "F_child"
     #define FL_status_string_child_not        "F_child_not"
     #define FL_status_string_complete         "F_complete"
     #define FL_status_string_complete_not     "F_complete_not"
     #define FL_status_string_connected        "F_connected"
     #define FL_status_string_connected_not    "F_connected_not"
+    #define FL_status_string_container        "F_container"
+    #define FL_status_string_container_not    "F_container_not"
     #define FL_status_string_critical         "F_critical"
     #define FL_status_string_critical_not     "F_critical_not"
     #define FL_status_string_deadlock         "F_deadlock"
@@ -204,6 +208,10 @@ extern "C" {
     #define FL_status_string_fork_not         "F_fork_not"
     #define FL_status_string_found            "F_found"
     #define FL_status_string_found_not        "F_found_not"
+    #define FL_status_string_group            "F_group"
+    #define FL_status_string_group_not        "F_group_not"
+    #define FL_status_string_ignore           "F_ignore"
+    #define FL_status_string_ignore_not       "F_ignore_not"
     #define FL_status_string_input            "F_input"
     #define FL_status_string_input_not        "F_input_not"
     #define FL_status_string_input_output     "F_input_output"
@@ -227,6 +235,8 @@ extern "C" {
     #define FL_status_string_mount_not        "F_mount_not"
     #define FL_status_string_name             "F_name"
     #define FL_status_string_name_not         "F_name_not"
+    #define FL_status_string_nice             "F_nice"
+    #define FL_status_string_nice_not         "F_nice_not"
     #define FL_status_string_optional         "F_optional"
     #define FL_status_string_optional_not     "F_optional_not"
     #define FL_status_string_output           "F_output"
@@ -258,6 +268,8 @@ extern "C" {
     #define FL_status_string_resource_not     "F_resource_not"
     #define FL_status_string_search           "F_search"
     #define FL_status_string_search_not       "F_search_not"
+    #define FL_status_string_schedule         "F_schedule"
+    #define FL_status_string_schedule_not     "F_schedule_not"
     #define FL_status_string_signal           "F_signal"
     #define FL_status_string_signal_not       "F_signal_not"
     #define FL_status_string_space            "F_space"
@@ -272,6 +284,8 @@ extern "C" {
     #define FL_status_string_syntax_not       "F_syntax_not"
     #define FL_status_string_supported        "F_supported"
     #define FL_status_string_supported_not    "F_supported_not"
+    #define FL_status_string_user             "F_user"
+    #define FL_status_string_user_not         "F_user_not"
     #define FL_status_string_utf              "F_utf"
     #define FL_status_string_utf_not          "F_utf_not"
     #define FL_status_string_valid            "F_valid"
@@ -282,6 +296,8 @@ extern "C" {
     #define FL_status_string_wait_not         "F_wait_not"
     #define FL_status_string_warn             "F_warn"
     #define FL_status_string_warn_not         "F_warn_not"
+    #define FL_status_string_world            "F_world"
+    #define FL_status_string_world_not        "F_world_not"
     #define FL_status_string_write            "F_write"
     #define FL_status_string_write_not        "F_write_not"
     #define FL_status_string_write_only       "F_write_only"
@@ -295,12 +311,16 @@ extern "C" {
     #define FL_status_string_block_not_length        11
     #define FL_status_string_bound_length            7
     #define FL_status_string_bound_not_length        11
+    #define FL_status_string_capability_length       12
+    #define FL_status_string_capability_not_length   16
     #define FL_status_string_child_length            7
     #define FL_status_string_child_not_length        11
     #define FL_status_string_complete_length         10
     #define FL_status_string_complete_not_length     14
     #define FL_status_string_connected_length        11
     #define FL_status_string_connected_not_length    15
+    #define FL_status_string_container_length        11
+    #define FL_status_string_container_not_length    15
     #define FL_status_string_critical_length         10
     #define FL_status_string_critical_not_length     14
     #define FL_status_string_deadlock_length         10
@@ -327,6 +347,10 @@ extern "C" {
     #define FL_status_string_fork_not_length         10
     #define FL_status_string_found_length            7
     #define FL_status_string_found_not_length        11
+    #define FL_status_string_group_length            7
+    #define FL_status_string_group_not_length        11
+    #define FL_status_string_ignore_length           8
+    #define FL_status_string_ignore_not_length       12
     #define FL_status_string_input_length            7
     #define FL_status_string_input_not_length        11
     #define FL_status_string_input_output_length     14
@@ -350,6 +374,8 @@ extern "C" {
     #define FL_status_string_mount_not_length        11
     #define FL_status_string_name_length             6
     #define FL_status_string_name_not_length         10
+    #define FL_status_string_nice_length             6
+    #define FL_status_string_nice_not_length         10
     #define FL_status_string_optional_length         10
     #define FL_status_string_optional_not_length     14
     #define FL_status_string_output_length           8
@@ -381,6 +407,8 @@ extern "C" {
     #define FL_status_string_resource_not_length     14
     #define FL_status_string_search_length           8
     #define FL_status_string_search_not_length       12
+    #define FL_status_string_schedule_length         10
+    #define FL_status_string_schedule_not_length     14
     #define FL_status_string_signal_length           8
     #define FL_status_string_signal_not_length       12
     #define FL_status_string_space_length            7
@@ -395,6 +423,8 @@ extern "C" {
     #define FL_status_string_supported_not_length    15
     #define FL_status_string_syntax_length           8
     #define FL_status_string_syntax_not_length       12
+    #define FL_status_string_user_length             6
+    #define FL_status_string_user_not_length         10
     #define FL_status_string_utf_length              5
     #define FL_status_string_utf_not_length          9
     #define FL_status_string_valid_length            7
@@ -405,6 +435,8 @@ extern "C" {
     #define FL_status_string_wait_not_length         10
     #define FL_status_string_warn_length             6
     #define FL_status_string_warn_not_length         10
+    #define FL_status_string_world_length            7
+    #define FL_status_string_world_not_length        11
     #define FL_status_string_write_length            7
     #define FL_status_string_write_not_length        11
     #define FL_status_string_write_only_length       12
index 38145ed3e841997772147dedbf93acfb94abc728..79ddaac440ec05103156dd7a74fff8fefec49c56 100644 (file)
@@ -168,7 +168,7 @@ extern "C" {
 #endif // _di_fll_execute_into_
 
 #ifndef _di_fll_execute_program_
-  f_return_status fll_execute_program(const f_string_t program, const f_string_statics_t arguments, fl_execute_parameter_t * const parameter, int *result) {
+  f_return_status fll_execute_program(const f_string_t program, const f_string_statics_t arguments, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result) {
     #ifndef _di_level_2_parameter_checking_
       if (!program && !arguments.used) return F_status_set_error(F_parameter);
       if (!result) return F_status_set_error(F_parameter);
@@ -274,17 +274,17 @@ extern "C" {
       if (F_status_is_error(status)) return status;
 
       if (parameter && parameter->data) {
-        return private_fll_execute_fork_data(program_path, fixed_arguments, parameter, result);
+        return private_fll_execute_fork_data(program_path, fixed_arguments, parameter, as, result);
       }
 
-      return private_fll_execute_fork(program_path, fixed_arguments, parameter, result);
+      return private_fll_execute_fork(program_path, fixed_arguments, parameter, as, result);
     }
 
     if (parameter && parameter->data) {
-      return private_fll_execute_fork_data(program, fixed_arguments, parameter, result);
+      return private_fll_execute_fork_data(program, fixed_arguments, parameter, as, result);
     }
 
-    return private_fll_execute_fork(program, fixed_arguments, parameter, result);
+    return private_fll_execute_fork(program, fixed_arguments, parameter, as, result);
   }
 #endif // _di_fll_execute_program_
 
index 00c18bd1a8b059c71fa2d069d7bb74b8d7091f1f..ce34a3d6a3e973178483562f9767cbf742622b79 100644 (file)
@@ -15,6 +15,7 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
@@ -381,6 +382,9 @@ extern "C" {
  * Otherwise, this returns F_child and assigns the child's return code to result for the child process.
  * The caller is expected to handle the appropriate exit procedures and memory deallocation for the child process when F_child is returned.
  *
+ * This returns F_capability, F_group, and F_user only for the child process and must be treated the same as F_child for the purposes of understanding what the current process is.
+ * These are essentialy F_child with explicit error codes that are returned instead of performing the desired execution.
+ *
  * @param program
  *   The name or path of the program.
  *   The string pointer may be set to 0, to designate that the first index in arguments is assumed to be the program.
@@ -404,15 +408,22 @@ extern "C" {
  *   data:
  *     A pointer to a string to pipe as standard input to the child process.
  *     The parent will block until the standard input is fully read or the child process exits.
+ * @param as
+ *   (optional) This and most of its fields are optional and are disabled when set to 0.
  * @param result
  *   The code returned after finishing execution of program.
  *
  * @return
  *   F_none on success.
- *   F_child on success but this is the child thread.
+ *   F_capability (with error bit) on failure to set capabilities in the child (only the child process returns this).
+ *   F_child (with error bit) on any failure without an explicit failure code (like F_group) before calling execute but this is the child thread.
  *   F_failure (with error bit) on execution failure.
  *   F_fork (with error bit) on fork failure.
+ *   F_group (with error bit) on failure to set GID in the child (only the child process returns this).
+ *   F_nice (with error bit) on failure to set process niceness in the child (only the child process returns this).
  *   F_pipe (with error bit) on pipe failure.
+ *   F_schedule (with error bit) on failure to set scheduler in the child (only the child process returns this).
+ *   F_user (with error bit) on failure to set UID in the child (only the child process returns this).
  *
  *   Errors (with error bit) from: f_environment_get().
  *   Errors (with error bit) from: f_file_exists().
@@ -423,6 +434,7 @@ extern "C" {
  *   Errors (with error bit) from: fl_string_dynamic_delete().
  *   Errors (with error bit) from: fl_string_dynamic_terminate().
  *
+ * @see cap_set_proc()
  * @see close()
  * @see clearenv()
  * @see dup2()
@@ -430,8 +442,14 @@ extern "C" {
  * @see execvp()
  * @see exit()
  * @see fork()
+ * @see getpid()
  * @see memcpy()
+ * @see nice()
  * @see pipe()
+ * @see sched_setscheduler()
+ * @see setgid()
+ * @see setgroups()
+ * @see setuid()
  * @see strnlen()
  * @see waitpid()
  *
@@ -443,7 +461,7 @@ extern "C" {
  * @see fl_string_dynamic_terminate()
  */
 #ifndef _di_fll_execute_program_
-  extern f_return_status fll_execute_program(const f_string_t program, const f_string_statics_t arguments, fl_execute_parameter_t * const parameter, int *result);
+  extern f_return_status fll_execute_program(const f_string_t program, const f_string_statics_t arguments, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result);
 #endif // _di_fll_execute_program_
 
 #ifdef __cplusplus
index eae5406625939d5bf13bd7851b468964a1249259..c3f81540c780f45b8f44cd388874bd90e5dc08bb 100644 (file)
@@ -117,7 +117,94 @@ extern "C" {
 #endif // !defined(_di_fll_execute_arguments_add_parameter_) || !defined(_di_fll_execute_arguments_add_parameter_set_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_set_)
 
 #if !defined(_di_fll_execute_program_)
-  f_return_status private_fll_execute_fork(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, int *result) {
+  f_return_status private_fll_execute_as(const fl_execute_as_t as, fl_execute_parameter_t * const parameter, int *result) {
+
+    if (as.nice) {
+      errno = 0;
+
+      if (nice(*as.nice) == -1 && errno == -1) {
+        *result = -1;
+
+        if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+          exit(*result);
+        }
+
+        return F_status_set_error(F_nice);
+      }
+    }
+
+    if (as.scheduler) {
+      const int process_id = getpid();
+
+      errno = 0;
+
+      if (sched_setscheduler(process_id, as.scheduler->policy, as.scheduler->parameter) == -1) {
+        *result = -1;
+
+        if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+          exit(*result);
+        }
+
+        return F_status_set_error(F_schedule);
+      }
+    }
+
+    /* @todo library dependencies, if this is not in libc, then this may not be supported. more investigation is needed.
+    if (as.capability) {
+      if (cap_set_proc(*as.capability) == -1) {
+        *result = -1;
+
+        if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+          exit(*result);
+        }
+
+        return F_status_set_error(F_capability);
+      }
+    }
+    */
+
+    if (as.ids_group) {
+      if (setgroups(as.ids_group->size, as.ids_group->groups) == -1) {
+        *result = -1;
+
+        if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+          exit(*result);
+        }
+
+        return F_status_set_error(F_group);
+      }
+    }
+
+    if (as.id_group) {
+      if (setgid(*as.id_group) == -1) {
+        *result = -1;
+
+        if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+          exit(*result);
+        }
+
+        return F_status_set_error(F_group);
+      }
+    }
+
+    if (as.id_user) {
+      if (setuid(*as.id_user) == -1) {
+        *result = -1;
+
+        if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+          exit(*result);
+        }
+
+        return F_status_set_error(F_user);
+      }
+    }
+
+    return F_none;
+  }
+#endif // !defined(_di_fll_execute_program_)
+
+#if !defined(_di_fll_execute_program_)
+  f_return_status private_fll_execute_fork(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result) {
 
     const pid_t process_id = fork();
 
@@ -155,6 +242,14 @@ extern "C" {
       } // for
     }
 
+    if (as) {
+      const f_status_t status = private_fll_execute_as(*as, parameter, result);
+
+      if (F_status_is_error(status)) {
+        return status;
+      }
+    }
+
     const int code = parameter && (parameter->option & fl_execute_parameter_option_path) ? execv(program, fixed_arguments) : execvp(program, fixed_arguments);
 
     if (result) {
@@ -170,7 +265,7 @@ extern "C" {
 #endif // !defined(_di_fll_execute_program_)
 
 #if !defined(_di_fll_execute_program_)
-  f_return_status private_fll_execute_fork_data(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, int *result) {
+  f_return_status private_fll_execute_fork_data(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result) {
 
     int descriptors[2] = { -1, -1 };
 
@@ -235,6 +330,14 @@ extern "C" {
 
     dup2(descriptors[0], f_type_descriptor_input);
 
+    if (as) {
+      const f_status_t status = private_fll_execute_as(*as, parameter, result);
+
+      if (F_status_is_error(status)) {
+        return status;
+      }
+    }
+
     const int code = parameter && parameter->option & fl_execute_parameter_option_path ? execv(program, fixed_arguments) : execvp(program, fixed_arguments);
 
     // close the write pipe for the child when done.
index 96c9b7a9986a2b4ee216f39eba9d097486c98772..6abd480c579b2a19351372e7ef30433127db028f 100644 (file)
@@ -105,6 +105,44 @@ extern "C" {
 #endif // !defined(_di_fll_execute_arguments_add_parameter_) || !defined(_di_fll_execute_arguments_add_parameter_set_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_set_)
 
 /**
+ * Private function for perform the execute as operations.
+ *
+ * This should be executed in the child thread.
+ *
+ * @param as
+ *   The "as" operations to perform.
+ * @param parameter
+ *   (optional) This and most of its fields are optional and are disabled when set to 0.
+ *   This function only cares about "option" on this structure.
+ *   option:
+ *     A bitwise set of options, such as: fl_execute_parameter_option_exit, and fl_execute_parameter_option_path.
+ * @param result
+ *   The code returned after finishing execution of program.
+ *
+ * @return
+ *   F_none on success.
+ *   F_capability (with error bit) on failure to set capabilities.
+ *   F_group (with error bit) on failure to set GID.
+ *   F_nice (with error bit) on failure to set process niceness.
+ *   F_schedule (with error bit) on failure to set scheduler.
+ *   F_user (with error bit) on failure to set UID.
+ *
+ * @see cap_set_proc()
+ * @see exit()
+ * @see getpid()
+ * @see nice()
+ * @see sched_setscheduler()
+ * @see setgid()
+ * @see setgroups()
+ * @see setuid()
+ *
+ * @see fll_execute_program()
+ */
+#if !defined(_di_fll_execute_program_)
+  extern f_return_status private_fll_execute_as(const fl_execute_as_t as, fl_execute_parameter_t * const parameter, int *result) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fll_execute_program_)
+
+/**
  * Private function for performing the fork and execute operation.
  *
  * This implementation ignores parameter.data.
@@ -131,14 +169,21 @@ extern "C" {
  *   data:
  *     A pointer to a string to pipe as standard input to the child process.
  *     The parent will block until the standard input is fully read or the child process exits.
+ * @param as
+ *   (optional) This and most of its fields are optional and are disabled when set to 0.
  * @param result
  *   The code returned after finishing execution of program.
  *
  * @return
  *   F_none on success.
+ *   F_capability (with error bit) on failure to set capabilities in the child (only the child process returns this).
  *   F_child on success but this is the child thread.
  *   F_failure (with error bit) on execution failure.
  *   F_fork (with error bit) on fork failure.
+ *   F_group (with error bit) on failure to set GID in the child (only the child process returns this).
+ *   F_nice (with error bit) on failure to set process niceness in the child (only the child process returns this).
+ *   F_schedule (with error bit) on failure to set scheduler in the child (only the child process returns this).
+ *   F_user (with error bit) on failure to set UID in the child (only the child process returns this).
  *
  * @see clearenv()
  * @see execv()
@@ -151,7 +196,7 @@ extern "C" {
  * @see fll_execute_program()
  */
 #if !defined(_di_fll_execute_program_)
-  extern f_return_status private_fll_execute_fork(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, int *result) f_gcc_attribute_visibility_internal;
+  extern f_return_status private_fll_execute_fork(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result) f_gcc_attribute_visibility_internal;
 #endif // !defined(_di_fll_execute_program_)
 
 /**
@@ -181,15 +226,22 @@ extern "C" {
  *   data:
  *     A pointer to a string to pipe as standard input to the child process.
  *     The parent will block until the standard input is fully read or the child process exits.
+ * @param as
+ *   (optional) This and most of its fields are optional and are disabled when set to 0.
  * @param result
  *   The code returned after finishing execution of program.
  *
  * @return
  *   F_none on success.
+ *   F_capability (with error bit) on failure to set capabilities in the child (only the child process returns this).
  *   F_child on success but this is the child thread.
  *   F_failure (with error bit) on execution failure.
  *   F_fork (with error bit) on fork failure.
+ *   F_group (with error bit) on failure to set GID in the child (only the child process returns this).
+ *   F_nice (with error bit) on failure to set process niceness in the child (only the child process returns this).
  *   F_pipe (with error bit) on pipe failure.
+ *   F_schedule (with error bit) on failure to set scheduler in the child (only the child process returns this).
+ *   F_user (with error bit) on failure to set UID in the child (only the child process returns this).
  *
  * @see clearenv()
  * @see close()
@@ -205,7 +257,7 @@ extern "C" {
  * @see fll_execute_program()
  */
 #if !defined(_di_fll_execute_program_)
-  extern f_return_status private_fll_execute_fork_data(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, int *result) f_gcc_attribute_visibility_internal;
+  extern f_return_status private_fll_execute_fork_data(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result) f_gcc_attribute_visibility_internal;
 #endif // !defined(_di_fll_execute_program_)
 
 /**
index f2c459fa9c7488ed66bff8374aff80a1b5c30fda..16aa35bed3206801f4501df2309644450cca6948 100644 (file)
@@ -406,13 +406,13 @@ extern "C" {
         return F_none;
       }
 
-      if (fl_string_compare(string, FL_status_string_complete, length, FL_status_string_complete_length) == F_equal_to) {
-        *code = F_complete;
+      if (fl_string_compare(string, FL_status_string_capability, length, FL_status_string_capability_length) == F_equal_to) {
+        *code = F_capability;
         return F_none;
       }
 
-      if (fl_string_compare(string, FL_status_string_complete_not, length, FL_status_string_complete_not_length) == F_equal_to) {
-        *code = F_complete_not;
+      if (fl_string_compare(string, FL_status_string_capability_not, length, FL_status_string_capability_not_length) == F_equal_to) {
+        *code = F_capability_not;
         return F_none;
       }
 
@@ -426,6 +426,16 @@ extern "C" {
         return F_none;
       }
 
+      if (fl_string_compare(string, FL_status_string_complete, length, FL_status_string_complete_length) == F_equal_to) {
+        *code = F_complete;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_complete_not, length, FL_status_string_complete_not_length) == F_equal_to) {
+        *code = F_complete_not;
+        return F_none;
+      }
+
       if (fl_string_compare(string, FL_status_string_connected, length, FL_status_string_connected_length) == F_equal_to) {
         *code = F_connected;
         return F_none;
@@ -436,6 +446,16 @@ extern "C" {
         return F_none;
       }
 
+      if (fl_string_compare(string, FL_status_string_container, length, FL_status_string_container_length) == F_equal_to) {
+        *code = F_container;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_container_not, length, FL_status_string_container_not_length) == F_equal_to) {
+        *code = F_container_not;
+        return F_none;
+      }
+
       if (fl_string_compare(string, FL_status_string_critical, length, FL_status_string_critical_length) == F_equal_to) {
         *code = F_critical;
         return F_none;
@@ -566,6 +586,26 @@ extern "C" {
         return F_none;
       }
 
+      if (fl_string_compare(string, FL_status_string_group, length, FL_status_string_group_length) == F_equal_to) {
+        *code = F_group;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_group_not, length, FL_status_string_group_not_length) == F_equal_to) {
+        *code = F_group_not;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_ignore, length, FL_status_string_ignore_length) == F_equal_to) {
+        *code = F_ignore;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_ignore_not, length, FL_status_string_ignore_not_length) == F_equal_to) {
+        *code = F_ignore_not;
+        return F_none;
+      }
+
       if (fl_string_compare(string, FL_status_string_input, length, FL_status_string_input_length) == F_equal_to) {
         *code = F_input;
         return F_none;
@@ -681,6 +721,16 @@ extern "C" {
         return F_none;
       }
 
+      if (fl_string_compare(string, FL_status_string_nice, length, FL_status_string_nice_length) == F_equal_to) {
+        *code = F_nice;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_nice_not, length, FL_status_string_nice_not_length) == F_equal_to) {
+        *code = F_nice_not;
+        return F_none;
+      }
+
       if (fl_string_compare(string, FL_status_string_optional, length, FL_status_string_optional_length) == F_equal_to) {
         *code = F_optional;
         return F_none;
@@ -836,6 +886,16 @@ extern "C" {
         return F_none;
       }
 
+      if (fl_string_compare(string, FL_status_string_schedule, length, FL_status_string_schedule_length) == F_equal_to) {
+        *code = F_schedule;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_schedule_not, length, FL_status_string_schedule_not_length) == F_equal_to) {
+        *code = F_schedule_not;
+        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;
@@ -906,6 +966,16 @@ extern "C" {
         return F_none;
       }
 
+      if (fl_string_compare(string, FL_status_string_user, length, FL_status_string_user_length) == F_equal_to) {
+        *code = F_user;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_user_not, length, FL_status_string_user_not_length) == F_equal_to) {
+        *code = F_user_not;
+        return F_none;
+      }
+
       if (fl_string_compare(string, FL_status_string_utf, length, FL_status_string_utf_length) == F_equal_to) {
         *code = F_utf;
         return F_none;
@@ -956,6 +1026,16 @@ extern "C" {
         return F_none;
       }
 
+      if (fl_string_compare(string, FL_status_string_world, length, FL_status_string_world_length) == F_equal_to) {
+        *code = F_world;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_world_not, length, FL_status_string_world_not_length) == F_equal_to) {
+        *code = F_world_not;
+        return F_none;
+      }
+
       if (fl_string_compare(string, FL_status_string_write, length, FL_status_string_write_length) == F_equal_to) {
         *code = F_write;
         return F_none;
index 04bb3b3e8af3ba2c0b67146d1f2c32b2c9b9bf77..23ac512f539bcd7928def264b3cf0efb915b49f2 100644 (file)
@@ -439,6 +439,7 @@ extern "C" {
 #ifndef _di_controller_rule_execute_
   f_return_status controller_rule_execute(const controller_cache_t cache, const f_array_length_t index, const uint8_t type, controller_data_t *data, controller_setting_t *setting) {
     f_status_t status = F_none;
+    f_status_t success = F_false;
 
     f_array_length_t i = 0;
     f_array_length_t j = 0;
@@ -487,7 +488,13 @@ extern "C" {
           }
 
           status = controller_rule_execute_foreground(item->type, *action, 0, action->parameters, 0, &parameter, data);
-          if (F_status_is_error(status)) break;
+
+          if (F_status_is_error(status)) {
+            action->status = F_status_set_error(F_failure);
+            break;
+          }
+
+          success = F_true;
         }
         else if (item->type == controller_rule_item_type_script) {
           parameter.data = &action->parameters.array[0];
@@ -497,7 +504,13 @@ extern "C" {
           }
 
           status = controller_rule_execute_foreground(item->type, *action, rule->script.used ? rule->script.string : controller_default_program_script, arguments_none, 0, &parameter, data);
-          if (F_status_is_error(status)) break;
+
+          if (F_status_is_error(status)) {
+            action->status = F_status_set_error(F_failure);
+            break;
+          }
+
+          success = F_true;
         }
         else if (item->type == controller_rule_item_type_service) {
 
@@ -505,14 +518,30 @@ extern "C" {
             parameter.option |= fl_execute_parameter_option_path;
           }
 
-          // @todo
-          //status = controller_rule_execute_background(item->type, *action, 0, action->parameters, 0, &parameter, data);
-          //if (F_status_is_error(status)) break;
+          status = controller_rule_execute_pid_with(item->type, *action, 0, action->parameters, 0, &parameter, data);
+
+          if (F_status_is_error(status)) {
+            action->status = F_status_set_error(F_failure);
+            break;
+          }
+
+          success = F_true;
         }
         else {
-          status = F_none;
 
-          // unknown, just ignore for now. (@todo print a warning when in debug mode.)
+          if (data->warning.verbosity == f_console_verbosity_debug) {
+            fprintf(data->warning.to.stream, "%c", f_string_eol_s[0]);
+            fprintf(data->warning.to.stream, "%s%sAction type is unknown, ignoring.%s%c", data->warning.context.before->string, data->warning.prefix ? data->warning.prefix : f_string_empty_s, data->warning.context.after->string, f_string_eol_s[0]);
+
+            controller_rule_error_print(data->warning, cache, F_true);
+          }
+
+          action->status = F_ignore;
+
+          if (success != F_true) {
+            success = F_ignore;
+          }
+
           continue;
         }
 
@@ -524,15 +553,71 @@ extern "C" {
 
     fl_string_maps_delete(&environment);
 
-    return status;
+    if (F_status_is_error(status) || success == F_false) {
+      rule->status = F_status_set_error(F_failure);
+    }
+    else if (success == F_ignore || success == F_busy) {
+      rule->status = success;
+    }
+    else {
+      rule->status = F_none;
+    }
+
+    return rule->status;
   }
 #endif // _di_controller_rule_execute_
 
+#ifndef _di_controller_rule_execute_pid_with_
+  f_return_status controller_rule_execute_pid_with(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, controller_data_t *data) {
+    int result = 0;
+
+    // @todo check to see if pid file exists.
+
+    // @todo this needs to support/use an option to designate that the process automatically forks in the background.
+    //       in which case fll_execute_program() is called.
+    //       otherwise this needs to call an asynchronous execute process.
+    //       until then, this controller_rule_execute_pid_with() function is not correct and only represents a process that forks to the background.
+    f_status_t status = fll_execute_program(program, arguments, parameter, 0, &result);
+
+    if (status == F_child) {
+      data->child = result;
+
+      return F_child;
+    }
+
+    if (result != 0) {
+      status = F_status_set_error(F_failure);
+    }
+
+    if (F_status_is_error(status)) {
+      if (F_status_set_fine(status) == F_failure) {
+        controller_rule_error_print_execute(data->error, type == controller_rule_item_type_script, program, result);
+      }
+      else if (F_status_set_fine(status) == F_file_found_not) {
+        controller_rule_error_print_execute_not_found(data->error, F_false, program);
+      }
+      else {
+        fll_error_print(data->error, F_status_set_fine(status), "fll_execute_program_environment", F_true);
+      }
+
+      data->child = 0;
+
+      return status;
+    }
+
+    // @todo wait for pid file or timeout.
+
+    data->child = 0;
+
+    return status;
+  }
+#endif // _di_controller_rule_execute_pid_with_
+
 #ifndef _di_controller_rule_execute_foreground_
   f_return_status controller_rule_execute_foreground(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, controller_data_t *data) {
     int result = 0;
 
-    f_status_t status = fll_execute_program(program, arguments, parameter, &result);
+    f_status_t status = fll_execute_program(program, arguments, parameter, 0, &result);
 
     if (status == F_child) {
       data->child = result;
index 7f462158842c40c1373dbd48038615dc38ea290f..81e4f6f003b71b9fbea9bf07df5b18d7a1c70d5a 100644 (file)
@@ -235,6 +235,50 @@ extern "C" {
 #endif // _di_controller_rule_execute_
 
 /**
+ * Perform an execution of the given rule in the foreground or background and creating a PID file.
+ *
+ * When this is synchronous, this will wait for the PID file to be generated before continuing.
+ * When this is asynchronous, this will continue on adding the rule id and action to the asynchronous list.
+ *
+ * @param type
+ *   The item type code.
+ * @param action
+ *   The action to perform based on the action type codes.
+ *
+ *   Only subset of the action type codes are supported:
+ *   - controller_rule_action_type_kill
+ *   - controller_rule_action_type_reload
+ *   - controller_rule_action_type_restart
+ *   - controller_rule_action_type_start
+ *   - controller_rule_action_type_stop
+ * @param program
+ *   The program to use (such as "bash").
+ * @param arguments
+ *   The arguments to pass to the program.
+ * @param options
+ *   The controller execute options (and not fl_execute_parameter_t.option).
+ *   This is for designating asynchronous and other controller specific execution options.
+ *   @todo this is not yet implemented.
+ * @param parameter
+ *   The execute parameter settings.
+ * @param data
+ *   The program data.
+ *
+ * @return
+ *   F_none on success.
+ *   F_busy on successful execute in asynchronous mode (executed process may or may not fail later on).
+ *   F_child on child process exiting.
+ *   F_signal on (exit) signal received.
+ *
+ *   Errors (with error bit) from: fll_execute_program().
+ *
+ * @see fll_execute_program()
+ */
+#ifndef _di_controller_rule_execute_pid_with_
+  extern f_return_status controller_rule_execute_pid_with(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, controller_data_t *data) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_rule_execute_pid_with_
+
+/**
  * Perform an execution of the given rule in the foreground.
  *
  * @param type
@@ -249,9 +293,9 @@ extern "C" {
  *   - controller_rule_action_type_start
  *   - controller_rule_action_type_stop
  * @param program
- *   The script program to use (such as "bash").
+ *   The program to use (such as "bash").
  * @param arguments
- *   The arguments to pass to the script.
+ *   The arguments to pass to the program.
  * @param options
  *   The controller execute options (and not fl_execute_parameter_t.option).
  *   This is for designating asynchronous and other controller specific execution options.
index 3939d2d12086791e06dfe4dd97835aa82a3617c4..cd0d6439fa629682840f492b0100444a8a6e0b23 100644 (file)
@@ -666,7 +666,7 @@ extern "C" {
 
       fl_execute_parameter_t parameter = fl_macro_execute_parameter_t_initialize(fl_execute_parameter_option_path, &data_build.environment, &signals, 0);
 
-      *status = fll_execute_program(path.string, arguments, &parameter, &return_code);
+      *status = fll_execute_program(path.string, arguments, &parameter, 0, &return_code);
 
       fl_string_dynamics_delete(&arguments);
 
index 806821b6276cd87eb78f15c8d8fd6abb1ff0b1ae..5f6addddfce0bcc8e6d5d5d5fbb4f834a9816a65 100644 (file)
@@ -43,7 +43,7 @@ extern "C" {
 
       fl_execute_parameter_t parameter = fl_macro_execute_parameter_t_initialize(0, &environment, &signals, 0);
 
-      *status = fll_execute_program(program.string, arguments, &parameter, &return_code);
+      *status = fll_execute_program(program.string, arguments, &parameter, 0, &return_code);
 
       if (fake_signal_received(data)) {
         *status = F_status_set_error(F_signal);
index c05e60d40190e92a29a36aa5bfcc178a241e5d24..63669465a9cec59649266135cf835d94d9fa4046 100644 (file)
@@ -3818,7 +3818,7 @@ extern "C" {
 
     fl_execute_parameter_t parameter = fl_macro_execute_parameter_t_initialize(as_shell ? 0 : fl_execute_parameter_option_path, &data_make->environment, &signals, 0);
 
-    status = fll_execute_program(program.string, arguments, &parameter, &return_code);
+    status = fll_execute_program(program.string, arguments, &parameter, 0, &return_code);
 
     if (status == F_status_set_error(F_signal)) {
       return status;
index e196987660e717de1840cc4f1973eac3ca468225..844c7f08335db58201c94a89847116201a02d327 100644 (file)
@@ -251,7 +251,7 @@ extern "C" {
           parameters.array[4].used = 9;
           parameters.array[5].used = 6;
 
-          status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, &return_code);
+          status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, 0, &return_code);
 
           // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
           if (status == F_child) {
@@ -284,7 +284,7 @@ extern "C" {
           parameters.array[4].used = 9;
           parameters.array[5].used = 6;
 
-          status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, &return_code);
+          status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, 0, &return_code);
 
           // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
           if (status == F_child) {
@@ -313,7 +313,7 @@ extern "C" {
           parameters.array[2].used = 9;
           parameters.array[3].used = 6;
 
-          status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, &return_code);
+          status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, 0, &return_code);
 
           // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
           if (status == F_child) {
index 97beec1ca18c0ba654e7becf7a0816e51272050d..95e8438c7a4e5233329409d96e7e2a9cb542a21e 100644 (file)
@@ -752,7 +752,7 @@ f_return_status firewall_perform_commands(const firewall_local_data_t local, con
                       fprintf(f_type_debug, "\n");
                     }
 
-                    status = fll_execute_program((f_string_t) current_tool, arguments, 0, &return_code);
+                    status = fll_execute_program((f_string_t) current_tool, arguments, 0, 0, &return_code);
 
                     // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
                     if (status == F_child) {
@@ -826,7 +826,7 @@ f_return_status firewall_perform_commands(const firewall_local_data_t local, con
             fprintf(f_type_debug, "\n");
           }
 
-          status = fll_execute_program(current_tool, arguments, 0, &return_code);
+          status = fll_execute_program(current_tool, arguments, 0, 0, &return_code);
 
           // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
           if (status == F_child) {
@@ -1070,7 +1070,7 @@ f_return_status firewall_create_custom_chains(firewall_reserved_chains_t *reserv
         }
 
         tool = firewall_program_iptables;
-        status = fll_execute_program((f_string_t) firewall_tool_iptables, arguments, 0, &return_code);
+        status = fll_execute_program((f_string_t) firewall_tool_iptables, arguments, 0, 0, &return_code);
 
         // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
         if (status == F_child) {
@@ -1091,7 +1091,7 @@ f_return_status firewall_create_custom_chains(firewall_reserved_chains_t *reserv
           }
 
           tool = firewall_program_ip6tables;
-          status = fll_execute_program((f_string_t) firewall_tool_ip6tables, arguments, 0, &return_code);
+          status = fll_execute_program((f_string_t) firewall_tool_ip6tables, arguments, 0, 0, &return_code);
 
           // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
           if (status == F_child) {
@@ -1179,7 +1179,7 @@ f_return_status firewall_delete_chains(const firewall_data_t data) {
       fprintf(f_type_debug, "\n");
     }
 
-    status = fll_execute_program(tools[i], arguments, 0, &return_code);
+    status = fll_execute_program(tools[i], arguments, 0, 0, &return_code);
 
     // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
     if (status == F_child) {
@@ -1239,7 +1239,7 @@ f_return_status firewall_delete_chains(const firewall_data_t data) {
       fprintf(f_type_debug, "\n");
     }
 
-    status = fll_execute_program(tools[i], arguments, 0, &return_code);
+    status = fll_execute_program(tools[i], arguments, 0, 0, &return_code);
 
     // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
     if (status == F_child) {
@@ -1321,7 +1321,7 @@ f_return_status firewall_default_lock(const firewall_data_t data) {
         fprintf(f_type_debug, "\n");
       }
 
-      status = fll_execute_program(tools[j], arguments, 0, &return_code);
+      status = fll_execute_program(tools[j], arguments, 0, 0, &return_code);
 
       // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
       if (status == F_child) {