]> Kevux Git Server - fll/commitdiff
Update: redesign fl_execute_parameter_option_path in fll_execute.
authorKevin Day <thekevinday@gmail.com>
Sat, 17 Apr 2021 05:34:34 +0000 (00:34 -0500)
committerKevin Day <thekevinday@gmail.com>
Sat, 17 Apr 2021 05:34:34 +0000 (00:34 -0500)
The previous design of fl_execute_parameter_option_path seemed pointless because it could be detected if a slash is in the progam name.
Recent changes have utilized the slash in the path to do just that.

While working with the controller program the SSHD program revealed that some programs are fickle about what is in their argument[0].
SSHD wants the full path and as such it needs to be provided.
This makes sense as the normal behavior of most programs when started with a full path general expect a full path in argument[0].

The fl_execute_parameter_option_path is redesigned to instead provide a full path for program and for argument[0].

Examples:
  - "bash my_script.sh" (without fl_execute_parameter_option_path), results in: program="bash", argument[0]="bash", argument[1]="my_script.sh".
  - "/bin/bash my_script.sh" (without fl_execute_parameter_option_path), results in: program="/bin/bash", argument[0]="bash", argument[1]="my_script.sh".
  - "bash my_script.sh" (with fl_execute_parameter_option_path), results in: program="/bin/bash", argument[0]="/bin/bash", argument[1]="my_script.sh".
  - "/bin/bash my_script.sh" (with fl_execute_parameter_option_path), results in: program="/bin/bash", argument[0]="/bin/bash", argument[1]="my_script.sh".

level_1/fl_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

index 16919084b2b39c10ee95c3d0ecae78cb2fe87ca0..deb4266deffb58a13c028b024f60b87da401d8ef 100644 (file)
@@ -21,7 +21,7 @@ extern "C" {
  *
  * bitwise options:
  *   fl_execute_parameter_option_exit:       used to desginate to exit after calling child otherwise child process will return.
- *   fl_execute_parameter_option_path:       used to designate that this is a path to a program (such as '/bin/bash').
+ *   fl_execute_parameter_option_path:       used to designate that the full path to the program is to be passed in argument[0] instead of the program name (such as '/bin/bash' instead of 'bash').
  *   fl_execute_parameter_option_threadsafe: used to designate that threadsafe functions are to be used (such as: f_thread_signal_mask instead of f_signal_mask).
  *   fl_execute_parameter_option_return:     used to designate that the parent process will immediately return instead of waiting for the child process to complete.
  *
index 8944a91ba1ab0b8b8609f804590f8a6f51073d85..546bb196c2f91d79bae0a33c1f8d1b9d2c89a562 100644 (file)
@@ -140,15 +140,119 @@ extern "C" {
     f_string_t fixed_arguments[arguments.used + 2];
 
     const f_string_t last_slash = strrchr(program ? program : arguments.array[0].string, f_path_separator_s[0]);
-    const f_array_length_t name_size = last_slash ? strnlen(last_slash + 1, f_path_length_max) : strnlen(program ? program : arguments.array[0].string, f_path_length_max);
+    const f_array_length_t size_name = last_slash ? strnlen(last_slash + 1, f_path_length_max) : strnlen(program ? program : arguments.array[0].string, f_path_length_max);
+
+    char program_name[size_name + 1];
+
+    private_fll_execute_path_arguments_fixate(program ? program : arguments.array[0].string, arguments, last_slash, !program, size_name, program_name, fixed_arguments);
+
+    int code = 0;
+
+    // full path is explicitly requested.
+    if (option & fl_execute_parameter_option_path) {
+      f_string_dynamic_t path = f_string_dynamic_t_initialize;
+      f_string_dynamics_t paths = f_string_dynamics_t_initialize;
+      f_string_dynamic_t *found = 0;
+
+      f_status_t status = F_none;
+
+      if (last_slash) {
+        status = f_file_exists(program ? program : arguments.array[0].string);
+
+        if (status != F_true) {
+          f_macro_string_dynamics_t_delete_simple(paths);
+
+          return F_status_set_error(F_file_found_not);
+        }
+
+        path.string = program ? program : arguments.array[0].string;
+        path.used = strnlen(program ? program : arguments.array[0].string, f_path_length_max);
+        found = &path;
+      }
+      else {
+        status = f_environment_get(f_path_environment_s, &path);
+
+        if (F_status_is_error(status)) {
+
+          // Do not consider PATH is not available (or valid?) to be an error.
+          if (F_status_set_fine(status) == F_valid_not || F_status_set_fine(status) == F_failure) {
+            status = F_none;
+          }
+        }
+        else {
+          status = fl_environment_path_explode_dynamic(path, &paths);
+        }
+
+        f_macro_string_dynamic_t_delete_simple(path);
+
+        if (F_status_is_error(status)) {
+          f_macro_string_dynamics_t_delete_simple(paths);
+
+          return status;
+        }
+
+        for (f_array_length_t i = 0; i < paths.used; ++i) {
+
+          status = f_string_append(program_name, size_name, &paths.array[i]);
+
+          if (F_status_is_error_not(status)) {
+            status = f_string_dynamic_terminate_after(&paths.array[i]);
+          }
+
+          if (F_status_is_error_not(status)) {
+            status = f_file_exists(paths.array[i].string);
+
+            if (status == F_true) {
+              found = &paths.array[i];
+
+              break;
+            }
+
+            if (F_status_is_error(status)) {
+              status = F_status_set_fine(status);
+
+              // don't consider bad/non-accessible paths an error, just ignore them.
+              if (status == F_name) {
+                continue;
+              }
+              else if (status == F_directory) {
+                continue;
+              }
+              else if (status == F_access_denied) {
+                continue;
+              }
+            }
+          }
+
+          if (F_status_is_error(status)) {
+            f_macro_string_dynamics_t_delete_simple(paths);
+
+            return status;
+          }
+        } // for
+
+        if (!found) {
+          f_macro_string_dynamics_t_delete_simple(paths);
+
+          return F_status_set_error(F_file_found_not);
+        }
+      }
 
-    char program_name[name_size + 1];
+      char program_path[found->used + 1];
+      program_path[found->used] = 0;
 
-    program_name[name_size] = 0;
+      memcpy(&program_path, found->string, found->used);
 
-    private_fll_execute_path_arguments_fixate(program ? program : arguments.array[0].string, arguments, last_slash, !program, name_size, program_name, fixed_arguments);
+      status = f_macro_string_dynamics_t_delete_simple(paths);
+      if (F_status_is_error(status)) return status;
+
+      fixed_arguments[0] = program_path;
 
-    const int code = option & fl_execute_parameter_option_path ? execv(program ? program : arguments.array[0].string, fixed_arguments) : execvp(program ? program : arguments.array[0].string, fixed_arguments);
+      code = execv(program_path, fixed_arguments);
+    }
+    else {
+      code = last_slash ? execv(program ? program : arguments.array[0].string, fixed_arguments) : execvp(program ? program : arguments.array[0].string, fixed_arguments);
+    }
 
     // generally this does not return, but in some cases (such as with scripts) this does return so handle the results.
     if (result) {
@@ -184,8 +288,8 @@ extern "C" {
 
     private_fll_execute_path_arguments_fixate(program ? program : arguments.array[0].string, arguments, last_slash, !program, size_name, program_name, fixed_arguments);
 
-    // when the environment is to be cleared, a full path must be used.
-    if (parameter && !(parameter->option & fl_execute_parameter_option_path) && parameter->environment) {
+    // determine full path when the environment is to be cleared or full path is explicitly requested.
+    if (parameter && parameter->environment || parameter && (parameter->option & fl_execute_parameter_option_path)) {
       f_string_dynamic_t path = f_string_dynamic_t_initialize;
       f_string_dynamics_t paths = f_string_dynamics_t_initialize;
       f_string_dynamic_t *found = 0;
@@ -282,18 +386,22 @@ extern "C" {
       status = f_macro_string_dynamics_t_delete_simple(paths);
       if (F_status_is_error(status)) return status;
 
+      if (parameter && (parameter->option & fl_execute_parameter_option_path)) {
+        fixed_arguments[0] = program_path;
+      }
+
       if (parameter && parameter->data) {
-        return private_fll_execute_fork_data(program_path, fixed_arguments, parameter, as, result);
+        return private_fll_execute_fork_data(F_true, program_path, fixed_arguments, parameter, as, result);
       }
 
-      return private_fll_execute_fork(program_path, fixed_arguments, parameter, as, result);
+      return private_fll_execute_fork(F_true, program_path, fixed_arguments, parameter, as, result);
     }
 
     if (parameter && parameter->data) {
-      return private_fll_execute_fork_data(program ? program : arguments.array[0].string, fixed_arguments, parameter, as, result);
+      return private_fll_execute_fork_data(last_slash, program ? program : arguments.array[0].string, fixed_arguments, parameter, as, result);
     }
 
-    return private_fll_execute_fork(program ? program : arguments.array[0].string, fixed_arguments, parameter, as, result);
+    return private_fll_execute_fork(last_slash, program ? program : arguments.array[0].string, fixed_arguments, parameter, as, result);
   }
 #endif // _di_fll_execute_program_
 
index 9c882595e6e3bfe43cd680fdd925c632ca778674..3e18b53d0081e1e708da5840bbe40711b8fdb236 100644 (file)
@@ -362,7 +362,7 @@ extern "C" {
  * @param option
  *   A bitwise set of options, such as: fl_execute_parameter_option_exit and fl_execute_parameter_option_path.
  *   If fl_execute_parameter_option_exit: this will call exit() at the end of execution (be it success or failure).
- *   If fl_execute_parameter_option_path: this is a program path (such as "/bin/bash"), otherwise this is a program (such as "bash").
+ *   If fl_execute_parameter_option_path: use the whole program path (such as "/bin/bash" instead "bash" when populated argument[0].
  * @param result
  *   The code returned after finishing execution of program.
  *
@@ -391,7 +391,7 @@ extern "C" {
  *   The environment is defined by the names and values pair.
  *   This requires paramete.values to also be specified with the same used length as parameter.names.
  *
- * When parameter.option has the fl_execute_parameter_option_path bit set, then this does validate the path to the program.
+ * When the path has a slash "/" or the environment is to be cleared, then this does validate the path to the program.
  * Otherwise, this does not validate the path to the program.
  *
  * When the parameter.option has the fl_execute_parameter_option_exit bit set, then this calls exit() when the child process returns.
@@ -411,7 +411,7 @@ extern "C" {
  * @param parameter
  *   (optional) This and most of its fields are optional and are disabled when set to 0.
  *   option:
- *     A bitwise set of options, such as: fl_execute_parameter_option_exit, and fl_execute_parameter_option_path.
+ *     A bitwise set of options, such as: fl_execute_parameter_option_exit and fl_execute_parameter_option_path.
  *   names:
  *     An array of strings representing the environment variable names.
  *     At most names.used variables are created.
index 19c771b289934f239a26baa45db9d72b634062ae..8b65b2e775ab5cb78b9512e6e1e43e9811f117b4 100644 (file)
@@ -253,7 +253,7 @@ extern "C" {
 #endif // !defined(_di_fll_execute_program_)
 
 #if !defined(_di_fll_execute_program_)
-  f_status_t 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, void *result) {
+  f_status_t private_fll_execute_fork(const bool direct, const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, void *result) {
 
     int descriptors[2] = { -1, -1 };
 
@@ -405,7 +405,7 @@ extern "C" {
       }
     }
 
-    const int code = parameter && (parameter->option & fl_execute_parameter_option_path) ? execv(program, fixed_arguments) : execvp(program, fixed_arguments);
+    const int code = direct ? execv(program, fixed_arguments) : execvp(program, fixed_arguments);
 
     if (result) {
       int *r = (int *) result;
@@ -421,7 +421,7 @@ extern "C" {
 #endif // !defined(_di_fll_execute_program_)
 
 #if !defined(_di_fll_execute_program_)
-  f_status_t 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, void *result) {
+  f_status_t private_fll_execute_fork_data(const bool direct, const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, void *result) {
 
     int descriptors[2] = { -1, -1 };
 
@@ -575,7 +575,7 @@ extern "C" {
       }
     }
 
-    const int code = parameter && parameter->option & fl_execute_parameter_option_path ? execv(program, fixed_arguments) : execvp(program, fixed_arguments);
+    const int code = direct ? execv(program, fixed_arguments) : execvp(program, fixed_arguments);
 
     // close the write pipe for the child when done.
     close(descriptors[0]);
index 9d73114a0df398d2c9cf73ec418496830bf8a528..09230ed9d319d4d6a03fa7deab009034c983004d 100644 (file)
@@ -175,6 +175,9 @@ extern "C" {
  *
  * This implementation ignores parameter.data.
  *
+ * @param direct
+ *   If TRUE, then use execv() to directly execute.
+ *   If FALSE, then use execvp() to search for in PATH then execute.
  * @param program
  *   The name or path of the program.
  * @param arguments
@@ -240,7 +243,7 @@ extern "C" {
  * @see fll_execute_program()
  */
 #if !defined(_di_fll_execute_program_)
-  extern f_status_t 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, void *result) f_gcc_attribute_visibility_internal;
+  extern f_status_t private_fll_execute_fork(const bool direct, const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, void *result) f_gcc_attribute_visibility_internal;
 #endif // !defined(_di_fll_execute_program_)
 
 /**
@@ -248,6 +251,9 @@ extern "C" {
  *
  * This implementation requires parameter.data.
  *
+ * @param direct
+ *   If TRUE, then use execv() to directly execute.
+ *   If FALSE, then use execvp() to search for in PATH then execute.
  * @param program
  *   The name or path of the program.
  * @param arguments
@@ -312,7 +318,7 @@ extern "C" {
  * @see fll_execute_program()
  */
 #if !defined(_di_fll_execute_program_)
-  extern f_status_t 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, void *result) f_gcc_attribute_visibility_internal;
+  extern f_status_t private_fll_execute_fork_data(const bool direct, const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, void *result) f_gcc_attribute_visibility_internal;
 #endif // !defined(_di_fll_execute_program_)
 
 /**