From dd2acbfa3abb0766e2c3a669f092faaced1ab56f Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Thu, 14 May 2020 21:42:01 -0500 Subject: [PATCH] Update: add environment functions, add static strings, and other changes Add environment project and associated functions for managing environment variables. Add execute functions for setting environment variables. - More work is needed to search the PATH to perform fll_execute_program_environment when PATH is not to be defined. Provide stub define build settings files for each project. Miscellaneous minor fixes/tweaks. --- build/level_0/settings | 4 +- build/monolithic/settings | 4 +- level_0/f_color/data/build/defines | 2 + level_0/f_console/c/console.h | 9 + level_0/f_console/data/build/defines | 2 + level_0/f_conversion/data/build/defines | 2 + level_0/f_directory/c/directory.h | 4 +- level_0/f_directory/data/build/defines | 2 + level_0/f_environment/c/environment.c | 127 ++++++++++++++ level_0/f_environment/c/environment.h | 204 ++++++++++++++++++++++ level_0/f_environment/c/private-environment.c | 77 ++++++++ level_0/f_environment/c/private-environment.h | 95 ++++++++++ level_0/f_environment/data/build/defines | 2 + level_0/f_environment/data/build/dependencies | 4 + level_0/f_environment/data/build/settings | 30 ++++ level_0/f_file/data/build/defines | 2 + level_0/f_fss/data/build/defines | 2 + level_0/f_memory/data/build/defines | 2 + level_0/f_path/data/build/defines | 2 + level_0/f_pipe/data/build/defines | 2 + level_0/f_print/data/build/defines | 2 + level_0/f_serialized/data/build/defines | 2 + level_0/f_socket/data/build/defines | 2 + level_0/f_status/c/status.h | 3 - level_0/f_status/data/build/defines | 2 + level_0/f_string/c/string.h | 37 ++-- level_0/f_type/data/build/defines | 2 + level_1/fl_color/data/build/defines | 2 + level_1/fl_console/data/build/defines | 2 + level_1/fl_file/data/build/defines | 2 + level_1/fl_fss/data/build/defines | 2 + level_1/fl_print/data/build/defines | 2 + level_1/fl_serialized/data/build/defines | 2 + level_1/fl_socket/data/build/defines | 2 + level_1/fl_status/c/status.c | 6 - level_1/fl_status/c/status.h | 6 - level_1/fl_status/data/build/defines | 2 + level_1/fl_string/data/build/defines | 2 + level_1/fl_utf/data/build/defines | 2 + level_1/fl_utf_file/data/build/defines | 2 + level_2/fll_directory/data/build/defines | 2 + level_2/fll_execute/c/execute.c | 191 +++++++++++++++++++- level_2/fll_execute/c/execute.h | 74 +++++++- level_2/fll_execute/data/build/defines | 2 + level_2/fll_execute/data/build/dependencies | 1 + level_2/fll_execute/data/build/settings | 2 +- level_2/fll_file/data/build/defines | 2 + level_2/fll_fss/c/fss_basic.c | 2 +- level_2/fll_fss/c/fss_basic.h | 2 +- level_2/fll_fss/c/fss_basic_list.c | 2 +- level_2/fll_fss/c/fss_basic_list.h | 2 +- level_2/fll_fss/c/fss_extended.c | 2 +- level_2/fll_fss/c/fss_extended.h | 2 +- level_2/fll_fss/c/fss_extended_list.c | 2 +- level_2/fll_fss/c/fss_extended_list.h | 2 +- level_2/fll_fss/data/build/defines | 2 + level_2/fll_program/data/build/defines | 2 + level_2/fll_status/c/status.c | 10 -- level_2/fll_status/data/build/defines | 2 + level_3/byte_dump/data/build/defines | 2 + level_3/fss_basic_list_read/data/build/defines | 2 + level_3/fss_basic_list_write/data/build/defines | 2 + level_3/fss_basic_read/data/build/defines | 2 + level_3/fss_basic_write/data/build/defines | 2 + level_3/fss_extended_list_read/data/build/defines | 2 + level_3/fss_extended_read/data/build/defines | 2 + level_3/fss_extended_write/data/build/defines | 2 + level_3/fss_status_code/data/build/defines | 2 + level_3/init/data/build/defines | 2 + level_3/status_code/data/build/defines | 2 + 70 files changed, 935 insertions(+), 55 deletions(-) create mode 100644 level_0/f_color/data/build/defines create mode 100644 level_0/f_console/data/build/defines create mode 100644 level_0/f_conversion/data/build/defines create mode 100644 level_0/f_directory/data/build/defines create mode 100644 level_0/f_environment/c/environment.c create mode 100644 level_0/f_environment/c/environment.h create mode 100644 level_0/f_environment/c/private-environment.c create mode 100644 level_0/f_environment/c/private-environment.h create mode 100644 level_0/f_environment/data/build/defines create mode 100644 level_0/f_environment/data/build/dependencies create mode 100644 level_0/f_environment/data/build/settings create mode 100644 level_0/f_file/data/build/defines create mode 100644 level_0/f_fss/data/build/defines create mode 100644 level_0/f_memory/data/build/defines create mode 100644 level_0/f_path/data/build/defines create mode 100644 level_0/f_pipe/data/build/defines create mode 100644 level_0/f_print/data/build/defines create mode 100644 level_0/f_serialized/data/build/defines create mode 100644 level_0/f_socket/data/build/defines create mode 100644 level_0/f_status/data/build/defines create mode 100644 level_0/f_type/data/build/defines create mode 100644 level_1/fl_color/data/build/defines create mode 100644 level_1/fl_console/data/build/defines create mode 100644 level_1/fl_file/data/build/defines create mode 100644 level_1/fl_fss/data/build/defines create mode 100644 level_1/fl_print/data/build/defines create mode 100644 level_1/fl_serialized/data/build/defines create mode 100644 level_1/fl_socket/data/build/defines create mode 100644 level_1/fl_status/data/build/defines create mode 100644 level_1/fl_string/data/build/defines create mode 100644 level_1/fl_utf/data/build/defines create mode 100644 level_1/fl_utf_file/data/build/defines create mode 100644 level_2/fll_directory/data/build/defines create mode 100644 level_2/fll_execute/data/build/defines create mode 100644 level_2/fll_file/data/build/defines create mode 100644 level_2/fll_fss/data/build/defines create mode 100644 level_2/fll_program/data/build/defines create mode 100644 level_2/fll_status/data/build/defines create mode 100644 level_3/byte_dump/data/build/defines create mode 100644 level_3/fss_basic_list_read/data/build/defines create mode 100644 level_3/fss_basic_list_write/data/build/defines create mode 100644 level_3/fss_basic_read/data/build/defines create mode 100644 level_3/fss_basic_write/data/build/defines create mode 100644 level_3/fss_extended_list_read/data/build/defines create mode 100644 level_3/fss_extended_read/data/build/defines create mode 100644 level_3/fss_extended_write/data/build/defines create mode 100644 level_3/fss_status_code/data/build/defines create mode 100644 level_3/init/data/build/defines create mode 100644 level_3/status_code/data/build/defines diff --git a/build/level_0/settings b/build/level_0/settings index acb13ed..1cd482d 100644 --- a/build/level_0/settings +++ b/build/level_0/settings @@ -12,9 +12,9 @@ build_linker ar build_libraries -lc build_libraries_fll build_libraries_fll-level -build_sources_library console.c conversion.c directory.c private-directory.c file.c memory.c pipe.c print.c utf.c private-utf.c +build_sources_library console.c conversion.c directory.c private-directory.c environment.c private-environment.c file.c memory.c pipe.c print.c utf.c private-utf.c build_sources_program -build_sources_headers color.h console.h conversion.h directory.c file.h fss.h memory.h path_fll.h path_filesystem.h path.h pipe.h print.h serialized.h socket.h status.h string.h type.h type_array.h utf.h +build_sources_headers color.h console.h conversion.h directory.h environment.h file.h fss.h memory.h path_fll.h path_filesystem.h path.h pipe.h print.h serialized.h socket.h status.h string.h type.h type_array.h utf.h build_shared yes build_static yes diff --git a/build/monolithic/settings b/build/monolithic/settings index 1eace14..614c23b 100644 --- a/build/monolithic/settings +++ b/build/monolithic/settings @@ -11,9 +11,9 @@ build_compiler gcc build_linker ar build_libraries -lc build_libraries_fll -build_sources_library level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/file.c level_0/memory.c level_0/pipe.c level_0/print.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/file.c level_1/fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/print.c level_1/serialized.c level_1/private-serialized.c level_1/socket.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_2/directory.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/program.c level_2/status.c +build_sources_library level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/memory.c level_0/pipe.c level_0/print.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/file.c level_1/fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/print.c level_1/serialized.c level_1/private-serialized.c level_1/socket.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_2/directory.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/program.c level_2/status.c build_sources_program -build_sources_headers level_0/color.h level_0/console.h level_0/conversion.h level_0/directory.h level_0/file.h level_0/fss.h level_0/memory.h level_0/path_fll.h level_0/path_filesystem.h level_0/path.h level_0/pipe.h level_0/print.h level_0/serialized.h level_0/socket.h level_0/status.h level_0/string.h level_0/type.h level_0/type_array.h level_0/utf.h level_1/color.h level_1/console.h level_1/file.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_status.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/print.h level_1/serialized.h level_1/socket.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/directory.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/program.h level_2/status.h +build_sources_headers level_0/color.h level_0/console.h level_0/conversion.h level_0/directory.h level_0/environment.h level_0/file.h level_0/fss.h level_0/memory.h level_0/path_fll.h level_0/path_filesystem.h level_0/path.h level_0/pipe.h level_0/print.h level_0/serialized.h level_0/socket.h level_0/status.h level_0/string.h level_0/type.h level_0/type_array.h level_0/utf.h level_1/color.h level_1/console.h level_1/file.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_status.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/print.h level_1/serialized.h level_1/socket.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/directory.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/program.h level_2/status.h build_sources_bash build_sources_settings build_shared yes diff --git a/level_0/f_color/data/build/defines b/level_0/f_color/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_color/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_console/c/console.h b/level_0/f_console/c/console.h index 0b6316e..374e4de 100644 --- a/level_0/f_console/c/console.h +++ b/level_0/f_console/c/console.h @@ -86,6 +86,13 @@ extern "C" { * - light: Do display color intended for light backgrounds when printing to the console. Other contexts may be acceptable (such as voice inflections, or lack-thereof) for audio.) * - no_color: Do not display color when printing to the console. Other contexts may be acceptable (such as voice inflections, or lack-thereof) for audio.) * - version: Should always print only the version number, no colors, but what represents the version number is undefined by this project. + * + * The following options are for special purposes: + * - status: Represents the return status code from another program. + * Because it is associated with the status from another program, its structure is very subjective. + * The only expectation is that it somehow communicates the fss status codes. + * Example of complex use: "failed_program_name:error:123". + * Example of simple use: "123". */ #ifndef _di_f_standard_console_parameters_ #define f_console_standard_short_dark "d" @@ -111,6 +118,7 @@ extern "C" { #define f_console_standard_long_help "help" #define f_console_standard_long_light "light" #define f_console_standard_long_no_color "no_color" + #define f_console_standard_long_status "status" #define f_console_standard_long_quiet "quiet" #define f_console_standard_long_verbose "verbose" #define f_console_standard_long_version "version" @@ -120,6 +128,7 @@ extern "C" { #define f_console_standard_long_help_length 4 #define f_console_standard_long_light_length 5 #define f_console_standard_long_no_color_length 8 + #define f_console_standard_long_status_length 6 #define f_console_standard_long_quiet_length 5 #define f_console_standard_long_verbose_length 7 #define f_console_standard_long_version_length 7 diff --git a/level_0/f_console/data/build/defines b/level_0/f_console/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_console/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_conversion/data/build/defines b/level_0/f_conversion/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_conversion/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_directory/c/directory.h b/level_0/f_directory/c/directory.h index c467704..77a3215 100644 --- a/level_0/f_directory/c/directory.h +++ b/level_0/f_directory/c/directory.h @@ -125,17 +125,17 @@ extern "C" { /** * A structure representing a directory. + * + * @todo review this and decide to keep and use it or just remove it. */ #ifndef _di_f_directory_ typedef struct { struct dirent entity; - int descriptor; f_directory_listing content; } f_directory; #define f_directory_initialize { \ { 0, 0, 0, 0, 0 }, \ - 0, \ f_directory_listing_initialize, \ } #endif // _di_f_directory_ diff --git a/level_0/f_directory/data/build/defines b/level_0/f_directory/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_directory/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_environment/c/environment.c b/level_0/f_environment/c/environment.c new file mode 100644 index 0000000..5509cf9 --- /dev/null +++ b/level_0/f_environment/c/environment.c @@ -0,0 +1,127 @@ +#include +#include "private-environment.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_f_environment_clear_ + f_return_status f_environment_clear() { + if (clearenv() == 0) { + return f_none; + } + + return f_status_set_error(f_failure); + } +#endif // _di_f_environment_clear_ + +#ifndef _di_f_environment_get_ + f_return_status f_environment_get(const f_string name, f_string_dynamic *value) { + return private_f_environment_get(name, value); + } +#endif // _di_f_environment_get_ + +#ifndef _di_f_environment_get_dynamic_ + f_return_status f_environment_get_dynamic(const f_string_static name, f_string_dynamic *value) { + #ifndef _di_level_0_parameter_checking_ + if (name.used > name.size) return f_status_set_error(f_invalid_parameter); + if (value->used > value->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_0_parameter_checking_ + + if (name.used == 0) return f_no_data; + + if (name.string[name.used - 1] == 0) { + return private_f_environment_get(name.string, value); + } + + char variable_name[name.used + 1]; + + memcpy(&variable_name, name.string, name.used); + variable_name[name.used] = 0; + + return private_f_environment_get(variable_name, value); + } +#endif // _di_f_environment_get_dynamic_ + +#ifndef _di_f_environment_set_ + f_return_status f_environment_set(const f_string name, const f_string value, const bool replace) { + return private_f_environment_set(name, value, replace); + } +#endif // _di_f_environment_set_ + +#ifndef _di_f_environment_set_dynamic_ + f_return_status f_environment_set_dynamic(const f_string_static name, const f_string_static value, const bool replace) { + #ifndef _di_level_0_parameter_checking_ + if (name.used > name.size) return f_status_set_error(f_invalid_parameter); + if (value.used > value.size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_0_parameter_checking_ + + if (name.used == 0) return f_no_data; + + if (name.string[name.used - 1] == 0) { + if (value.used > 0 && value.string[value.used - 1] == 0) { + return private_f_environment_set(name.string, value.string, replace); + } + + char variable_value[value.used + 1]; + + if (value.used > 0) { + memcpy(&variable_value, value.string, value.used); + } + + variable_value[value.used] = 0; + + return private_f_environment_set(name.string, variable_value, replace); + } + + char variable_name[name.used + 1]; + + memcpy(&variable_name, name.string, name.used); + variable_name[name.used] = 0; + + if (value.used > 0 && value.string[value.used - 1] == 0) { + return private_f_environment_set(variable_name, value.string, replace); + } + + char variable_value[value.used + 1]; + + if (value.used > 0) { + memcpy(&variable_value, value.string, value.used); + } + + variable_value[value.used] = 0; + + return private_f_environment_set(variable_name, variable_value, replace); + } +#endif // _di_f_environment_set_dynamic_ + +#ifndef _di_f_environment_unset_ + f_return_status f_environment_unset(const f_string name) { + return private_f_environment_unset(name); + } +#endif // _di_f_environment_unset_ + +#ifndef _di_f_environment_unset_ + f_return_status f_environment_unset_dynamic(const f_string_static name) { + #ifndef _di_level_0_parameter_checking_ + if (name.used > name.size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_0_parameter_checking_ + + if (name.used == 0) return f_no_data; + + if (name.string[name.used - 1] == 0) { + return private_f_environment_unset(name.string); + } + + char variable_name[name.used + 1]; + + memcpy(&variable_name, name.string, name.used); + variable_name[name.used] = 0; + + return private_f_environment_unset(variable_name); + } +#endif // _di_f_environment_unset_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_environment/c/environment.h b/level_0/f_environment/c/environment.h new file mode 100644 index 0000000..bae2d02 --- /dev/null +++ b/level_0/f_environment/c/environment.h @@ -0,0 +1,204 @@ +/** + * FLL - Level 0 + * + * Project: Environment + * API Version: 0.5 + * Licenses: lgplv2.1 + * + * Provides environment processing functionality, such as environment variable handling. + */ +#ifndef _F_environment_h +#define _F_environment_h + +// libc includes +#include +#include + +// fll-0 includes +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Environment related defines. + */ +#ifndef _di_f_environment_defines_ + #define f_environment_max_length f_string_length_size +#endif // _di_f_environment_defines_ + +/** + * Delete all environment variables. + * + * @return + * f_none on success. + * f_failure (with error bit) on failure. + * + * @see clearenv() + */ +#ifndef _di_f_environment_clear_ + extern f_return_status f_environment_clear(); +#endif // _di_f_environment_clear_ + +/** + * Get a single environment variable. + * + * The variable is copied into a new dynamically allocated string and is safe to alter. + * + * @param name + * The name of the environment variable to get. + * The name string must not contain the '=' character. + * The name must be NULL terminated. + * @param value + * The value associated with name. + * The value will not be null terminated. + * The value will be appended (set value->used to 0 to replace). + * + * @return + * f_none on success. + * f_does_not_exist if name does not exist. + * f_string_too_large (with error bit) if appended string length is too large to store in the buffer. + * f_error_reallocation (with error bit) on memory reallocation error. + * + * @see getenv() + */ +#ifndef _di_f_environment_get_ + extern f_return_status f_environment_get(const f_string name, f_string_dynamic *value); +#endif // _di_f_environment_get_ + +/** + * Get a single environment variable. + * + * The variable is copied into a new dynamically allocated string and is safe to alter. + * + * @param name + * The name of the environment variable to get. + * The name string must not contain the '=' character. + * The name need not be NULL terminated. + * @param value + * The value associated with name. + * The value will not be null terminated. + * The value will be appended (set value->used to 0 to replace). + * + * @return + * f_none on success. + * f_does_not_exist if name does not exist. + * f_no_data if name.used is 0. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_string_too_large (with error bit) if appended string length is too large to store in the buffer. + * f_error_reallocation (with error bit) on memory reallocation error. + * + * @see getenv() + */ +#ifndef _di_f_environment_get_dynamic_ + extern f_return_status f_environment_get_dynamic(const f_string_static name, f_string_dynamic *value); +#endif // _di_f_environment_get_dynamic_ + +/** + * Assign the given value to the named environment variable. + * + * If the name does not exist, then it is created. + * + * @param name + * The name of the environment variable to set. + * The name string must not contain the '=' character. + * The name must be NULL terminated. + * @param value + * The value to assign to name. + * The name must be NULL terminated. + * @param replace + * Set to TRUE to replace value if name already exists. + * Set to FALSE to not replace value if name already exists. + * + * @return + * f_none on success. + * f_invalid (with error bit) if name is an invalid string. + * f_out_of_memory (with error bit) on out of memory. + * f_failure (with error bit) on any other error. + * + * @see setenv() + */ +#ifndef _di_f_environment_set_ + extern f_return_status f_environment_set(const f_string name, const f_string value, const bool replace); +#endif // _di_f_environment_set_ + +/** + * Assign the given value to the named environment variable. + * + * If the name does not exist, then it is created. + * + * @param name + * The name of the environment variable to set. + * The name string must not contain the '=' character. + * The name need not be NULL terminated. + * @param value + * The value to assign to name. + * The value need not be NULL terminated. + * @param replace + * Set to TRUE to replace value if name already exists. + * Set to FALSE to not replace value if name already exists. + * + * @return + * f_none on success. + * f_no_data if name.used is 0. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_invalid (with error bit) if name is an invalid string. + * f_out_of_memory (with error bit) on out of memory. + * f_failure (with error bit) on any other error. + * + * @see setenv() + */ +#ifndef _di_f_environment_set_dynamic_ + extern f_return_status f_environment_set_dynamic(const f_string_static name, const f_string_static value, const bool replace); +#endif // _di_f_environment_set_dynamic_ + +/** + * Remove the name environment variable. + * + * @param name + * The name of the environment variable to remove. + * The name string must not contain the '=' character. + * The name must be NULL terminated. + * + * @return + * f_none on success. + * f_invalid (with error bit) if name is an invalid string. + * f_out_of_memory (with error bit) on out of memory. + * f_failure (with error bit) on any other error. + * + * @see unsetenv() + */ +#ifndef _di_f_environment_unset_ + extern f_return_status f_environment_unset(const f_string name); +#endif // _di_f_environment_unset_ + +/** + * Remove the name environment variable. + * + * @param name + * The name of the environment variable to remove. + * The name string must not contain the '=' character. + * The name need not be NULL terminated. + * + * @return + * f_none on success. + * f_invalid (with error bit) if name is an invalid string. + * f_out_of_memory (with error bit) on out of memory. + * f_failure (with error bit) on any other error. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * + * @see unsetenv() + */ +#ifndef _di_f_environment_unset_dynamic_ + extern f_return_status f_environment_unset_dynamic(const f_string_static name); +#endif // _di_f_environment_unset_dynamic_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _F_environment_h diff --git a/level_0/f_environment/c/private-environment.c b/level_0/f_environment/c/private-environment.c new file mode 100644 index 0000000..67bb510 --- /dev/null +++ b/level_0/f_environment/c/private-environment.c @@ -0,0 +1,77 @@ +#include +#include "private-environment.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_di_f_environment_get_) || !defined(_di_f_environment_get_dynamic_) + f_return_status private_f_environment_get(const f_string name, f_string_dynamic *value) { + const f_string result = getenv(name); + + if (result == 0) { + return f_does_not_exist; + } + + const f_string_length size = strnlen(result, f_environment_max_length); + + if (size == 0) { + value->used = 0; + } + else { + if (value->used + size > f_environment_max_length) { + return f_status_set_error(f_string_too_large); + } + + if (value->used + size > value->size) { + f_status status = f_none; + + f_macro_string_dynamic_resize(status, (*value), size); + if (f_status_is_error(status)) return status; + } + + memcpy(&value->string + value->used, result, value->used + size); + value->used = size; + } + + return f_none; + } +#endif // !defined(_di_f_environment_get_) || !defined(_di_f_environment_get_dynamic_) + +#if !defined(_di_f_environment_set_) || !defined(_di_f_environment_set_dynamic_) + f_return_status private_f_environment_set(const f_string name, const f_string value, const bool replace) { + if (setenv(name, value, replace) < 0) { + if (errno == EINVAL) { + return f_status_set_error(f_invalid); + } + else if (errno == ENOMEM) { + return f_status_set_error(f_out_of_memory); + } + + return f_status_set_error(f_failure); + } + + return f_none; + } +#endif // !defined(_di_f_environment_set_) || !defined(_di_f_environment_set_dynamic_) + +#if !defined(_di_f_environment_unset_) || !defined(_di_f_environment_unset_dynamic_) + f_return_status private_f_environment_unset(const f_string name) { + if (unsetenv(name) < 0) { + if (errno == EINVAL) { + return f_status_set_error(f_invalid); + } + else if (errno == ENOMEM) { + return f_status_set_error(f_out_of_memory); + } + + return f_status_set_error(f_failure); + } + + return f_none; + } +#endif // !defined(_di_f_environment_unset_) || !defined(_di_f_environment_unset_dynamic_) + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_environment/c/private-environment.h b/level_0/f_environment/c/private-environment.h new file mode 100644 index 0000000..4dc80b4 --- /dev/null +++ b/level_0/f_environment/c/private-environment.h @@ -0,0 +1,95 @@ +/** + * FLL - Level 0 + * + * Project: Environment + * API Version: 0.5 + * Licenses: lgplv2.1 + * + * Provides environment processing functionality, such as environment variable handling. + */ +#ifndef _PRIVATE_F_environment_h +#define _PRIVATE_F_environment_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get a single environment variable. + * + * The variable is copied into a new dynamically allocated string and is safe to alter. + * + * @param name + * The name of the environment variable to get. + * The name string must not contain the '=' character. + * The name must be NULL terminated. + * @param value + * The value associated with name. + * The value will not be null terminated. + * The value will be appended (set value->used to 0 to replace). + * + * @return + * f_none on success. + * f_does_not_exist if name does not exist. + * f_string_too_large (with error bit) if appended string length is too large to store in the buffer. + * f_error_reallocation (with error bit) on memory reallocation error. + * + * @see f_environment_get() + * @see f_environment_get_dynamic() + */ +#if !defined(_di_f_environment_get_) || !defined(_di_f_environment_get_dynamic_) + extern f_return_status private_f_environment_get(const f_string name, f_string_dynamic *value) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_environment_get_) || !defined(_di_f_environment_get_dynamic_) + +/** + * Assign the given value to the named environment variable. + * + * If the name does not exist, then it is created. + * + * @param name + * The name of the environment variable to set. + * The name string must not contain the '=' character. + * @param value + * The value to assign to name. + * @param replace + * Set to TRUE to replace value if name already exists. + * Set to FALSE to not replace value if name already exists. + * + * @return + * f_none on success. + * f_invalid (with error bit) if name is an invalid string. + * f_out_of_memory (with error bit) on out of memory. + * f_failure (with error bit) on any other error. + * + * @see f_environment_set() + * @see f_environment_set_dynamic() + */ +#if !defined(_di_f_environment_set_) || !defined(_di_f_environment_set_dynamic_) + extern f_return_status private_f_environment_set(const f_string name, const f_string value, const bool replace) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_environment_set_) || !defined(_di_f_environment_set_dynamic_) + +/** + * Remove the name environment variable. + * + * @param name + * The name of the environment variable to remove. + * The name string must not contain the '=' character. + * + * @return + * f_none on success. + * f_invalid (with error bit) if name is an invalid string. + * f_out_of_memory (with error bit) on out of memory. + * f_failure (with error bit) on any other error. + * + * @see f_environment_unset() + * @see f_environment_unset_dynamic() + */ +#if !defined(_di_f_environment_unset_) || !defined(_di_f_environment_unset_dynamic_) + extern f_return_status private_f_environment_unset(const f_string name) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_environment_unset_) || !defined(_di_f_environment_unset_dynamic_) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PRIVATE_F_environment_h diff --git a/level_0/f_environment/data/build/defines b/level_0/f_environment/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_environment/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_environment/data/build/dependencies b/level_0/f_environment/data/build/dependencies new file mode 100644 index 0000000..d8175f5 --- /dev/null +++ b/level_0/f_environment/data/build/dependencies @@ -0,0 +1,4 @@ +f_type +f_status +f_memory +f_string diff --git a/level_0/f_environment/data/build/settings b/level_0/f_environment/data/build/settings new file mode 100644 index 0000000..f12b79e --- /dev/null +++ b/level_0/f_environment/data/build/settings @@ -0,0 +1,30 @@ +# fss-0000 + +project_name f_environment +project_level 0 + +version_major 0 +version_minor 5 +version_micro 0 + +build_compiler gcc +build_linker ar +build_libraries -lc +build_libraries_fll -lf_memory +build_sources_library environment.c private-environment.c +build_sources_program +build_sources_headers environment.h +build_sources_bash +build_sources_settings +build_shared yes +build_static yes + +defines_all +defines_static +defines_shared + +flags_all -z now -g +flags_shared +flags_static +flags_library -fPIC +flags_program -fPIE diff --git a/level_0/f_file/data/build/defines b/level_0/f_file/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_file/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_fss/data/build/defines b/level_0/f_fss/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_fss/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_memory/data/build/defines b/level_0/f_memory/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_memory/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_path/data/build/defines b/level_0/f_path/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_path/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_pipe/data/build/defines b/level_0/f_pipe/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_pipe/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_print/data/build/defines b/level_0/f_print/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_print/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_serialized/data/build/defines b/level_0/f_serialized/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_serialized/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_socket/data/build/defines b/level_0/f_socket/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_socket/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_status/c/status.h b/level_0/f_status/c/status.h index 5376b61..1902e77 100644 --- a/level_0/f_status/c/status.h +++ b/level_0/f_status/c/status.h @@ -311,10 +311,8 @@ extern "C" { f_filesystem_quota_reached, #endif // _di_f_status_filesystem_ - // Most of these are a guess until I get around to researching & implementing linux directory I/O. #ifndef _di_f_status_directory_ f_directory_error, - f_directory_error_allocation, f_directory_error_close, f_directory_error_descriptor, f_directory_error_flush, @@ -322,7 +320,6 @@ extern "C" { f_directory_error_open, f_directory_error_purge, f_directory_error_read, - f_directory_error_reallocation, f_directory_error_stream, f_directory_error_synchronize, f_directory_error_unsupported, diff --git a/level_0/f_status/data/build/defines b/level_0/f_status/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_status/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_0/f_string/c/string.h b/level_0/f_string/c/string.h index e8bb990..e6fabd7 100644 --- a/level_0/f_string/c/string.h +++ b/level_0/f_string/c/string.h @@ -295,6 +295,29 @@ extern "C" { #endif // _di_f_string_dynamic_ /** + * An array of static strings. + * + * array: the array of static strings. + * size: total amount of space available. + * used: total number of space used. + */ +#ifndef _di_f_string_statics_ + typedef struct { + f_string_static *array; + + f_string_length size; + f_string_length used; + } f_string_statics; + + #define f_string_statics_initialize { 0, 0, 0 } + + #define f_macro_string_statics_clear(statics) \ + statics.array = 0; \ + statics.size = 0; \ + statics.used = 0; +#endif // _di_f_string_statics_ + +/** * An array of dynamic strings. * * array: the array of dynamic strings. @@ -302,19 +325,11 @@ extern "C" { * used: total number of allocated spaces used. */ #ifndef _di_f_string_dynamics_ - typedef struct { - f_string_dynamic *array; - - f_string_length size; - f_string_length used; - } f_string_dynamics; + typedef f_string_statics f_string_dynamics; - #define f_string_dynamics_initialize { 0, 0, 0 } + #define f_string_dynamics_initialize f_string_statics_initialize - #define f_macro_string_dynamics_clear(dynamics) \ - dynamics.array = 0; \ - dynamics.size = 0; \ - dynamics.used = 0; + #define f_macro_string_dynamics_clear(dynamics) f_macro_string_statics_clear(dynamics) #define f_macro_string_dynamics_new(status, dynamics, length) \ f_macro_string_dynamics_clear(dynamics) \ diff --git a/level_0/f_type/data/build/defines b/level_0/f_type/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_0/f_type/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_1/fl_color/data/build/defines b/level_1/fl_color/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_1/fl_color/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_1/fl_console/data/build/defines b/level_1/fl_console/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_1/fl_console/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_1/fl_file/data/build/defines b/level_1/fl_file/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_1/fl_file/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_1/fl_fss/data/build/defines b/level_1/fl_fss/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_1/fl_fss/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_1/fl_print/data/build/defines b/level_1/fl_print/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_1/fl_print/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_1/fl_serialized/data/build/defines b/level_1/fl_serialized/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_1/fl_serialized/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_1/fl_socket/data/build/defines b/level_1/fl_socket/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_1/fl_socket/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_1/fl_status/c/status.c b/level_1/fl_status/c/status.c index bdbb5fb..f825007 100644 --- a/level_1/fl_status/c/status.c +++ b/level_1/fl_status/c/status.c @@ -729,12 +729,6 @@ extern "C" { case f_directory_not_open: *string = fl_status_string_directory_not_open; break; - case f_directory_error_allocation: - *string = fl_status_string_directory_allocation_error; - break; - case f_directory_error_reallocation: - *string = fl_status_string_directory_reallocation_error; - break; case f_directory_error: *string = fl_status_string_directory_error; break; diff --git a/level_1/fl_status/c/status.h b/level_1/fl_status/c/status.h index 9de5fc4..938f0b8 100644 --- a/level_1/fl_status/c/status.h +++ b/level_1/fl_status/c/status.h @@ -730,12 +730,6 @@ extern "C" { #define fl_status_string_directory_not_open "f_directory_not_open" #define fl_status_string_directory_not_open_length 20 - #define fl_status_string_directory_allocation_error "f_directory_error_allocation" - #define fl_status_string_directory_allocation_error_length 28 - - #define fl_status_string_directory_reallocation_error "f_directory_error_reallocation" - #define fl_status_string_directory_reallocation_error_length 30 - #define fl_status_string_directory_error "f_directory_error" #define fl_status_string_directory_error_length 17 diff --git a/level_1/fl_status/data/build/defines b/level_1/fl_status/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_1/fl_status/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_1/fl_string/data/build/defines b/level_1/fl_string/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_1/fl_string/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_1/fl_utf/data/build/defines b/level_1/fl_utf/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_1/fl_utf/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_1/fl_utf_file/data/build/defines b/level_1/fl_utf_file/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_1/fl_utf_file/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_2/fll_directory/data/build/defines b/level_2/fll_directory/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_2/fll_directory/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_2/fll_execute/c/execute.c b/level_2/fll_execute/c/execute.c index a606b66..609037e 100644 --- a/level_2/fll_execute/c/execute.c +++ b/level_2/fll_execute/c/execute.c @@ -186,7 +186,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 program_path, const f_string_dynamics arguments, int *result) { + f_return_status fll_execute_path(const f_string program_path, const f_string_statics arguments, int *result) { #ifndef _di_level_2_parameter_checking_ if (result == 0) return f_status_set_error(f_invalid_parameter); if (arguments.used > arguments.size) return f_status_set_error(f_invalid_parameter); @@ -287,8 +287,119 @@ extern "C" { } #endif // _di_fll_execute_path_ +#ifndef _di_fll_execute_path_environment_ + f_return_status fll_execute_path_environment(const f_string program_path, const f_string_statics arguments, const f_string_statics names, const f_string_statics values, int *result) { + #ifndef _di_level_2_parameter_checking_ + if (result == 0) return f_status_set_error(f_invalid_parameter); + if (arguments.used > arguments.size) return f_status_set_error(f_invalid_parameter); + if (names.used > names.size) return f_status_set_error(f_invalid_parameter); + if (values.used > values.size) return f_status_set_error(f_invalid_parameter); + if (names.used > values.used) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_2_parameter_checking_ + + // create a string array that is compatible with execv() calls. + f_string fixed_arguments[arguments.used + 2]; + + f_string last_slash = f_string_initialize; + f_string program_name = f_string_initialize; + + f_string_length name_size = 0; + + f_status status = f_none; + + memset(&fixed_arguments, 0, sizeof(f_string) * (arguments.used + 2)); + + last_slash = strrchr(program_path, '/'); + + if (last_slash != 0) { + name_size = strnlen(last_slash, PATH_MAX); + + if (name_size > 1) { + f_macro_string_new(status, program_name, name_size + 1); + + if (f_status_is_error(status)) return status; + + memcpy(program_name, last_slash + 1, sizeof(f_string_length) * name_size); + memset(program_name, name_size, 0); + } + else { + name_size = 0; + } + } + + if (name_size == 0) { + fixed_arguments[0] = f_string_eos; + } + else { + fixed_arguments[0] = program_name; + } + + for (f_string_length i = 0; i < arguments.used; i++) { + f_macro_string_new(status, fixed_arguments[i + 1], arguments.array[i].used + 1); + + if (f_status_is_error(status)) { + if (name_size > 0) f_macro_string_delete_simple(program_name, name_size); + + for (f_string_length j = 0; j < i; j++) { + f_macro_string_delete_simple(fixed_arguments[i + 1], arguments.array[j].used + 1); + } // for + + return status; + } + + memcpy(fixed_arguments[i + 1], arguments.array[i].string, arguments.array[i].used); + fixed_arguments[i + 1][arguments.array[i].used] = f_string_eos; + } // for + + // insert the required array terminated + fixed_arguments[arguments.used + 2] = 0; + + // @todo validate that the file at program_path actually exists before attempting to fork and execute + int process_id = 0; + + process_id = vfork(); + + if (process_id < 0) { + if (name_size > 0) f_macro_string_delete_simple(program_name, name_size); + + for (f_string_length i = 0; i < arguments.used; i++) { + f_macro_string_delete_simple(fixed_arguments[i + 1], arguments.array[i].used + 1); + } // for + + return f_status_set_error(f_fork_failed); + } + + // child + if (process_id == 0) { + clearenv(); + + for (f_array_length i = 0; i < names.used; i++) { + f_environment_set_dynamic(names.array[i], values.array[i], true); + } + + execv(program_path, fixed_arguments); + + // 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, result, 0); + + if (name_size > 0) f_macro_string_delete_simple(program_name, name_size); + + for (f_string_length i = 0; i < arguments.used; i++) { + f_macro_string_delete_simple(fixed_arguments[i + 1], arguments.array[i].used + 1); + } // for + + if (*result != 0) return f_status_set_error(f_failure); + + return f_none; + } +#endif // _di_fll_execute_path_environment_ + #ifndef _di_fll_execute_program_ - f_return_status fll_execute_program(const f_string program_name, const f_string_dynamics arguments, int *result) { + f_return_status fll_execute_program(const f_string program_name, const f_string_statics arguments, int *result) { #ifndef _di_level_2_parameter_checking_ if (result == 0) return f_status_set_error(f_invalid_parameter); if (arguments.used > arguments.size) return f_status_set_error(f_invalid_parameter); @@ -354,6 +465,82 @@ extern "C" { } #endif // _di_fll_execute_program_ +#ifndef _di_fll_execute_program_environment_ + f_return_status fll_execute_program_environment(const f_string program_name, const f_string_statics arguments, const f_string_statics names, const f_string_statics values, int *result) { + #ifndef _di_level_2_parameter_checking_ + if (result == 0) return f_status_set_error(f_invalid_parameter); + if (arguments.used > arguments.size) return f_status_set_error(f_invalid_parameter); + if (names.used > names.size) return f_status_set_error(f_invalid_parameter); + if (values.used > values.size) return f_status_set_error(f_invalid_parameter); + if (names.used > values.used) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_2_parameter_checking_ + + // create a string array that is compatible with execv() calls. + f_string fixed_arguments[arguments.used + 2]; + + memset(&fixed_arguments, 0, sizeof(f_string) * (arguments.used + 2)); + fixed_arguments[0] = program_name; + + f_status status = f_none; + + for (f_string_length i = 0; i < arguments.used; i++) { + f_macro_string_new(status, fixed_arguments[i + 1], arguments.array[i].used + 1); + + if (f_status_is_error(status)) { + for (f_string_length j = 0; j < i; j++) { + f_macro_string_delete_simple(fixed_arguments[i + 1], arguments.array[j].used + 1); + } // for + + return status; + } + + memcpy(fixed_arguments[i + 1], arguments.array[i].string, arguments.array[i].used); + fixed_arguments[i + 1][arguments.array[i].used] = f_string_eos; + } // for + + // insert the required array terminated + fixed_arguments[arguments.used + 2] = 0; + + // @todo validate that the file at program_path actually exists before attempting to fork and execute + int process_id = 0; + + process_id = vfork(); + + if (process_id < 0) { + for (f_string_length i = 0; i < arguments.used; i++) { + f_macro_string_delete_simple(fixed_arguments[i + 1], arguments.array[i].used + 1); + } // for + + return f_status_set_error(f_fork_failed); + } + + // child + if (process_id == 0) { + clearenv(); + + for (f_array_length i = 0; i < names.used; i++) { + f_environment_set_dynamic(names.array[i], values.array[i], true); + } + + execvp(program_name, fixed_arguments); + + // 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, result, 0); + + for (f_string_length i = 0; i < arguments.used; i++) { + f_macro_string_delete_simple(fixed_arguments[i + 1], arguments.array[i].used + 1); + } // for + + if (*result != 0) return f_status_set_error(f_failure); + + return f_none; + } +#endif // _di_fll_execute_program_environment_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_2/fll_execute/c/execute.h b/level_2/fll_execute/c/execute.h index d454b72..6d1e6e1 100644 --- a/level_2/fll_execute/c/execute.h +++ b/level_2/fll_execute/c/execute.h @@ -23,6 +23,7 @@ #include #include #include +#include // fll-1 includes #include @@ -298,10 +299,43 @@ extern "C" { * @see execv() */ #ifndef _di_fll_execute_path_ - extern f_return_status fll_execute_path(const f_string program_path, const f_string_dynamics arguments, int *result); + extern f_return_status fll_execute_path(const f_string program_path, const f_string_statics arguments, int *result); #endif // _di_fll_execute_path_ /** + * Execute a program given some path + program name (such as "/bin/bash"). + * + * The environment is defined by the names and values pair. + * + * @param program_path + * The entire path to the program. + * @param arguments + * An array of strings representing the arguments. + * @param names + * An array of strings representing the environment variable names. + * At most names.used variables are created. + * Duplicate names are overwritten. + * @param values + * An array of strings representing the environment variable names. + * The values.used must be of at least names.used. + * Set individual strings.used to 0 for empty/null values. + * @param result + * The code returned after finishing execution of program_path. + * + * @return + * f_none on success. + * f_failure (with error bit) if result is non-zero. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * + * @see execv() + */ +#ifndef _di_fll_execute_path_environment_ + f_return_status fll_execute_path_environment(const f_string program_path, const f_string_statics arguments, const f_string_statics names, const f_string_statics values, int *result); +#endif // _di_fll_execute_path_environment_ + +/** * Execute a program given by name found in the PATH environment (such as "bash"). * * @param program_name @@ -322,9 +356,45 @@ extern "C" { * @see execvp() */ #ifndef _di_fll_execute_program_ - extern f_return_status fll_execute_program(const f_string program_name, const f_string_dynamics arguments, int *result); + extern f_return_status fll_execute_program(const f_string program_name, const f_string_statics arguments, 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. + * + * @todo this probably needs special work to find the program from PATH when PATH environment variable gets cleared before execution. + * + * @param program_name + * The name of the program. + * @param arguments + * An array of strings representing the arguments. + * @param names + * An array of strings representing the environment variable names. + * At most names.used variables are created. + * Duplicate names are overwritten. + * @param values + * An array of strings representing the environment variable names. + * The values.used must be of at least names.used. + * Set individual strings.used to 0 for empty/null values. + * @param result + * The code returned after finishing execution of program. + * + * @return + * f_none on success. + * f_failure (with error bit) if result is non-zero. + * f_fork_failed (with error bit) on fork failure. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on allocation error. + * f_error_reallocation (with error bit) on reallocation error. + * + * @see execvpe() + */ +#ifndef _di_fll_execute_program_environment_ + extern f_return_status fll_execute_program_environment(const f_string program_name, const f_string_statics arguments, const f_string_statics names, const f_string_statics values, int *result); +#endif // _di_fll_execute_program_environment_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_2/fll_execute/data/build/defines b/level_2/fll_execute/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_2/fll_execute/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_2/fll_execute/data/build/dependencies b/level_2/fll_execute/data/build/dependencies index 4804427..c33a8e4 100644 --- a/level_2/fll_execute/data/build/dependencies +++ b/level_2/fll_execute/data/build/dependencies @@ -2,4 +2,5 @@ f_type f_status f_memory f_string +f_environment fl_string diff --git a/level_2/fll_execute/data/build/settings b/level_2/fll_execute/data/build/settings index c51b88d..e9f161e 100644 --- a/level_2/fll_execute/data/build/settings +++ b/level_2/fll_execute/data/build/settings @@ -10,7 +10,7 @@ version_micro 0 build_compiler gcc build_linker ar build_libraries -lc -build_libraries_fll -lfl_string -lf_memory +build_libraries_fll -lfl_string -lf_environment -lf_memory build_sources_library execute.c private-execute.c build_sources_program build_sources_headers execute.h diff --git a/level_2/fll_file/data/build/defines b/level_2/fll_file/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_2/fll_file/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_2/fll_fss/c/fss_basic.c b/level_2/fll_fss/c/fss_basic.c index e71bb1c..d1f506a 100644 --- a/level_2/fll_fss/c/fss_basic.c +++ b/level_2/fll_fss/c/fss_basic.c @@ -143,7 +143,7 @@ extern "C" { #endif // _di_fll_fss_basic_read_ #ifndef _di_fll_fss_basic_write_ - f_return_status fll_fss_basic_write(const f_string_static object, const f_string_dynamics contents, f_string_dynamic *buffer) { + f_return_status fll_fss_basic_write(const f_string_static object, const f_string_statics contents, f_string_dynamic *buffer) { #ifndef _di_level_2_parameter_checking_ if (buffer == 0) return f_status_set_error(f_invalid_parameter); if (contents.used > contents.size) return f_status_set_error(f_invalid_parameter); diff --git a/level_2/fll_fss/c/fss_basic.h b/level_2/fll_fss/c/fss_basic.h index 18032a5..1eda122 100644 --- a/level_2/fll_fss/c/fss_basic.h +++ b/level_2/fll_fss/c/fss_basic.h @@ -79,7 +79,7 @@ extern "C" { * f_invalid_parameter (with error bit) if a parameter is invalid. */ #ifndef _di_fll_fss_basic_write_ - extern f_return_status fll_fss_basic_write(const f_string_static object, const f_string_dynamics contents, f_string_dynamic *buffer); + extern f_return_status fll_fss_basic_write(const f_string_static object, const f_string_statics contents, f_string_dynamic *buffer); #endif // _di_fll_fss_basic_write_ #ifdef __cplusplus diff --git a/level_2/fll_fss/c/fss_basic_list.c b/level_2/fll_fss/c/fss_basic_list.c index ff2c4bf..1d199ab 100644 --- a/level_2/fll_fss/c/fss_basic_list.c +++ b/level_2/fll_fss/c/fss_basic_list.c @@ -143,7 +143,7 @@ extern "C" { #endif // _di_fll_fss_basic_list_read_ #ifndef _di_fll_fss_basic_list_write_ - f_return_status fll_fss_basic_list_write(const f_string_static object, const f_string_dynamics contents, f_string_dynamic *buffer) { + f_return_status fll_fss_basic_list_write(const f_string_static object, const f_string_statics contents, f_string_dynamic *buffer) { #ifndef _di_level_2_parameter_checking_ if (buffer == 0) return f_status_set_error(f_invalid_parameter); if (contents.used > contents.size) return f_status_set_error(f_invalid_parameter); diff --git a/level_2/fll_fss/c/fss_basic_list.h b/level_2/fll_fss/c/fss_basic_list.h index 8ac24a3..f201b2a 100644 --- a/level_2/fll_fss/c/fss_basic_list.h +++ b/level_2/fll_fss/c/fss_basic_list.h @@ -78,7 +78,7 @@ extern "C" { * f_invalid_parameter (with error bit) if a parameter is invalid. */ #ifndef _di_fll_fss_basic_list_write_ - extern f_return_status fll_fss_basic_list_write(const f_string_static object, const f_string_dynamics contents, f_string_dynamic *buffer); + extern f_return_status fll_fss_basic_list_write(const f_string_static object, const f_string_statics contents, f_string_dynamic *buffer); #endif // _di_fll_fss_basic_list_write_ #ifdef __cplusplus diff --git a/level_2/fll_fss/c/fss_extended.c b/level_2/fll_fss/c/fss_extended.c index a566238..20cdef0 100644 --- a/level_2/fll_fss/c/fss_extended.c +++ b/level_2/fll_fss/c/fss_extended.c @@ -143,7 +143,7 @@ extern "C" { #endif // _di_fll_fss_extended_read_ #ifndef _di_fll_fss_extended_write_ - f_return_status fll_fss_extended_write(const f_string_static object, const f_string_dynamics contents, f_string_dynamic *buffer) { + f_return_status fll_fss_extended_write(const f_string_static object, const f_string_statics contents, f_string_dynamic *buffer) { #ifndef _di_level_2_parameter_checking_ if (buffer == 0) return f_status_set_error(f_invalid_parameter); if (contents.used > contents.size) return f_status_set_error(f_invalid_parameter); diff --git a/level_2/fll_fss/c/fss_extended.h b/level_2/fll_fss/c/fss_extended.h index 0a6fdc3..8d1dde7 100644 --- a/level_2/fll_fss/c/fss_extended.h +++ b/level_2/fll_fss/c/fss_extended.h @@ -78,7 +78,7 @@ extern "C" { * f_invalid_parameter (with error bit) if a parameter is invalid. */ #ifndef _di_fll_fss_extended_write_ - extern f_return_status fll_fss_extended_write(const f_string_static object, const f_string_dynamics contents, f_string_dynamic *buffer); + extern f_return_status fll_fss_extended_write(const f_string_static object, const f_string_statics contents, f_string_dynamic *buffer); #endif // _di_fll_fss_extended_write_ #ifdef __cplusplus diff --git a/level_2/fll_fss/c/fss_extended_list.c b/level_2/fll_fss/c/fss_extended_list.c index a9b6024..96971c6 100644 --- a/level_2/fll_fss/c/fss_extended_list.c +++ b/level_2/fll_fss/c/fss_extended_list.c @@ -113,7 +113,7 @@ extern "C" { /* #ifndef _di_fll_fss_extended_list_write_ - f_return_status fll_fss_extended_list_write(const f_string_static object, const f_string_dynamics contents, f_string_dynamic *buffer) { + f_return_status fll_fss_extended_list_write(const f_string_static object, const f_string_statics contents, f_string_dynamic *buffer) { #ifndef _di_level_3_parameter_checking_ if (buffer == 0) return f_status_set_error(f_invalid_parameter); if (contents.used > contents.size) return f_status_set_error(f_invalid_parameter); diff --git a/level_2/fll_fss/c/fss_extended_list.h b/level_2/fll_fss/c/fss_extended_list.h index 0ab413f..f3c6354 100644 --- a/level_2/fll_fss/c/fss_extended_list.h +++ b/level_2/fll_fss/c/fss_extended_list.h @@ -83,7 +83,7 @@ extern "C" { * f_invalid_parameter (with error bit) if a parameter is invalid. */ #ifndef _di_fll_fss_extended_list_write_ - //extern f_return_status fll_fss_extended_list_write(const f_string_static object, const f_string_dynamics contents, f_string_dynamic *buffer); + //extern f_return_status fll_fss_extended_list_write(const f_string_static object, const f_string_statics contents, f_string_dynamic *buffer); #endif // _di_fll_fss_extended_list_write_ #ifdef __cplusplus diff --git a/level_2/fll_fss/data/build/defines b/level_2/fll_fss/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_2/fll_fss/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_2/fll_program/data/build/defines b/level_2/fll_program/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_2/fll_program/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_2/fll_status/c/status.c b/level_2/fll_status/c/status.c index be2b8f3..fc8ec3c 100644 --- a/level_2/fll_status/c/status.c +++ b/level_2/fll_status/c/status.c @@ -1186,16 +1186,6 @@ extern "C" { return f_none; } - if (fl_string_compare(string, fl_status_string_directory_allocation_error, length, fl_status_string_directory_allocation_error_length) == f_equal_to) { - *code = f_directory_error_allocation; - return f_none; - } - - if (fl_string_compare(string, fl_status_string_directory_reallocation_error, length, fl_status_string_directory_reallocation_error_length) == f_equal_to) { - *code = f_directory_error_reallocation; - return f_none; - } - if (fl_string_compare(string, fl_status_string_directory_error, length, fl_status_string_directory_error_length) == f_equal_to) { *code = f_directory_error; return f_none; diff --git a/level_2/fll_status/data/build/defines b/level_2/fll_status/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_2/fll_status/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_3/byte_dump/data/build/defines b/level_3/byte_dump/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_3/byte_dump/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_3/fss_basic_list_read/data/build/defines b/level_3/fss_basic_list_read/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_3/fss_basic_list_read/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_3/fss_basic_list_write/data/build/defines b/level_3/fss_basic_list_write/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_3/fss_basic_list_write/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_3/fss_basic_read/data/build/defines b/level_3/fss_basic_read/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_3/fss_basic_read/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_3/fss_basic_write/data/build/defines b/level_3/fss_basic_write/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_3/fss_basic_write/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_3/fss_extended_list_read/data/build/defines b/level_3/fss_extended_list_read/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_3/fss_extended_list_read/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_3/fss_extended_read/data/build/defines b/level_3/fss_extended_read/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_3/fss_extended_read/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_3/fss_extended_write/data/build/defines b/level_3/fss_extended_write/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_3/fss_extended_write/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_3/fss_status_code/data/build/defines b/level_3/fss_status_code/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_3/fss_status_code/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_3/init/data/build/defines b/level_3/init/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_3/init/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_3/status_code/data/build/defines b/level_3/status_code/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_3/status_code/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + -- 1.8.3.1