]> Kevux Git Server - fll/commitdiff
Progress: controller program, working on execute script logic.
authorKevin Day <thekevinday@gmail.com>
Fri, 18 Dec 2020 04:18:00 +0000 (22:18 -0600)
committerKevin Day <thekevinday@gmail.com>
Fri, 18 Dec 2020 04:18:00 +0000 (22:18 -0600)
I have been tossing around how exactly I want to implement the execute with piped data.
I have decided that I should clean up the parameters and redesign it to accept a few specialized structures.

Before I do that, I wanted to confirm that the pipe to shell (such as bash) works as I expect it to.
This tweaks the code to a temporary state where I can automatically execute some bash script with some string piped to it.
This seems to work as expected and errors out as expected.

I also need to write some asynchronous functions to help with managing asynchronous processes.
This might require a new series of projects (f_asynchronous, fl_asynchronous, etc..).

Note: "bash" was used as the default script, but I really need to provide some sort of configuration to change this.

level_0/f_execute/c/execute-common.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_3/controller/c/controller.h
level_3/controller/c/private-common.h
level_3/controller/c/private-rule.c
level_3/controller/c/private-rule.h
level_3/controller/data/build/dependencies
level_3/controller/data/build/settings

index b2201d119591dfd407d615e5861193f3b3b048ee..5e5ed2793417cd5e7504362f75bc7a93f39693d4 100644 (file)
@@ -17,30 +17,34 @@ extern "C" {
 #endif
 
 /**
- * A set containing the standard descriptors for use in pipes during the execution process.
+ * A structure for use in processing asynchronous execute behavior.
  *
  * Future versions may suppot stdwarn and stddebug if there ever is such a thing.
  *
  * Descriptors always use -1 to designate not used because 0 represent a valid descriptor.
+ * The process ID always uses -1 to designate no valid process ID is set.
  *
- * input:  the input file descriptor.
- * output: the output file descriptor.
- * error:  the error file descriptor.
+ * input:   the input file descriptor.
+ * output:  the output file descriptor.
+ * error:   the error file descriptor.
+ * process: the process ID whereas 0 represents a parent and anything greater than 0 represents a child.
  */
-#ifndef _di_f_execute_pipe_t_
+#ifndef _di_f_execute_asynchronous_t_
   typedef struct {
     int input;
     int output;
     int error;
-  } f_execute_pipe_t;
+    int process;
+  } f_execute_asynchronous_t;
 
-  #define f_execute_pipe_t_initialize { -1, -1, -1 }
+  #define f_execute_asynchronous_t_initialize { -1, -1, -1, -1 }
 
-  #define f_execute_pipe_t_clear(set) \
+  #define f_execute_asynchronous_t_clear(set) \
     set.input = -1; \
     set.output = -1; \
-    set.error = -1;
-#endif // _di_f_execute_pipe_t_
+    set.error = -1; \
+    set.process = -1;
+#endif // _di_f_execute_asynchronous_t_
 
 #ifdef __cplusplus
 } // extern "C"
index da9c2a6715d532d181091dc249d65e684bdca1dc..948e98aa1e438ae79b03c7ce9b960517ea843f50 100644 (file)
@@ -130,7 +130,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, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, 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, f_string_static_t * const pipe, int *result) {
     #ifndef _di_level_2_parameter_checking_
       if (!result) return F_status_set_error(F_parameter);
     #endif // _di_level_2_parameter_checking_
@@ -163,7 +163,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, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) {
+  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, const f_signal_how_t *signals, f_string_static_t * const pipe, int *result) {
     #ifndef _di_level_2_parameter_checking_
       if (!result) return F_status_set_error(F_parameter);
     #endif // _di_level_2_parameter_checking_
@@ -194,7 +194,7 @@ extern "C" {
 #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, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, 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, f_string_static_t * const pipe, int *result) {
     #ifndef _di_level_2_parameter_checking_
       if (!result) return F_status_set_error(F_parameter);
     #endif // _di_level_2_parameter_checking_
@@ -216,7 +216,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, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) {
+  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, const f_signal_how_t *signals, f_string_static_t * const pipe, int *result) {
     #ifndef _di_level_2_parameter_checking_
       if (!result) return F_status_set_error(F_parameter);
     #endif // _di_level_2_parameter_checking_
index 8c5885220c085afa72ab625950a092fc2c742894..64e7de94fa55f460cd8b81f16600a869f35c44c7 100644 (file)
@@ -334,14 +334,8 @@ extern "C" {
  * This does validate that the program path exists.
  *
  * This does not call exit() when the child process exits.
- * Instead, this returns F_child and assigns the child's return code to result.
- * The caller is expected to handle the appropriate exit procedures and memory deallocation.
- *
- * When the passed pipe parameter is not NULL, this function is effectively asynchronous and will not block.
- * The caller is then expected to handle all read/write operations to/from the pipe.
- * The caller is expected to appropriately call waitpid() or similar as needed.
- * The caller is expected to handle both parent and child process (status is F_parent for parent and F_child for child.).
- * When the passed paremeter is NULL, then this function is effectively synchronous and blocks until child exits.
+ * Instead, 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.
  *
  * @param program_path
  *   The entire path to the program.
@@ -351,9 +345,7 @@ extern "C" {
  *   (optional) A pointer to the set of signals.
  *   Set to 0 to disable.
  * @param pipe
- *   (optional) A pointer to the set of pipe desciptors (I/O) to be used by the child process.
- *   When a non-zero address, the child process will assign these as the standard I/O file descriptors for piping to/from the parent/child.
- *   For each pipe, setting a value of -1 means to use the default pipe.
+ *   (optional) A pointer to a string to pipe as standard input to the child process.
  *   Set to 0 to disable.
  * @param result
  *   The code returned after finishing execution of program_path.
@@ -361,44 +353,39 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_child on success but this is the child thread.
- *   F_parent on success but this is the parent thread and pipe is non-zero (function is not blocking).
  *   F_failure (with error bit) on execution failure.
  *   F_fork (with error bit) on fork failure.
+ *   F_pipe (with error bit) on pipe failure.
  *
  *   Errors (with error bit) from: f_file_exists().
  *   Errors (with error bit) from: f_signal_set_handle().
  *
+ * @see close()
  * @see dup2()
  * @see execv()
- * @see exit()
+ * @see execvp()
  * @see fork()
- * @see memcpy()
- * @see strnlen()
+ * @see pipe()
  * @see waitpid()
  *
  * @see f_file_exists()
  * @see f_signal_set_handle()
  */
 #ifndef _di_fll_execute_path_
-  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, f_execute_pipe_t * const pipe, 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, f_string_static_t * const pipe, int *result);
 #endif // _di_fll_execute_path_
 
 /**
  * Execute a program given some path + program name (such as "/bin/bash").
  *
- * This does validate that the program path exists.
- *
+ * Uses the provided environment array to designate the environment for the program being executed.
  * The environment is defined by the names and values pair.
  *
- * This does not call exit() when the child process exits.
- * Instead, this returns F_child and assigns the child's return code to result.
- * The caller is expected to handle the appropriate exit procedures and memory deallocation.
+ * This does validate that the program path exists.
  *
- * When the passed pipe parameter is not NULL, this function is effectively asynchronous and will not block.
- * The caller is then expected to handle all read/write operations to/from the pipe.
- * The caller is expected to appropriately call waitpid() or similar as needed.
- * The caller is expected to handle both parent and child process (status is F_parent for parent and F_child for child.).
- * When the passed paremeter is NULL, then this function is effectively synchronous and blocks until child exits.
+ * This does not call exit() when the child process exits.
+ * Instead, 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.
  *
  * @param program_path
  *   The entire path to the program.
@@ -416,9 +403,7 @@ extern "C" {
  *   (optional) A pointer to the set of signals.
  *   Set to 0 to disable.
  * @param pipe
- *   (optional) A pointer to the set of pipe desciptors (I/O) to be used by the child process.
- *   When a non-zero address, the child process will assign these as the standard I/O file descriptors for piping to/from the parent/child.
- *   For each pipe, setting a value of -1 means to use the default pipe.
+ *   (optional) A pointer to a string to pipe as standard input to the child process.
  *   Set to 0 to disable.
  * @param result
  *   The code returned after finishing execution of program_path.
@@ -426,19 +411,21 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_child on success but this is the child thread.
- *   F_parent on success but this is the parent thread and pipe is non-zero (function is not blocking).
  *   F_failure (with error bit) on execution failure.
  *   F_fork (with error bit) on fork failure.
+ *   F_pipe (with error bit) on pipe failure.
  *
  *   Errors (with error bit) from: f_environment_set_dynamic().
  *   Errors (with error bit) from: f_file_exists().
  *   Errors (with error bit) from: f_signal_set_handle().
  *
+ * @see close()
  * @see clearenv()
  * @see dup2()
- * @see execv()
+ * @see execvp()
  * @see fork()
  * @see memcpy()
+ * @see pipe()
  * @see strnlen()
  * @see waitpid()
  *
@@ -447,7 +434,7 @@ extern "C" {
  * @see f_signal_set_handle()
  */
 #ifndef _di_fll_execute_path_environment_
-  extern 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, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result);
+  extern 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, const f_signal_how_t *signals, f_string_static_t * const pipe, int *result);
 #endif // _di_fll_execute_path_environment_
 
 /**
@@ -456,14 +443,8 @@ extern "C" {
  * This does not validate the path to the program.
  *
  * This does not call exit() when the child process exits.
- * Instead, this returns F_child and assigns the child's return code to result.
- * The caller is expected to handle the appropriate exit procedures and memory deallocation.
- *
- * When the passed pipe parameter is not NULL, this function is effectively asynchronous and will not block.
- * The caller is then expected to handle all read/write operations to/from the pipe.
- * The caller is expected to appropriately call waitpid() or similar as needed.
- * The caller is expected to handle both parent and child process (status is F_parent for parent and F_child for child.).
- * When the passed paremeter is NULL, then this function is effectively synchronous and blocks until child exits.
+ * Instead, 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.
  *
  * @param program_name
  *   The name of the program.
@@ -473,9 +454,7 @@ extern "C" {
  *   (optional) A pointer to the set of signals.
  *   Set to 0 to disable.
  * @param pipe
- *   (optional) A pointer to the set of pipe desciptors (I/O) to be used by the child process.
- *   When a non-zero address, the child process will assign these as the standard I/O file descriptors for piping to/from the parent/child.
- *   For each pipe, setting a value of -1 means to use the default pipe.
+ *   (optional) A pointer to a string to pipe as standard input to the child process.
  *   Set to 0 to disable.
  * @param result
  *   The code returned after finishing execution of program.
@@ -483,44 +462,39 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_child on success but this is the child thread.
- *   F_parent on success but this is the parent thread and pipe is non-zero (function is not blocking).
  *   F_failure (with error bit) on execution failure.
  *   F_fork (with error bit) on fork failure.
+ *   F_pipe (with error bit) on pipe failure.
  *
  *   Errors (with error bit) from: f_file_exists().
  *   Errors (with error bit) from: f_signal_set_handle().
  *
+ * @see close()
  * @see dup2()
+ * @see execv()
  * @see execvp()
  * @see fork()
- * @see strnlen()
+ * @see pipe()
  * @see waitpid()
  *
  * @see f_file_exists()
  * @see f_signal_set_handle()
  */
 #ifndef _di_fll_execute_program_
-  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, f_execute_pipe_t * const pipe, 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, f_string_static_t * const pipe, int *result);
 #endif // _di_fll_execute_program_
 
 /**
  * Execute a program given by name found in the PATH environment (such as "bash").
  *
- * Uses the provided environment array to designate the environment for the called program.
- *
- * This does validate the path to the program because it completes the path to the program.
- * This is done because the PATH environment will get cleared or may be set differently.
- * Execution of program_name is done using the PATH environment prior to clearing and reassigning the environment variables.
+ * Uses the provided environment array to designate the environment for the program being executed.
+ * The environment is defined by the names and values pair.
  *
- * Unlike the execv() family of functions, this does not call exit() when the child process exits.
- * Instead, this returns F_child and assigns the child's return code to result.
- * The caller is expected to handle the appropriate exit procedures and memory deallocation.
+ * This does not validate the path to the program.
  *
- * When the passed pipe parameter is not NULL, this function is effectively asynchronous and will not block.
- * The caller is then expected to handle all read/write operations to/from the pipe.
- * The caller is expected to appropriately call waitpid() or similar as needed.
- * The caller is expected to handle both parent and child process (status is F_parent for parent and F_child for child.).
- * When the passed paremeter is NULL, then this function is effectively synchronous and blocks until child exits.
+ * This does not call exit() when the child process exits.
+ * Instead, 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.
  *
  * @param program_name
  *   The name of the program.
@@ -538,9 +512,7 @@ extern "C" {
  *   (optional) A pointer to the set of signals.
  *   Set to 0 to disable.
  * @param pipe
- *   (optional) A pointer to the set of pipe desciptors (I/O) to be used by the child process.
- *   When a non-zero address, the child process will assign these as the standard I/O file descriptors for piping to/from the parent/child.
- *   For each pipe, setting a value of -1 means to use the default pipe.
+ *   (optional) A pointer to a string to pipe as standard input to the child process.
  *   Set to 0 to disable.
  * @param result
  *   The code returned after finishing execution of program.
@@ -548,9 +520,9 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_child on success but this is the child thread.
- *   F_parent on success but this is the parent thread and pipe is non-zero (function is not blocking).
  *   F_failure (with error bit) on execution failure.
  *   F_fork (with error bit) on fork failure.
+ *   F_pipe (with error bit) on pipe failure.
  *
  *   Errors (with error bit) from: f_environment_get().
  *   Errors (with error bit) from: f_file_exists().
@@ -561,11 +533,13 @@ extern "C" {
  *   Errors (with error bit) from: fl_string_append().
  *   Errors (with error bit) from: fl_string_dynamic_terminate().
  *
+ * @see close()
  * @see clearenv()
  * @see dup2()
  * @see execvp()
  * @see fork()
  * @see memcpy()
+ * @see pipe()
  * @see strnlen()
  * @see waitpid()
  *
@@ -577,7 +551,7 @@ extern "C" {
  * @see fl_string_dynamic_terminate()
  */
 #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, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result);
+  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, const f_signal_how_t *signals, f_string_static_t * const pipe, int *result);
 #endif // _di_fll_execute_program_environment_
 
 #ifdef __cplusplus
index 97dab1371a1a8fc47a7111d44faa4e9f30b864fc..4f0cc5f46a223249bd6516190e08b853e9b93959 100644 (file)
@@ -111,42 +111,54 @@ 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_path_) || !defined(_di_fll_execute_program_)
-  f_return_status private_fll_execute_fork(const f_string_t program_path, const f_string_t fixed_arguments[], const bool program_is, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) {
+  f_return_status private_fll_execute_fork(const f_string_t program_path, const f_string_t fixed_arguments[], const bool program_is, const f_signal_how_t *signals, f_string_static_t * const pipe_data, int *result) {
+
+    int descriptors[2] = { -1, -1 };
+
+    if (pipe_data) {
+       if (pipe(descriptors) == -1) {
+         return F_status_set_error(F_pipe);
+       }
+    }
 
     const pid_t process_id = fork();
 
     if (process_id < 0) {
+
+      if (pipe_data) {
+        close(descriptors[0]);
+        close(descriptors[1]);
+      }
+
       return F_status_set_error(F_fork);
     }
 
     if (process_id) {
-      if (pipe) {
-        return F_parent;
-      }
+
+      // close the read pipe for the parent.
+      close(descriptors[0]);
     }
     else {
 
+      // close the write pipe for the child.
+      close(descriptors[1]);
+
       if (signals) {
         f_signal_set_handle(SIG_BLOCK, &signals->block);
         f_signal_set_handle(SIG_UNBLOCK, &signals->block_not);
       }
 
-      if (pipe) {
-        if (pipe->input != -1) {
-          dup2(pipe->input, f_type_descriptor_input);
-        }
-
-        if (pipe->output != -1) {
-          dup2(pipe->input, f_type_descriptor_output);
-        }
-
-        if (pipe->error != -1) {
-          dup2(pipe->error, f_type_descriptor_error);
-        }
+      if (pipe_data) {
+        dup2(descriptors[0], f_type_descriptor_input);
       }
 
       const int code = program_is ? execvp(program_path, fixed_arguments) : execv(program_path, fixed_arguments);
 
+      // close the write pipe for the child when done.
+      if (pipe_data) {
+        close(descriptors[0]);
+      }
+
       if (result) {
         *result = code;
       }
@@ -154,6 +166,16 @@ extern "C" {
       return F_child;
     }
 
+    // write all data, if child doesn't read this could block until child closes the pipe.
+    if (pipe_data) {
+      const f_file_t file = f_macro_file_t_initialize(0, descriptors[1], f_file_flag_write_only);
+
+      f_file_write(file, *pipe_data, 0);
+
+      // close the write pipe for the parent when finished writing.
+      close(descriptors[1]);
+    }
+
     // have the parent wait for the child process to finish.
     waitpid(process_id, result, WUNTRACED | WCONTINUED);
 
@@ -170,20 +192,38 @@ extern "C" {
 #endif // !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_program_)
 
 #if !defined(_di_fll_execute_path_environment_) || !defined(_di_fll_execute_program_environment_)
-  f_return_status private_fll_execute_fork_environment(const f_string_t program_path, const f_string_t fixed_arguments[], const bool program_is, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) {
+  f_return_status private_fll_execute_fork_environment(const f_string_t program_path, const f_string_t fixed_arguments[], const bool program_is, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, f_string_static_t * const pipe_data, int *result) {
+
+    int descriptors[2] = { -1, -1 };
+
+    if (pipe_data) {
+       if (pipe(descriptors) == -1) {
+         return F_status_set_error(F_pipe);
+       }
+    }
 
     const pid_t process_id = fork();
 
     if (process_id < 0) {
+
+      if (pipe_data) {
+        close(descriptors[0]);
+        close(descriptors[1]);
+      }
+
       return F_status_set_error(F_fork);
     }
 
     if (process_id) {
-      if (pipe) {
-        return F_parent;
-      }
+
+      // close the read pipe for the parent.
+      close(descriptors[0]);
     }
     else {
+
+      // close the write pipe for the child.
+      close(descriptors[1]);
+
       if (signals) {
         f_signal_set_handle(SIG_BLOCK, &signals->block);
         f_signal_set_handle(SIG_UNBLOCK, &signals->block_not);
@@ -195,22 +235,17 @@ extern "C" {
         f_environment_set_dynamic(names.array[i], values.array[i], F_true);
       } // for
 
-      if (pipe) {
-        if (pipe->input != -1) {
-          dup2(pipe->input, f_type_descriptor_input);
-        }
-
-        if (pipe->output != -1) {
-          dup2(pipe->input, f_type_descriptor_output);
-        }
-
-        if (pipe->error != -1) {
-          dup2(pipe->error, f_type_descriptor_error);
-        }
+      if (pipe_data) {
+        dup2(descriptors[0], f_type_descriptor_input);
       }
 
       const int code = program_is ? execvp(program_path, fixed_arguments) : execv(program_path, fixed_arguments);
 
+      // close the write pipe for the child when done.
+      if (pipe_data) {
+        close(descriptors[0]);
+      }
+
       if (result) {
         *result = code;
       }
@@ -218,6 +253,16 @@ extern "C" {
       return F_child;
     }
 
+    // write all data, if child doesn't read this could block until child closes the pipe.
+    if (pipe_data) {
+      const f_file_t file = f_macro_file_t_initialize(0, descriptors[1], f_file_flag_write_only);
+
+      f_file_write(file, *pipe_data, 0);
+
+      // close the write pipe for the parent when finished writing.
+      close(descriptors[1]);
+    }
+
     // have the parent wait for the child process to finish.
     waitpid(process_id, result, WUNTRACED | WCONTINUED);
 
index ea9dd2d66c31569a46aaa54cef9d375c338b9d27..e024643ed43bb735c710b17be1110d8fb932face 100644 (file)
@@ -117,10 +117,8 @@ extern "C" {
  * @param set_signal
  *   (optional) A pointer to the set of signals.
  *   Set to 0 to disable.
- * @param pipe
- *   (optional) A pointer to the set of pipe desciptors (I/O) to be used by the child process.
- *   When a non-zero address, the child process will assign these as the standard I/O file descriptors for piping to/from the parent/child.
- *   For each pipe, setting a value of -1 means to use the default pipe.
+ * @param pipe_data
+ *   (optional) A pointer to a string to pipe as standard input to the child process.
  *   Set to 0 to disable.
  * @param result
  *   The code returned after finishing execution of program_path.
@@ -128,17 +126,23 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_child on success but this is the child thread.
- *   F_parent on success but this is the parent thread and pipe is non-zero (function is not blocking).
  *   F_failure (with error bit) on execution failure.
  *   F_fork (with error bit) on fork failure.
+ *   F_pipe (with error bit) on pipe failure.
  *
+ * @see close()
+ * @see dup2()
  * @see execv()
  * @see execvp()
+ * @see fork()
+ * @see pipe()
+ * @see waitpid()
+ *
  * @see fll_execute_path()
  * @see fll_execute_program()
  */
 #if !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_program_)
-  extern f_return_status private_fll_execute_fork(const f_string_t program_path, const f_string_t fixed_arguments[], const bool program_is, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) f_gcc_attribute_visibility_internal;
+  extern f_return_status private_fll_execute_fork(const f_string_t program_path, const f_string_t fixed_arguments[], const bool program_is, const f_signal_how_t *signals, f_string_static_t * const pipe_data, int *result) f_gcc_attribute_visibility_internal;
 #endif // !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_program_)
 
 /**
@@ -162,10 +166,8 @@ extern "C" {
  * @param signals
  *   (optional) A pointer to the set of signals.
  *   Set to 0 to disable.
- * @param pipe
- *   (optional) A pointer to the set of pipe desciptors (I/O) to be used by the child process.
- *   When a non-zero address, the child process will assign these as the standard I/O file descriptors for piping to/from the parent/child.
- *   For each pipe, setting a value of -1 means to use the default pipe.
+ * @param pipe_data
+ *   (optional) A pointer to a string to pipe as standard input to the child process.
  *   Set to 0 to disable.
  * @param result
  *   The code returned after finishing execution of program_path.
@@ -173,17 +175,25 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_child on success but this is the child thread.
- *   F_parent on success but this is the parent thread and pipe is non-zero (function is not blocking).
  *   F_failure (with error bit) on execution failure.
  *   F_fork (with error bit) on fork failure.
+ *   F_pipe (with error bit) on pipe failure.
+ *
+ * @see close()
+ * @see clearenv()
+ * @see dup2()
+ * @see execvp()
+ * @see fork()
+ * @see memcpy()
+ * @see pipe()
+ * @see strnlen()
+ * @see waitpid()
  *
- * @see execv()
- * @see execvpe()
  * @see fll_execute_path_environment()
  * @see fll_execute_program_environment()
  */
 #if !defined(_di_fll_execute_path_environment_) || !defined(_di_fll_execute_program_environment_)
-  extern f_return_status private_fll_execute_fork_environment(const f_string_t program_path, const f_string_t fixed_arguments[], const bool program_is, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) f_gcc_attribute_visibility_internal;
+  extern f_return_status private_fll_execute_fork_environment(const f_string_t program_path, const f_string_t fixed_arguments[], const bool program_is, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, f_string_static_t * const pipe_data, int *result) f_gcc_attribute_visibility_internal;
 #endif // !defined(_di_fll_execute_path_environment_) || !defined(_di_fll_execute_program_environment_)
 
 /**
index 559018b5e4095de645b667bfb1216e8da58339f0..10ba05e2d955c1b9f468697de9e728615a28a934 100644 (file)
@@ -50,6 +50,7 @@
 
 // fll-2 includes
 #include <level_2/error.h>
+#include <level_2/execute.h>
 #include <level_2/fss.h>
 #include <level_2/fss_basic_list.h>
 #include <level_2/fss_extended.h>
index bd0ec6404408d0a2f56b584f6ce606cc3df98270..358f9fc5534f6012ee0d16417811ea51b21b2701 100644 (file)
@@ -16,6 +16,7 @@ extern "C" {
   #define controller_string_action        "action"
   #define controller_string_actions       "actions"
   #define controller_string_asynchronous  "asynchronous"
+  #define controller_string_bash          "bash"
   #define controller_string_create        "create"
   #define controller_string_command       "command"
   #define controller_string_consider      "consider"
@@ -66,6 +67,7 @@ extern "C" {
   #define controller_string_action_length        6
   #define controller_string_actions_length       7
   #define controller_string_asynchronous_length  12
+  #define controller_string_bash_length          4
   #define controller_string_create_length        6
   #define controller_string_command_length       7
   #define controller_string_consider_length      8
index 8b3504b11589f1a68a74c96da5a43ebbd3910e93..44c40fcb7c398f30a47f5edd6535c75a23e3e862 100644 (file)
@@ -401,45 +401,43 @@ extern "C" {
 #endif // _di_controller_rule_error_need_want_wish_print_
 
 #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 action, controller_data_t *data, controller_setting_t *setting) {
+  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_array_length_t i = 0;
     f_array_length_t j = 0;
     f_array_length_t k = 0;
 
-    controller_rule_item_t *rule_item = 0;
-    controller_rule_action_t *rule_action = 0;
+    controller_rule_item_t *item = 0;
+    controller_rule_action_t *action = 0;
 
     for (i = 0; i < setting->rules.array[index].items.used; ++i) {
 
       if (setting->rules.array[index].items.array[i].type == controller_rule_item_type_setting) continue;
 
-      rule_item = &setting->rules.array[index].items.array[i];
+      item = &setting->rules.array[index].items.array[i];
 
-      for (j = 0; j < rule_item->actions.used; ++j) {
+      for (j = 0; j < item->actions.used; ++j) {
 
-        if (rule_item->actions.array[j].type != action) continue;
+        if (item->actions.array[j].type != type) continue;
 
-        rule_action = &rule_item->actions.array[j];
+        action = &item->actions.array[j];
+        status = F_none;
 
-        if (rule_item->type == controller_rule_item_type_command) {
-          if (rule_action->method == controller_rule_action_method_extended) {
+        if (item->type == controller_rule_item_type_command) {
+          if (action->method == controller_rule_action_method_extended) {
             // @todo
           }
           else {
             // @todo extended list execution.
           }
         }
-        else if (rule_item->type == controller_rule_item_type_script) {
-          if (rule_action->method == controller_rule_action_method_extended) {
-          // @todo
-          }
-          else {
-            // @todo extended list execution.
-          }
+        else if (item->type == controller_rule_item_type_script) {
+          status = controller_rule_execute_script(*action, 0, data);
+          if (F_status_is_error(status)) break;
         }
-        else if (rule_item->type == controller_rule_item_type_service) {
-          if (rule_action->method == controller_rule_action_method_extended) {
+        else if (item->type == controller_rule_item_type_service) {
+          if (action->method == controller_rule_action_method_extended) {
           // @todo
           }
           else {
@@ -450,39 +448,46 @@ extern "C" {
           // unknown, just ignore for now. (@todo print a warning when in debug mode.)
           continue;
         }
+
+        if (status == F_child || status == F_signal) break;
       } // for
+
+      if (status == F_child || status == F_signal) break;
     } // for
 
-    return F_none;
+    return status;
   }
 #endif // _di_controller_rule_execute_
 
 #ifndef _di_controller_rule_execute_script_
-  f_return_status controller_rule_execute_script(const controller_rule_action_t action, controller_data_t *data) {
+  f_return_status controller_rule_execute_script(const controller_rule_action_t action, const uint8_t options, controller_data_t *data) {
 
     // 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);
 
-    f_execute_pipe_t pipe = f_execute_pipe_t_initialize;
+    int result = 0;
 
-    f_status_t status = F_none;
-    //f_status_t status = fll_execute_program_environment(program.string, arguments, environment.names, environment.values, &signals, &pipe, &data->child);
+    const f_string_dynamics_t arguments = f_string_dynamics_t_initialize;
+
+    // @todo script program (such as: "bash") should be configurable somehow (a new entry setting? a new rule setting? both?).
+    // @todo have the environment variables built before executing the script and then instead call fll_execute_program_environment() for all execute functions (with environment.names, environment.values).
+    f_status_t status = fll_execute_program(controller_string_bash, arguments, &signals, action.parameters.used ? &action.parameters.array[0] : 0, &result);
 
     if (status == F_child) {
-      // @todo wait for parent pipe.
-      // @todo how do I get status code? there will likely need to be more changes to fll_execute_program_environment()...
+      data->child = result;
+
       return F_child;
     }
 
-    // parent process should print to the pipe.
-
     // @todo handle errors, print messages, etc..
-    if (data->child != 0) {
+    if (result != 0) {
       status = F_status_set_error(F_failure);
     }
     else if (F_status_is_error(status)) {
+      fll_error_print(data->error, F_status_set_fine(status), "fll_execute_program_environment", F_true);
+      return status;
     }
 
     data->child = 0;
@@ -1103,6 +1108,7 @@ extern "C" {
 
         if (F_status_is_error(status)) {
           fll_error_print(data->error, F_status_set_fine(status), "controller_rule_execute", F_true);
+          controller_rule_error_print(data->error, *cache, F_true);
         }
 
         if (status == F_child) {
index c86bf3702bb8f338c04c0147cfbd5607660f2825..1d2c705d1d1800ec301bc5c5322f32e35b525a26 100644 (file)
@@ -175,7 +175,7 @@ extern "C" {
  *   A structure for containing and caching relevant data.
  * @param index
  *   The position in the setting.rules array representing the rule to simulate.
- * @param action
+ * @param type
  *   The action to perform based on the action type codes.
  *
  *   Only subset of the action type codes are supported:
@@ -199,10 +199,40 @@ extern "C" {
  *   On failure, the individual status for the rule is set to an appropriate error status.
  */
 #ifndef _di_controller_rule_execute_
-  extern f_return_status controller_rule_execute(const controller_cache_t cache, const f_array_length_t index, const uint8_t action, controller_data_t *data, controller_setting_t *setting) f_gcc_attribute_visibility_internal;
+  extern 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_gcc_attribute_visibility_internal;
 #endif // _di_controller_rule_execute_
 
 /**
+ * Perform an execution of the given rule for the script execution type.
+ *
+ * @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 options
+ *   The execute options.
+ * @param data
+ *   The program data.
+ *
+ * @return
+ *   F_none on success.
+ *   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_script_
+  extern f_return_status controller_rule_execute_script(const controller_rule_action_t action, const uint8_t options, controller_data_t *data) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_rule_execute_script_
+
+/**
  * Search the already loaded rules to see if one is found.
  *
  * @param data
index 32305e204de720491de62f91a5ebc4db5e43f8aa..10114602adac698b2c1daef8d472435f826b99cd 100644 (file)
@@ -25,6 +25,7 @@ fl_iki
 fl_string
 fl_type
 fll_error
+fll_execute
 fll_fss
 fll_path
 fll_program
index 95f70d8f12a355d20941fb3d2d6ea1c2307045d0..82788d3876f719b6b3615ffa15022768ee3c8fb3 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_error -lfll_fss -lfll_path -lfll_program -lfll_status -lfl_color -lfl_console -lfl_conversion -lfl_fss -lfl_iki -lfl_status -lfl_string -lfl_type -lf_console -lf_conversion -lf_directory -lf_file -lf_fss -lf_iki -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-individual -lfll_error -lfll_execute -lfll_fss -lfll_path -lfll_program -lfll_status -lfl_color -lfl_console -lfl_conversion -lfl_environment -lfl_fss -lfl_iki -lfl_status -lfl_string -lfl_type -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_iki -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library controller.c private-control.c private-controller.c private-entry.c private-rule.c