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) {
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;
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_
* @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.
*
* 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.
* @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.
#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 };
}
}
- 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;
#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 };
}
}
- 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]);
*
* 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
* @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_)
/**
*
* 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
* @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_)
/**