This is necessary for the parent process to directly pipe date to/from a child process.
One of the intended goals is for something like the controller program to directly execute a bash script from a string generated by the parent (where this is no file).
The standard input can be used by the child process as pipe data.
When a pipe is passed then the execute functions are asynchronous instead of blocking.
The caller must properly handling all blocking operations as appropriate.
The pipe functionality is optional.
build_libraries-level
build_sources_library account.c console.c conversion.c directory.c private-directory.c environment.c private-environment.c file.c private-file.c fss.c iki.c private-iki.c memory.c path.c private-path.c pipe.c print.c private-print.c process.c serialize.c private-serialize.c signal.c socket.c utf.c private-utf.c
build_sources_program
-build_sources_headers account.h account-common.h color.h console.h console-common.h conversion.h conversion-common.h directory.h directory_type.h directory-common.h environment.h environment-common.h file.h file-common.h fss.h fss-common.h fss_comment.h fss_delimit.h fss_named.h fss_nest.h fss_quote.h fss_set.h iki.h iki-common.h memory.h memory_structure.h path.h path-common.h pipe.h print.h process.h process-common.h serialize.h serialize-common.h signal.h signal-common.h socket.h socket-common.h status.h status_array.h string.h string-common.h string_dynamic.h string_map.h string_quantity.h string_range.h string_triple.h type.h type_array.h utf.h utf-common.h
+build_sources_headers account.h account-common.h color.h console.h console-common.h conversion.h conversion-common.h directory.h directory_type.h directory-common.h environment.h environment-common.h execute.h execute-common.h file.h file-common.h fss.h fss-common.h fss_comment.h fss_delimit.h fss_named.h fss_nest.h fss_quote.h fss_set.h iki.h iki-common.h memory.h memory_structure.h path.h path-common.h pipe.h print.h process.h process-common.h serialize.h serialize-common.h signal.h signal-common.h socket.h socket-common.h status.h status_array.h string.h string-common.h string_dynamic.h string_map.h string_quantity.h string_range.h string_triple.h type.h type_array.h utf.h utf-common.h
build_sources_script
build_sources_setting
build_script yes
build_libraries-monolithic
build_sources_library level_0/account.c 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/private-file.c level_0/fss.c level_0/iki.c level_0/private-iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/private-print.c level_0/process.c level_0/serialize.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_embedded_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/private-print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/type.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/error.c level_2/private-error.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_embedded_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/iki.c level_2/private-iki.c level_2/path.c level_2/program.c level_2/status.c
build_sources_program
-build_sources_headers level_0/account.h level_0/account-common.h level_0/color.h level_0/console.h level_0/console-common.h level_0/conversion.h level_0/conversion-common.h level_0/directory.h level_0/directory_type.h level_0/directory-common.h level_0/environment.h level_0/environment-common.h level_0/file.h level_0/file-common.h level_0/fss.h level_0/fss-common.h level_0/fss_comment.h level_0/fss_delimit.h level_0/fss_named.h level_0/fss_nest.h level_0/fss_quote.h level_0/fss_set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory_structure.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/process.h level_0/process-common.h level_0/serialize.h level_0/serialize-common.h level_0/signal.h level_0/signal-common.h level_0/socket.h level_0/socket-common.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string-common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/string_triple.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_embedded_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/type.h level_1/utf.h level_1/utf_file.h level_2/error.h level_2/error-common.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_embedded_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/iki.h level_2/path.h level_2/program.h level_2/status.h
+build_sources_headers level_0/account.h level_0/account-common.h level_0/color.h level_0/console.h level_0/console-common.h level_0/conversion.h level_0/conversion-common.h level_0/directory.h level_0/directory_type.h level_0/directory-common.h level_0/environment.h level_0/environment-common.h level_0/execute.h level_0/execute-common.h level_0/file.h level_0/file-common.h level_0/fss.h level_0/fss-common.h level_0/fss_comment.h level_0/fss_delimit.h level_0/fss_named.h level_0/fss_nest.h level_0/fss_quote.h level_0/fss_set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory_structure.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/process.h level_0/process-common.h level_0/serialize.h level_0/serialize-common.h level_0/signal.h level_0/signal-common.h level_0/socket.h level_0/socket-common.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string-common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/string_triple.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_embedded_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/type.h level_1/utf.h level_1/utf_file.h level_2/error.h level_2/error-common.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_embedded_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/iki.h level_2/path.h level_2/program.h level_2/status.h
build_sources_script
build_sources_setting
build_script yes
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual
+build_libraries-individual -lf_memory
build_sources_library
build_sources_program
build_sources_headers color.h
--- /dev/null
+/**
+ * FLL - Level 0
+ *
+ * Project: Execute
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * Defines common data to be used for/by project execute.
+ *
+ * This is auto-included by execute.h and should not need to be explicitly included.
+ */
+#ifndef _F_execute_common_h
+#define _F_execute_common_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A set containing the three standard descriptors for use in pipes.
+ *
+ * Future versions may suppot stdwarn and stddebug if there ever is such a thing.
+ *
+ * Descriptors always use -1 to designate not used because 0 represent a valid descriptor.
+ *
+ * input: the input file descriptor.
+ * output: the output file descriptor.
+ * error: the error file descriptor.
+ */
+#ifndef _di_f_execute_pipe_t_
+ typedef struct {
+ int input;
+ int output;
+ int error;
+ } f_execute_pipe_t;
+
+ #define f_execute_pipe_t_initialize { -1, -1, -1 }
+
+ #define f_execute_pipe_t_clear(set) \
+ set.input = -1; \
+ set.output = -1; \
+ set.error = -1;
+#endif // _di_f_execute_pipe_t_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _F_execute_common_h
--- /dev/null
+/**
+ * FLL - Level 0
+ *
+ * Project: Execute
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * Provides execute processing functionality.
+ */
+#ifndef _F_execute_h
+#define _F_execute_h
+
+// libc includes
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+
+// fll-0 execute includes
+#include <level_0/execute-common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _F_execute_h
--- /dev/null
+# fss-0000
--- /dev/null
+# fss-0000
+
+f_type
+f_status
+f_string
--- /dev/null
+# fss-0001
+
+project_name f_execute
+
+version_major 0
+version_minor 5
+version_micro 2
+version_target major
+
+environment
+
+process_pre
+process_post
+
+modes individual
+modes_default individual
+
+build_compiler gcc
+build_indexer ar
+build_language c
+build_libraries -lc
+build_libraries-individual -lf_memory
+build_sources_library
+build_sources_program
+build_sources_headers execute.h execute-common.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+path_headers level_0
+path_headers_preserve no
+path_library_script script
+path_library_shared shared
+path_library_static static
+path_program_script script
+path_program_shared shared
+path_program_static static
+path_sources
+path_standard yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+defines_all
+defines_static
+defines_shared
+
+flags_all -z now -g -fdiagnostics-color=always
+flags_shared
+flags_static
+flags_library -fPIC
+flags_program -fPIE
#include <level_0/type.h>
#include <level_0/status.h>
+// fll-0 signal includes
+#include <level_0/signal-common.h>
+
#ifdef __cplusplus
extern "C" {
#endif
-// fll-0 signal includes
-#include <level_0/signal-common.h>
-
/**
* Close an open signal descriptor.
*
#endif // _di_fll_execute_arguments_dynamic_add_set_
#ifndef _di_fll_execute_path_
- f_return_status fll_execute_path(const f_string_t program_path, const f_string_statics_t arguments, const f_signal_how_t *signals, int *result) {
+ f_return_status fll_execute_path(const f_string_t program_path, const f_string_statics_t arguments, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) {
#ifndef _di_level_2_parameter_checking_
if (!result) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
}
}
- return private_fll_execute_fork(program_name, fixed_arguments, F_false, signals, result);
+ return private_fll_execute_fork(program_name, fixed_arguments, F_false, signals, pipe, result);
}
#endif // _di_fll_execute_path_
#ifndef _di_fll_execute_path_environment_
- f_return_status fll_execute_path_environment(const f_string_t program_path, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, int *result) {
+ f_return_status fll_execute_path_environment(const f_string_t program_path, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) {
#ifndef _di_level_2_parameter_checking_
if (!result) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
}
}
- return private_fll_execute_fork_environment(program_name, fixed_arguments, F_false, names, values, signals, result);
+ return private_fll_execute_fork_environment(program_name, fixed_arguments, F_false, names, values, signals, pipe, result);
}
#endif // _di_fll_execute_path_environment_
#ifndef _di_fll_execute_program_
- f_return_status fll_execute_program(const f_string_t program_name, const f_string_statics_t arguments, const f_signal_how_t *signals, int *result) {
+ f_return_status fll_execute_program(const f_string_t program_name, const f_string_statics_t arguments, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) {
#ifndef _di_level_2_parameter_checking_
if (!result) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
// insert the required array terminated.
fixed_arguments[arguments.used + 1] = 0;
- return private_fll_execute_fork(program_name, fixed_arguments, F_true, signals, result);
+ return private_fll_execute_fork(program_name, fixed_arguments, F_true, signals, pipe, result);
}
#endif // _di_fll_execute_program_
#ifndef _di_fll_execute_program_environment_
- f_return_status fll_execute_program_environment(const f_string_t program_name, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, int *result) {
+ f_return_status fll_execute_program_environment(const f_string_t program_name, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) {
#ifndef _di_level_2_parameter_checking_
if (!result) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
f_macro_string_dynamics_t_delete(status, paths);
if (F_status_is_error(status)) return status;
- return private_fll_execute_fork_environment(program_name, fixed_arguments, F_true, names, values, signals, result);
+ return private_fll_execute_fork_environment(program_name, fixed_arguments, F_true, names, values, signals, pipe, result);
}
#endif // _di_fll_execute_program_environment_
#include <level_0/string.h>
#include <level_0/utf.h>
#include <level_0/environment.h>
+#include <level_0/execute.h>
#include <level_0/file.h>
#include <level_0/path.h>
#include <level_0/signal.h>
* Instead, this returns F_child and assigns the child's return code to result.
* The caller is expected to handle the appropriate exit procedures and memory deallocation.
*
+ * When the passed pipe parameter is not NULL, this function is effectively asynchronous and will not block.
+ * The caller is then expected to handle all read/write operations to/from the pipe.
+ * The caller is expected to appropriately call waitpid() or similar as needed.
+ * The caller is expected to handle both parent and child process (status is F_parent for parent and F_child for child.).
+ * When the passed paremeter is NULL, then this function is effectively synchronous and blocks until child exits.
+ *
* @param program_path
* The entire path to the program.
* @param arguments
* An array of strings representing the arguments.
- * @param set_signal
+ * @param signals
* (optional) A pointer to the set of signals.
* Set to 0 to disable.
+ * @param pipe
+ * (optional) A pointer to the set of pipe desciptors (I/O) to be used by the child process.
+ * When a non-zero address, the child process will assign these as the standard I/O file descriptors for piping to/from the parent/child.
+ * For each pipe, setting a value of -1 means to use the default pipe.
+ * Set to 0 to disable.
* @param result
* The code returned after finishing execution of program_path.
*
* @return
* F_none on success.
- * F_child on success but this is the child thread (this may happen when calling scripts rather than executing a binary).
- * F_failure (with error bit) if result is non-zero.
- * F_fork (with error bit) if fork failed.
+ * F_child on success but this is the child thread.
+ * F_parent on success but this is the parent thread and pipe is non-zero (function is not blocking).
+ * F_failure (with error bit set) on execution failure.
+ * F_fork (with error bit set) on fork failure.
*
* Errors (with error bit) from: f_file_exists().
* Errors (with error bit) from: f_signal_set_handle().
*
+ * @see dup2()
* @see execv()
* @see exit()
* @see fork()
* @see f_signal_set_handle()
*/
#ifndef _di_fll_execute_path_
- extern f_return_status fll_execute_path(const f_string_t program_path, const f_string_statics_t arguments, const f_signal_how_t *signals, int *result);
+ extern f_return_status fll_execute_path(const f_string_t program_path, const f_string_statics_t arguments, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result);
#endif // _di_fll_execute_path_
/**
* Instead, this returns F_child and assigns the child's return code to result.
* The caller is expected to handle the appropriate exit procedures and memory deallocation.
*
+ * When the passed pipe parameter is not NULL, this function is effectively asynchronous and will not block.
+ * The caller is then expected to handle all read/write operations to/from the pipe.
+ * The caller is expected to appropriately call waitpid() or similar as needed.
+ * The caller is expected to handle both parent and child process (status is F_parent for parent and F_child for child.).
+ * When the passed paremeter is NULL, then this function is effectively synchronous and blocks until child exits.
+ *
* @param program_path
* The entire path to the program.
* @param arguments
* @param signals
* (optional) A pointer to the set of signals.
* Set to 0 to disable.
+ * @param pipe
+ * (optional) A pointer to the set of pipe desciptors (I/O) to be used by the child process.
+ * When a non-zero address, the child process will assign these as the standard I/O file descriptors for piping to/from the parent/child.
+ * For each pipe, setting a value of -1 means to use the default pipe.
+ * Set to 0 to disable.
* @param result
* The code returned after finishing execution of program_path.
*
* @return
* F_none on success.
- * F_child on success but this is the child thread (this may happen when calling scripts rather than executing a binary).
- * F_failure (with error bit) if result is non-zero.
- * F_fork (with error bit) if fork failed.
+ * F_child on success but this is the child thread.
+ * F_parent on success but this is the parent thread and pipe is non-zero (function is not blocking).
+ * F_failure (with error bit set) on execution failure.
+ * F_fork (with error bit set) on fork failure.
*
* Errors (with error bit) from: f_environment_set_dynamic().
* Errors (with error bit) from: f_file_exists().
* Errors (with error bit) from: f_signal_set_handle().
*
- * @see execv()
* @see clearenv()
+ * @see dup2()
+ * @see execv()
* @see fork()
* @see memcpy()
* @see strnlen()
* @see f_signal_set_handle()
*/
#ifndef _di_fll_execute_path_environment_
- extern f_return_status fll_execute_path_environment(const f_string_t program_path, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, int *result);
+ extern f_return_status fll_execute_path_environment(const f_string_t program_path, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result);
#endif // _di_fll_execute_path_environment_
/**
* Instead, this returns F_child and assigns the child's return code to result.
* The caller is expected to handle the appropriate exit procedures and memory deallocation.
*
+ * When the passed pipe parameter is not NULL, this function is effectively asynchronous and will not block.
+ * The caller is then expected to handle all read/write operations to/from the pipe.
+ * The caller is expected to appropriately call waitpid() or similar as needed.
+ * The caller is expected to handle both parent and child process (status is F_parent for parent and F_child for child.).
+ * When the passed paremeter is NULL, then this function is effectively synchronous and blocks until child exits.
+ *
* @param program_name
* The name of the program.
* @param arguments
* An array of strings representing the arguments.
- * @param set_signal
+ * @param signals
* (optional) A pointer to the set of signals.
* Set to 0 to disable.
+ * @param pipe
+ * (optional) A pointer to the set of pipe desciptors (I/O) to be used by the child process.
+ * When a non-zero address, the child process will assign these as the standard I/O file descriptors for piping to/from the parent/child.
+ * For each pipe, setting a value of -1 means to use the default pipe.
+ * Set to 0 to disable.
* @param result
* The code returned after finishing execution of program.
*
* @return
* F_none on success.
- * F_child on success but this is the child thread (this may happen when calling scripts rather than executing a binary).
- * F_failure (with error bit) if result is non-zero.
- * F_fork (with error bit) if fork failed.
+ * F_child on success but this is the child thread.
+ * F_parent on success but this is the parent thread and pipe is non-zero (function is not blocking).
+ * F_failure (with error bit set) on execution failure.
+ * F_fork (with error bit set) on fork failure.
*
* Errors (with error bit) from: f_file_exists().
* Errors (with error bit) from: f_signal_set_handle().
*
+ * @see dup2()
* @see execvp()
* @see fork()
* @see strnlen()
* @see f_signal_set_handle()
*/
#ifndef _di_fll_execute_program_
- extern f_return_status fll_execute_program(const f_string_t program_name, const f_string_statics_t arguments, const f_signal_how_t *signals, int *result);
+ extern f_return_status fll_execute_program(const f_string_t program_name, const f_string_statics_t arguments, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result);
#endif // _di_fll_execute_program_
/**
* Instead, this returns F_child and assigns the child's return code to result.
* The caller is expected to handle the appropriate exit procedures and memory deallocation.
*
+ * When the passed pipe parameter is not NULL, this function is effectively asynchronous and will not block.
+ * The caller is then expected to handle all read/write operations to/from the pipe.
+ * The caller is expected to appropriately call waitpid() or similar as needed.
+ * The caller is expected to handle both parent and child process (status is F_parent for parent and F_child for child.).
+ * When the passed paremeter is NULL, then this function is effectively synchronous and blocks until child exits.
+ *
* @param program_name
* The name of the program.
* @param arguments
* @param signals
* (optional) A pointer to the set of signals.
* Set to 0 to disable.
+ * @param pipe
+ * (optional) A pointer to the set of pipe desciptors (I/O) to be used by the child process.
+ * When a non-zero address, the child process will assign these as the standard I/O file descriptors for piping to/from the parent/child.
+ * For each pipe, setting a value of -1 means to use the default pipe.
+ * Set to 0 to disable.
* @param result
* The code returned after finishing execution of program.
*
* @return
* F_none on success.
- * F_child on success but this is the child thread (this may happen when calling scripts rather than executing a binary).
- * F_failure (with error bit) if result is non-zero.
- * F_fork (with error bit) if fork failed.
+ * F_child on success but this is the child thread.
+ * F_parent on success but this is the parent thread and pipe is non-zero (function is not blocking).
+ * F_failure (with error bit set) on execution failure.
+ * F_fork (with error bit set) on fork failure.
*
* Errors (with error bit) from: f_environment_get().
* Errors (with error bit) from: f_file_exists().
* Errors (with error bit) from: fl_string_append().
* Errors (with error bit) from: fl_string_dynamic_terminate().
*
+ * @see clearenv()
+ * @see dup2()
* @see execvp()
* @see fork()
* @see memcpy()
* @see fl_string_dynamic_terminate()
*/
#ifndef _di_fll_execute_program_environment_
- extern f_return_status fll_execute_program_environment(const f_string_t program_name, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, int *result);
+ extern f_return_status fll_execute_program_environment(const f_string_t program_name, const f_string_statics_t arguments, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result);
#endif // _di_fll_execute_program_environment_
#ifdef __cplusplus
#endif // !defined(_di_fll_execute_arguments_add_parameter_) || !defined(_di_fll_execute_arguments_add_parameter_set_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_set_)
#if !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_program_)
- f_return_status private_fll_execute_fork(const f_string_t program_path, const f_string_t fixed_arguments[], const bool execute_program, const f_signal_how_t *signals, int *result) {
+ f_return_status private_fll_execute_fork(const f_string_t program_path, const f_string_t fixed_arguments[], const bool program_is, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) {
const pid_t process_id = fork();
return F_status_set_error(F_fork);
}
- // child process.
- if (!process_id) {
+ if (process_id) {
+ if (pipe) {
+ return F_parent;
+ }
+ }
+ else {
if (signals) {
f_signal_set_handle(SIG_BLOCK, &signals->block);
f_signal_set_handle(SIG_UNBLOCK, &signals->block_not);
}
- const int code = execute_program ? execvp(program_path, fixed_arguments) : execv(program_path, fixed_arguments);
+ if (pipe) {
+ if (pipe->input != -1) {
+ dup2(pipe->input, f_type_descriptor_input);
+ }
+
+ if (pipe->output != -1) {
+ dup2(pipe->input, f_type_descriptor_output);
+ }
+
+ if (pipe->error != -1) {
+ dup2(pipe->error, f_type_descriptor_error);
+ }
+ }
+
+ const int code = program_is ? execvp(program_path, fixed_arguments) : execv(program_path, fixed_arguments);
if (result) {
*result = code;
#endif // !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_program_)
#if !defined(_di_fll_execute_path_environment_) || !defined(_di_fll_execute_program_environment_)
- f_return_status private_fll_execute_fork_environment(const f_string_t program_path, const f_string_t fixed_arguments[], const bool execute_program, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, int *result) {
+ f_return_status private_fll_execute_fork_environment(const f_string_t program_path, const f_string_t fixed_arguments[], const bool program_is, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) {
const pid_t process_id = fork();
return F_status_set_error(F_fork);
}
- // child process.
- if (!process_id) {
+ if (process_id) {
+ if (pipe) {
+ return F_parent;
+ }
+ }
+ else {
if (signals) {
f_signal_set_handle(SIG_BLOCK, &signals->block);
f_signal_set_handle(SIG_UNBLOCK, &signals->block_not);
f_environment_set_dynamic(names.array[i], values.array[i], F_true);
} // for
- const int code = execute_program ? execvp(program_path, fixed_arguments) : execv(program_path, fixed_arguments);
+ if (pipe) {
+ if (pipe->input != -1) {
+ dup2(pipe->input, f_type_descriptor_input);
+ }
+
+ if (pipe->output != -1) {
+ dup2(pipe->input, f_type_descriptor_output);
+ }
+
+ if (pipe->error != -1) {
+ dup2(pipe->error, f_type_descriptor_error);
+ }
+ }
+
+ const int code = program_is ? execvp(program_path, fixed_arguments) : execv(program_path, fixed_arguments);
if (result) {
*result = code;
* The part of the path to the program representing the program name to copy from.
* @param fixed_arguments
* A fixed array of strings representing the arguments.
- * @param execute_path
+ * @param program_is
* If TRUE then execvp() is called to perform execution.
* If FALSE then execv() is called to perform execution.
* @param set_signal
* (optional) A pointer to the set of signals.
* Set to 0 to disable.
+ * @param pipe
+ * (optional) A pointer to the set of pipe desciptors (I/O) to be used by the child process.
+ * When a non-zero address, the child process will assign these as the standard I/O file descriptors for piping to/from the parent/child.
+ * For each pipe, setting a value of -1 means to use the default pipe.
+ * Set to 0 to disable.
* @param result
* The code returned after finishing execution of program_path.
*
* @return
* F_none on success.
* F_child on success but this is the child thread.
- * F_fork (with error bit set) on fork failure.
+ * F_parent on success but this is the parent thread and pipe is non-zero (function is not blocking).
* F_failure (with error bit set) on execution failure.
+ * F_fork (with error bit set) on fork failure.
*
* @see execv()
* @see execvp()
* @see fll_execute_program()
*/
#if !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_program_)
- extern f_return_status private_fll_execute_fork(const f_string_t program_path, const f_string_t fixed_arguments[], const bool execute_path, const f_signal_how_t *signals, int *result) f_gcc_attribute_visibility_internal;
+ extern f_return_status private_fll_execute_fork(const f_string_t program_path, const f_string_t fixed_arguments[], const bool program_is, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) f_gcc_attribute_visibility_internal;
#endif // !defined(_di_fll_execute_path_) || !defined(_di_fll_execute_program_)
/**
* The part of the path to the program representing the program name to copy from.
* @param fixed_arguments
* A fixed array of strings representing the arguments.
- * @param execute_program
+ * @param program_is
* If TRUE then execvp() is called to perform execution.
* If FALSE then execv() is called to perform execution.
* @param names
* @param signals
* (optional) A pointer to the set of signals.
* Set to 0 to disable.
+ * @param pipe
+ * (optional) A pointer to the set of pipe desciptors (I/O) to be used by the child process.
+ * When a non-zero address, the child process will assign these as the standard I/O file descriptors for piping to/from the parent/child.
+ * For each pipe, setting a value of -1 means to use the default pipe.
+ * Set to 0 to disable.
* @param result
* The code returned after finishing execution of program_path.
*
* @return
* F_none on success.
* F_child on success but this is the child thread.
- * F_fork (with error bit set) on fork failure.
+ * F_parent on success but this is the parent thread and pipe is non-zero (function is not blocking).
* F_failure (with error bit set) on execution failure.
+ * F_fork (with error bit set) on fork failure.
*
* @see execv()
* @see execvpe()
* @see fll_execute_program_environment()
*/
#if !defined(_di_fll_execute_path_environment_) || !defined(_di_fll_execute_program_environment_)
- extern f_return_status private_fll_execute_fork_environment(const f_string_t program_path, const f_string_t fixed_arguments[], const bool execute_program, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, int *result) f_gcc_attribute_visibility_internal;
+ extern f_return_status private_fll_execute_fork_environment(const f_string_t program_path, const f_string_t fixed_arguments[], const bool program_is, const f_string_statics_t names, const f_string_statics_t values, const f_signal_how_t *signals, f_execute_pipe_t * const pipe, int *result) f_gcc_attribute_visibility_internal;
#endif // !defined(_di_fll_execute_path_environment_) || !defined(_di_fll_execute_program_environment_)
/**
f_memory
f_string
f_environment
+f_execute
f_file
f_path
f_signal
#include <level_0/console.h>
#include <level_0/directory.h>
#include <level_0/environment.h>
+#include <level_0/execute.h>
#include <level_0/file.h>
#include <level_0/iki.h>
#include <level_0/path.h>
f_signal_set_empty(&signals.block);
f_signal_set_fill(&signals.block_not);
- *status = fll_execute_path_environment(path.string, arguments, data_build.environment.names, data_build.environment.values, &signals, &return_code);
+ *status = fll_execute_path_environment(path.string, arguments, data_build.environment.names, data_build.environment.values, &signals, 0, &return_code);
f_macro_string_dynamics_t_delete_simple(arguments);
f_signal_set_empty(&signals.block);
f_signal_set_fill(&signals.block_not);
- *status = fll_execute_program_environment(program.string, arguments, environment.names, environment.values, &signals, &return_code);
+ *status = fll_execute_program_environment(program.string, arguments, environment.names, environment.values, &signals, 0, &return_code);
if (fake_signal_received(data)) {
*status = F_status_set_error(F_signal);
f_signal_set_fill(&signals.block_not);
if (as_shell) {
- status = fll_execute_path_environment(program.string, arguments, data_make->environment.names, data_make->environment.values, &signals, &return_code);
+ status = fll_execute_path_environment(program.string, arguments, data_make->environment.names, data_make->environment.values, &signals, 0, &return_code);
}
else {
- status = fll_execute_program_environment(program.string, arguments, data_make->environment.names, data_make->environment.values, &signals, &return_code);
+ status = fll_execute_program_environment(program.string, arguments, data_make->environment.names, data_make->environment.values, &signals, 0, &return_code);
}
if (status == F_status_set_error(F_signal)) {
f_conversion
f_directory
f_environment
+f_execute
f_fss
f_file
f_iki
parameters.array[4].used = 9;
parameters.array[5].used = 6;
- status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, &return_code);
+ status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, 0, &return_code);
+
+ // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
+ if (status == F_child) {
+ exit(return_code);
+ }
fprintf(data->output.stream, "\n");
fflush(data->output.stream);
parameters.array[4].used = 9;
parameters.array[5].used = 6;
- status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, &return_code);
+ status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, 0, &return_code);
+
+ // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
+ if (status == F_child) {
+ exit(return_code);
+ }
fprintf(data->output.stream, "\n");
fflush(data->output.stream);
parameters.array[2].used = 9;
parameters.array[3].used = 6;
- status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, &return_code);
+ status = fll_execute_program((f_string_t) firewall_tool_iptables, parameters, 0, 0, &return_code);
+
+ // immediately exit child process, @todo this may require additional memory deallocation and relating changes.
+ if (status == F_child) {
+ exit(return_code);
+ }
fprintf(data->output.stream, "\n");
fflush(data->output.stream);
#include <level_0/utf.h>
#include <level_0/console.h>
#include <level_0/directory.h>
+#include <level_0/execute.h>
#include <level_0/file.h>
#include <level_0/pipe.h>
#include <level_0/print.h>
fprintf(f_type_debug, "\n");
}
- status = fll_execute_program((f_string_t) current_tool, arguments, 0, &return_code);
+ status = fll_execute_program((f_string_t) current_tool, arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
fprintf(f_type_debug, "\n");
}
- status = fll_execute_program(current_tool, arguments, 0, &return_code);
+ status = fll_execute_program(current_tool, arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
}
tool = firewall_program_iptables;
- status = fll_execute_program((f_string_t) firewall_tool_iptables, arguments, 0, &return_code);
+ status = fll_execute_program((f_string_t) firewall_tool_iptables, arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
}
tool = firewall_program_ip6tables;
- status = fll_execute_program((f_string_t) firewall_tool_ip6tables, arguments, 0, &return_code);
+ status = fll_execute_program((f_string_t) firewall_tool_ip6tables, arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
fprintf(f_type_debug, "\n");
}
- status = fll_execute_program(tools[i], arguments, 0, &return_code);
+ status = fll_execute_program(tools[i], arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
fprintf(f_type_debug, "\n");
}
- status = fll_execute_program(tools[i], arguments, 0, &return_code);
+ status = fll_execute_program(tools[i], arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
fprintf(f_type_debug, "\n");
}
- status = fll_execute_program(tools[j], arguments, 0, &return_code);
+ status = fll_execute_program(tools[j], arguments, 0, 0, &return_code);
// immediately exit child process, @todo this may require additional memory deallocation and relating changes.
if (status == F_child) {
f_console
f_directory
f_environment
+f_execute
f_file
f_fss
f_path
// fll-2 includes
#include <level_2/error.h>
-#include <level_2/execute.h>
#include <level_2/file.h>
#include <level_2/fss_basic_list.h>
#include <level_2/program.h>
fl_status
fl_string
fll_error
-fll_execute
fll_file
fll_fss
fll_program
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_print -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_fss -lfl_print -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library fss_basic_list_read.c private-fss_basic_list_read.c
fl_status
fl_string
fll_error
-fll_execute
fll_file
fll_fss
fll_program
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library fss_basic_list_write.c private-fss_basic_list_write.c
// fll-2 includes
#include <level_2/error.h>
-#include <level_2/execute.h>
#include <level_2/file.h>
#include <level_2/fss_basic.h>
#include <level_2/program.h>
fl_status
fl_string
fll_error
-fll_execute
fll_file
fll_fss
fll_program
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_print -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_fss -lfl_print -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library fss_basic_read.c private-fss_basic_read.c
fl_status
fl_string
fll_error
-fll_execute
fll_file
fll_fss
fll_program
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library fss_basic_write.c private-fss_basic_write.c
// fll-2 includes
#include <level_2/error.h>
-#include <level_2/execute.h>
#include <level_2/file.h>
#include <level_2/fss_embedded_list.h>
#include <level_2/program.h>
fl_status
fl_string
fll_error
-fll_execute
fll_file
fll_fss
fll_program
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_print -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_fss -lfl_print -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library fss_embedded_list_read.c private-fss_embedded_list_read.c
fl_status
fl_string
fll_error
-fll_execute
fll_file
fll_fss
fll_program
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library fss_embedded_list_write.c private-fss_embedded_list_write.c
// fll-2 includes
#include <level_2/error.h>
-#include <level_2/execute.h>
#include <level_2/file.h>
#include <level_2/fss_extended_list.h>
#include <level_2/program.h>
fl_status
fl_string
fll_error
-fll_execute
fll_file
fll_fss
fll_program
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_print -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_fss -lfl_print -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library fss_extended_list_read.c private-fss_extended_list_read.c
fl_status
fl_string
fll_error
-fll_execute
fll_file
fll_fss
fll_program
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library fss_extended_list_write.c private-fss_extended_list_write.c
// fll-2 includes
#include <level_2/error.h>
-#include <level_2/execute.h>
#include <level_2/file.h>
#include <level_2/fss_extended.h>
#include <level_2/program.h>
fl_status
fl_string
fll_error
-fll_execute
fll_file
fll_fss
fll_program
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_print -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_fss -lfl_print -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library fss_extended_read.c private-fss_extended_read.c
fl_status
fl_string
fll_error
-fll_execute
fll_file
fll_fss
fll_program
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_program -lfl_color -lfl_conversion -lfl_directory -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library fss_extended_write.c private-fss_extended_write.c
fl_string
fl_utf
fll_error
-fll_execute
fll_file
fll_fss
fll_program
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_program -lfll_status -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_status -lfl_string -lfl_utf -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
+build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_program -lfll_status -lfl_color -lfl_console -lfl_conversion -lfl_directory -lfl_fss -lfl_status -lfl_string -lfl_utf -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library fss_status_code.c private-fss_status_code.c