]> Kevux Git Server - fll/commitdiff
Update: implement fll_execute_program and fix fll_execute_path
authorKevin Day <kevin@kevux.org>
Fri, 9 Mar 2012 01:27:55 +0000 (19:27 -0600)
committerKevin Day <kevin@kevux.org>
Fri, 9 Mar 2012 01:27:55 +0000 (19:27 -0600)
This adds fll_execute_program and changes how fll_execute_path works to function properly.
Prior to this change, fll_execute_path did not set the first argument which would cause the programs argv[0] to not be equivalent to the program name.

This also corrects a few mistakes where level_1 syntax and comments were not changed to level_2.

level_2/fll_execute/c/execute.c
level_2/fll_execute/c/execute.h

index 76a297e5da177c616b49a0532e59792c213a9f05..8d941a2860570d6ef4ffcd550dd018bc38e406e8 100644 (file)
@@ -1,12 +1,11 @@
-/* FLL - Level 1
+/* FLL - Level 2
  * Project:       Execute
  * Version:       0.3.x
  * Licenses:      lgplv2.1
  * Programmers:   Kevin Day
  * Documentation:
  *
- * Provides program execution operations similart to system()
- * TODO: I should implement a function that will find the program based on PATH so that static paths do not have to be used
+ * Provides program execution operations similart to system().
  */
 #include <level_2/execute.h>
 
@@ -16,30 +15,59 @@ extern "C"{
 
 #ifndef _di_fll_execute_path_
   f_return_status fll_execute_path(const f_string program_path, const f_dynamic_strings arguments, f_s_int *results){
-    #ifndef _di_level_1_parameter_checking_
+    #ifndef _di_level_2_parameter_checking_
       if (results == f_null) return f_invalid_parameter;
 
-      if (arguments.used <= 0)              return f_invalid_parameter;
-      if (arguments.used  > arguments.size) return f_invalid_parameter;
-    #endif // _di_level_1_parameter_checking_
+      if (arguments.used < 0)              return f_invalid_parameter;
+      if (arguments.used > arguments.size) return f_invalid_parameter;
+    #endif // _di_level_2_parameter_checking_
 
     // create a string array that is compatible with execv() calls
     f_status   status            = f_status_initialize;
     f_autochar **arguments_array = 0;
 
-    status = f_new_array((void **) & arguments_array, sizeof(f_autochar **), arguments.used + 1);
+    f_string        last_slash   = f_string_initialize;
+    f_string        program_name = f_string_initialize;
+    f_string_length name_size    = program_path;
 
-    if (f_macro_test_for_allocation_errors(status)) return status;
+    last_slash = strrchr(program_path, '/');
+
+    if (last_slash != f_null){
+      name_size = strnlen(last_slash, PATH_MAX);
+
+      if (name_size > 1){
+        f_new_string(status, program_name, name_size + 1);
+
+        if (f_macro_test_for_allocation_errors(status)) return status;
+
+        memcpy(program_name, last_slash + 1, name_size);
+        memset(program_name, name_size, 0);
+      } else {
+        name_size = 0;
+      }
+    }
+
+    status = f_new_array((void **) & arguments_array, sizeof(f_autochar **), arguments.used + 2);
+
+    if (f_macro_test_for_allocation_errors(status)){
+      f_status tmp_status = f_status_initialize;
+
+      f_delete_string(tmp_status, program_name, name_size);
+      return status;
+    }
 
     {
       f_string_length counter = f_string_length_initialize;
 
+      arguments_array[0] = program_name;
+      counter++;
+
       for (; counter < arguments.used; counter++){
         arguments_array[counter] = arguments.array[counter].string;
       }
 
       // insert the required array terminated
-      arguments_array[arguments.used] = 0;
+      arguments_array[arguments.used + 1] = 0;
     }
 
     // TODO: validate that the file at program_path actually exists before attempting to fork and execute
@@ -61,7 +89,8 @@ extern "C"{
     // have the parent wait for the child process to finish
     waitpid(process_id, results, 0);
 
-    f_delete((void **) & arguments_array, sizeof(f_autochar), arguments.used + 1);
+    if (name_size > 0) f_delete_string(status, program_name, name_size);
+    f_delete((void **) & arguments_array, sizeof(f_autochar), arguments.used + 2);
 
     if (*results != 0) return f_failure;
 
@@ -69,6 +98,64 @@ extern "C"{
   }
 #endif // _di_fll_execute_path_
 
+#ifndef _di_fll_execute_program_
+  f_return_status fll_execute_program(const f_string program_name, const f_dynamic_strings arguments, f_s_int *results){
+    #ifndef _di_level_2_parameter_checking_
+      if (results == f_null) return f_invalid_parameter;
+
+      if (arguments.used < 0)              return f_invalid_parameter;
+      if (arguments.used > arguments.size) return f_invalid_parameter;
+    #endif // _di_level_2_parameter_checking_
+
+    // create a string array that is compatible with execv() calls
+    f_status   status            = f_status_initialize;
+    f_autochar **arguments_array = 0;
+
+    status = f_new_array((void **) & arguments_array, sizeof(f_autochar **), arguments.used + 2);
+
+    if (f_macro_test_for_allocation_errors(status)) return status;
+
+    {
+      f_string_length counter = f_string_length_initialize;
+
+      arguments_array[0] = program_name;
+      counter++;
+
+      for (; counter < arguments.used; counter++){
+        arguments_array[counter] = arguments.array[counter].string;
+      }
+
+      // insert the required array terminated
+      arguments_array[arguments.used + 1] = 0;
+    }
+
+    // TODO: validate that the file at program_path actually exists before attempting to fork and execute
+    f_s_int process_id = 0;
+
+    process_id = vfork();
+
+    if (process_id < 0){
+      return f_fork_failed;
+    }
+
+    if (process_id == 0){ // child
+      execvp(program_name, arguments_array);
+
+      // according to manpages, calling _exit() is safer and should be called here instead of exit()
+      _exit(-1);
+    }
+
+    // have the parent wait for the child process to finish
+    waitpid(process_id, results, 0);
+
+    f_delete((void **) & arguments_array, sizeof(f_autochar), arguments.used + 2);
+
+    if (*results != 0) return f_failure;
+
+    return f_none;
+  }
+#endif // _di_fll_execute_program_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 7011956213ecad9a10df585677f066291733baf0..988f81e3de80f9bba57cefb9b49f058b64552b22 100644 (file)
@@ -14,6 +14,9 @@
 #include <unistd.h>
 #include <sys/wait.h>
 #include <signal.h>
+#include <linux/limits.h> // defines PATH_MAX
+#include <string.h>
+#include <memory.h>
 
 // fll-0 includes
 #include <level_0/strings.h>
@@ -34,7 +37,7 @@ extern "C"{
 
 #ifndef _di_fll_execute_program_
   // This will find the program based on PATH environment so that static paths do not have to be used as with f_execute_path
-  extern f_return_status fll_execute_program(const f_string program_name, const f_string arguments[], f_s_int *results);
+  extern f_return_status fll_execute_program(const f_string program_name, const f_dynamic_strings arguments, f_s_int *results);
 #endif // _di_fll_execute_program_
 
 #ifdef __cplusplus