build_libraries -lc -lcap
build_libraries-level
build_libraries-level_threadless
-build_sources_library account.c private-account.c capability.c color.c color-common.c console.c console-common.c control_group.c control_group-common.c conversion.c conversion-common.c private-conversion.c directory.c private-directory.c environment.c private-environment.c file.c file-common.c private-file.c fss.c private-fss.c fss-common.c fss_named.c fss_nest.c fss_set.c iki.c iki-common.c private-iki.c limit.c memory.c memory_structure.c private-memory.c path.c path-common.c private-path.c pipe.c print.c print-common.c private-print.c serialize.c serialize-common.c private-serialize.c signal.c socket.c string.c string-common.c private-string.c string_dynamic.c string_map.c string_quantity.c string_range.c string_triple.c type_array.c private-type_array.c utf.c utf-common.c private-utf.c utf_dynamic.c utf_map.c utf_triple.c
+build_sources_library account.c private-account.c capability.c color.c color-common.c console.c console-common.c control_group.c control_group-common.c conversion.c conversion-common.c private-conversion.c directory.c private-directory.c environment.c private-environment.c execute.c file.c file-common.c private-file.c fss.c private-fss.c fss-common.c fss_named.c fss_nest.c fss_set.c iki.c iki-common.c private-iki.c limit.c memory.c memory_structure.c private-memory.c path.c path-common.c private-path.c pipe.c print.c print-common.c private-print.c serialize.c serialize-common.c private-serialize.c signal.c socket.c string.c string-common.c private-string.c string_dynamic.c string_map.c string_quantity.c string_range.c string_triple.c type_array.c private-type_array.c utf.c utf-common.c private-utf.c utf_dynamic.c utf_map.c utf_triple.c
build_sources_library-level thread.c private-thread.c
build_sources_program
build_sources_headers account.h account-common.h capability.h capability-common.h color.h color-common.h console.h console-common.h control_group.h control_group-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 limit.h limit-common.h memory.h memory_structure.h memory-common.h path.h path-common.h pipe.h print.h print-common.h serialize.h serialize-common.h signal.h signal-common.h socket.h socket-common.h status.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 type_array-common.h utf.h utf-common.h utf_dynamic.h utf_map.h utf_triple.h
build_libraries -lc -lcap
build_libraries-monolithic
build_libraries-monolithic_threadless
-build_sources_library level_0/account.c level_0/private-account.c level_0/capability.c level_0/color.c level_0/color-common.c level_0/console.c level_0/console-common.c level_0/control_group.c level_0/control_group-common.c level_0/conversion.c level_0/conversion-common.c level_0/private-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/file-common.c level_0/private-file.c level_0/fss.c level_0/private-fss.c level_0/fss-common.c level_0/fss_named.c level_0/fss_nest.c level_0/fss_set.c level_0/iki.c level_0/iki-common.c level_0/private-iki.c level_0/limit.c level_0/memory.c level_0/memory_structure.c level_0/private-memory.c level_0/path.c level_0/path-common.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/print-common.c level_0/private-print.c level_0/serialize.c level_0/serialize-common.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/string.c level_0/string-common.c level_0/private-string.c level_0/string_dynamic.c level_0/string_map.c level_0/string_quantity.c level_0/string_range.c level_0/string_triple.c level_0/type_array.c level_0/private-type_array.c level_0/utf.c level_0/utf-common.c level_0/private-utf.c level_0/utf_dynamic.c level_0/utf_map.c level_0/utf_triple.c level_1/console.c level_1/control_group.c level_1/conversion.c level_1/private-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/signal.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_1/private-utf_file.c level_2/control_group.c level_2/error.c level_2/error-common.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/print.c level_2/program.c level_2/status.c
+build_sources_library level_0/account.c level_0/private-account.c level_0/capability.c level_0/color.c level_0/color-common.c level_0/console.c level_0/console-common.c level_0/control_group.c level_0/control_group-common.c level_0/conversion.c level_0/conversion-common.c level_0/private-conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/execute.c level_0/file.c level_0/file-common.c level_0/private-file.c level_0/fss.c level_0/private-fss.c level_0/fss-common.c level_0/fss_named.c level_0/fss_nest.c level_0/fss_set.c level_0/iki.c level_0/iki-common.c level_0/private-iki.c level_0/limit.c level_0/memory.c level_0/memory_structure.c level_0/private-memory.c level_0/path.c level_0/path-common.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/print-common.c level_0/private-print.c level_0/serialize.c level_0/serialize-common.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/string.c level_0/string-common.c level_0/private-string.c level_0/string_dynamic.c level_0/string_map.c level_0/string_quantity.c level_0/string_range.c level_0/string_triple.c level_0/type_array.c level_0/private-type_array.c level_0/utf.c level_0/utf-common.c level_0/private-utf.c level_0/utf_dynamic.c level_0/utf_map.c level_0/utf_triple.c level_1/console.c level_1/control_group.c level_1/conversion.c level_1/private-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/signal.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_1/private-utf_file.c level_2/control_group.c level_2/error.c level_2/error-common.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/print.c level_2/program.c level_2/status.c
build_sources_library-monolithic level_0/thread.c level_0/private-thread.c
build_sources_program
build_sources_headers level_0/account.h level_0/account-common.h level_0/capability.h level_0/capability-common.h level_0/color.h level_0/color-common.h level_0/console.h level_0/console-common.h level_0/control_group.h level_0/control_group-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/limit.h level_0/limit-common.h level_0/memory.h level_0/memory_structure.h level_0/memory-common.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/print-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/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/type_array-common.h level_0/utf.h level_0/utf-common.h level_0/utf_dynamic.h level_0/utf_map.h level_0/utf_triple.h level_1/console.h level_1/control_group.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/execute.h level_1/execute-common.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_status.h level_1/iki.h level_1/print.h level_1/signal.h level_1/signal-common.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/control_group.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/print.h level_2/program.h level_2/status.h
#endif
/**
+ * All special case execute codes.
+ *
+ * Only the lower 8-bits are available for return codes and so this is a special small set of status codes to be returned by a child process for a parent process to get.
+ * A waitpid() call can be used within the parent to get these codes if the child returns with these codes.
+ *
+ * All codes, except 0, represent an error.
+ *
+ * F_execute_code_last, this is intended to designate the last code provided by level_0 execute project.
+ * All code sets started by another project must start at this number + 1 with a code start map.
+ *
+ * Warning: F_execute and F_execute_not are F_status_t status codes and are not F_execute_codes.
+ * The F_execute_off is the execute code equivalent of F_execute_not.
+ */
+#ifndef _di_F_execute_codes_
+ enum {
+ F_execute_none = 0,
+ F_execute_access,
+ F_execute_buffer,
+ F_execute_busy,
+ F_execute_capability,
+ F_execute_control_group,
+ F_execute_child,
+ F_execute_directory_not,
+ F_execute_failure,
+ F_execute_file_found_not,
+ F_execute_file_type_directory,
+ F_execute_group,
+ F_execute_input_output,
+ F_execute_limit,
+ F_execute_loop,
+ F_execute_memory_not,
+ F_execute_name_not,
+ F_execute_nice,
+ F_execute_off,
+ F_execute_parameter,
+ F_execute_pipe,
+ F_execute_processor,
+ F_execute_prohibited,
+ F_execute_resource_not,
+ F_execute_schedule,
+ F_execute_too_large,
+ F_execute_user,
+ F_execute_valid_not,
+
+ // Required.
+ F_execute_code_last,
+ }; // enum
+#endif // _di_F_execute_codes_
+
+/**
* A structure representing a scheduler and its parameters for execution.
*
* @todo move this into a f_scheduler project.
scheduler.priority = 0;
#endif // _di_f_execute_scheduler_t_
+/**
+ * A structure representing either a pid_t or an f_status_t.
+ *
+ * This is intended to be used for the execute functions that may store a pid_t in a parent process but a f_status_t in a child process.
+ * These would use the same variable, but it may be stored differently.
+ *
+ * status: The status code, generally used by the child process.
+ * pid: The process id (PID) of the child process, generally used by the parent process;
+ */
+#ifndef _di_f_execute_result_t_
+ typedef union {
+ int status;
+ pid_t pid;
+ } f_execute_result_t;
+
+ #define f_execute_result_t_initialize { 0 }
+
+ #define f_execute_result_t_clear(execute_result) \
+ execute_result.status = 0; \
+ execute_result.pid = 0;
+#endif // _di_f_execute_result_t_
+
#ifdef __cplusplus
} // extern "C"
#endif
--- /dev/null
+#include "execute.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_f_execute_status_from_status_
+ uint8_t f_execute_status_from_status(f_status_t status) {
+
+ if (F_status_set_fine(status) == F_none) {
+ return F_execute_none;
+ }
+
+ if (F_status_set_fine(status) == F_access) {
+ return F_execute_access;
+ }
+
+ if (F_status_set_fine(status) == F_buffer) {
+ return F_execute_buffer;
+ }
+
+ if (F_status_set_fine(status) == F_busy) {
+ return F_execute_busy;
+ }
+
+ if (F_status_set_fine(status) == F_capability) {
+ return F_execute_capability;
+ }
+
+ if (F_status_set_fine(status) == F_control_group) {
+ return F_execute_control_group;
+ }
+
+ if (F_status_set_fine(status) == F_child) {
+ return F_execute_child;
+ }
+
+ if (F_status_set_fine(status) == F_directory_not) {
+ return F_execute_directory_not;
+ }
+
+ if (F_status_set_fine(status) == F_execute_not) {
+ return F_execute_off;
+ }
+
+ if (F_status_set_fine(status) == F_failure) {
+ return F_execute_failure;
+ }
+
+ if (F_status_set_fine(status) == F_file_found_not) {
+ return F_execute_file_found_not;
+ }
+
+ if (F_status_set_fine(status) == F_file_type_directory) {
+ return F_execute_file_type_directory;
+ }
+
+ if (F_status_set_fine(status) == F_group) {
+ return F_execute_group;
+ }
+
+ if (F_status_set_fine(status) == F_input_output) {
+ return F_execute_input_output;
+ }
+
+ if (F_status_set_fine(status) == F_limit) {
+ return F_execute_limit;
+ }
+
+ if (F_status_set_fine(status) == F_loop) {
+ return F_execute_loop;
+ }
+
+ if (F_status_set_fine(status) == F_memory_not) {
+ return F_execute_memory_not;
+ }
+
+ if (F_status_set_fine(status) == F_name_not) {
+ return F_execute_name_not;
+ }
+
+ if (F_status_set_fine(status) == F_nice) {
+ return F_execute_nice;
+ }
+
+ if (F_status_set_fine(status) == F_parameter) {
+ return F_execute_parameter;
+ }
+
+ if (F_status_set_fine(status) == F_pipe) {
+ return F_execute_pipe;
+ }
+
+ if (F_status_set_fine(status) == F_processor) {
+ return F_execute_processor;
+ }
+
+ if (F_status_set_fine(status) == F_prohibited) {
+ return F_execute_prohibited;
+ }
+
+ if (F_status_set_fine(status) == F_resource_not) {
+ return F_execute_resource_not;
+ }
+
+ if (F_status_set_fine(status) == F_schedule) {
+ return F_execute_schedule;
+ }
+
+ if (F_status_set_fine(status) == F_too_large) {
+ return F_execute_too_large;
+ }
+
+ if (F_status_set_fine(status) == F_user) {
+ return F_execute_user;
+ }
+
+ if (F_status_set_fine(status) == F_valid_not) {
+ return F_execute_valid_not;
+ }
+
+ return F_execute_code_last;
+ }
+#endif // _di_f_execute_status_from_status_
+
+#ifndef _di_f_execute_status_to_status_
+ f_status_t f_execute_status_to_status(uint8_t status) {
+
+ if (status == F_execute_none) {
+ return F_none;
+ }
+
+ if (status == F_execute_access) {
+ return F_access;
+ }
+
+ if (status == F_execute_buffer) {
+ return F_buffer;
+ }
+
+ if (status == F_execute_busy) {
+ return F_busy;
+ }
+
+ if (status == F_execute_capability) {
+ return F_capability;
+ }
+
+ if (status == F_execute_control_group) {
+ return F_control_group;
+ }
+
+ if (status == F_execute_child) {
+ return F_child;
+ }
+
+ if (status == F_execute_directory_not) {
+ return F_directory_not;
+ }
+
+ if (status == F_execute_failure) {
+ return F_failure;
+ }
+
+ if (status == F_execute_file_found_not) {
+ return F_file_found_not;
+ }
+
+ if (status == F_execute_file_type_directory) {
+ return F_file_type_directory;
+ }
+
+ if (status == F_execute_group) {
+ return F_group;
+ }
+
+ if (status == F_execute_input_output) {
+ return F_input_output;
+ }
+
+ if (status == F_execute_limit) {
+ return F_limit;
+ }
+
+ if (status == F_execute_loop) {
+ return F_loop;
+ }
+
+ if (status == F_execute_memory_not) {
+ return F_memory_not;
+ }
+
+ if (status == F_execute_name_not) {
+ return F_name_not;
+ }
+
+ if (status == F_execute_nice) {
+ return F_nice;
+ }
+
+ if (status == F_execute_off) {
+ return F_execute_not;
+ }
+
+ if (status == F_execute_parameter) {
+ return F_parameter;
+ }
+
+ if (status == F_execute_pipe) {
+ return F_pipe;
+ }
+
+ if (status == F_execute_processor) {
+ return F_processor;
+ }
+
+ if (status == F_execute_prohibited) {
+ return F_prohibited;
+ }
+
+ if (status == F_execute_resource_not) {
+ return F_resource_not;
+ }
+
+ if (status == F_execute_schedule) {
+ return F_schedule;
+ }
+
+ if (status == F_execute_too_large) {
+ return F_too_large;
+ }
+
+ if (status == F_execute_user) {
+ return F_user;
+ }
+
+ if (status == F_execute_valid_not) {
+ return F_valid_not;
+ }
+
+ return F_status_set_error(F_known_not);
+ }
+#endif // _di_f_execute_status_to_status_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
extern "C" {
#endif
+/**
+ * Convert from F_status_t to execute status.
+ *
+ * @param status
+ * The status to convert from.
+ * The execute status does not support flags and so flags on this are ignored.
+ *
+ * @return
+ * The appropriate execute status code is returned on match.
+ *
+ * F_execute_code_last is returned when there are no matching execute states.
+ */
+#ifndef _di_f_execute_status_from_status_
+ extern uint8_t f_execute_status_from_status(f_status_t status);
+#endif // _di_f_execute_status_from_status_
+
+/**
+ * Convert execute status to F_status_t.
+ *
+ * @param status
+ * An execute status number to convert.
+ * The execute status has no flags and is only 8-bits wide.
+ *
+ * @return
+ * The appropriate status code is returned on match (no bits, error or otherwise are set).
+ *
+ * F_known_not (with error bit) if the given number has no known execute state to convert.
+ */
+#ifndef _di_f_execute_status_to_status_
+ extern f_status_t f_execute_status_to_status(uint8_t status);
+#endif // _di_f_execute_status_to_status_
+
#ifdef __cplusplus
} // extern "C"
#endif
build_language c
build_libraries -lc
build_libraries-individual -lf_memory -lf_string
-build_sources_library
+build_sources_library execute.c
build_sources_program
build_sources_headers execute.h execute-common.h
build_sources_script
F_thread_not,
F_time,
F_time_not,
+ F_too_large,
+ F_too_small,
F_user,
F_user_not,
F_utf,
#endif // _di_F_status_access_
// Required.
- F_status_code_last
+ F_status_code_last,
}; // enum
#endif // _di_F_status_codes_
build_indexer ar
build_language c
build_libraries -lc -lcap
-build_libraries-individual -lf_capability -lf_limit -lf_memory -lf_signal -lf_string -lf_type_array
+build_libraries-individual -lf_capability -lf_execute -lf_limit -lf_memory -lf_signal -lf_string -lf_type_array
build_sources_library
build_sources_program
build_sources_headers execute.h execute-common.h
case F_time_not:
*string = FL_status_string_time_not;
break;
+ case F_too_large:
+ *string = FL_status_string_too_large;
+ break;
+ case F_too_small:
+ *string = FL_status_string_too_small;
+ break;
case F_known:
*string = FL_status_string_known;
break;
#define FL_status_string_thread_not "F_thread_not"
#define FL_status_string_time "F_time"
#define FL_status_string_time_not "F_time_not"
+ #define FL_status_string_too_large "F_too_large"
+ #define FL_status_string_too_small "F_too_small"
#define FL_status_string_success "F_success"
#define FL_status_string_success_not "F_success_not"
#define FL_status_string_supported "F_supported"
#define FL_status_string_thread_not_length 12
#define FL_status_string_time_length 6
#define FL_status_string_time_not_length 10
+ #define FL_status_string_too_large_length 11
+ #define FL_status_string_too_small_length 11
#define FL_status_string_user_length 6
#define FL_status_string_user_not_length 10
#define FL_status_string_utf_length 5
}
// generally this does not return, but in some cases (such as with scripts) this does return so handle the results.
+ if (code < 0) {
+ if (errno == EACCES) code = F_execute_access;
+ else if (errno == E2BIG) code = F_execute_too_large;
+ else if (errno == EAGAIN) code = F_execute_resource_not;
+ else if (errno == EFAULT) code = F_execute_buffer;
+ else if (errno == EINVAL) code = F_execute_parameter;
+ else if (errno == EIO) code = F_execute_input_output;
+ else if (errno == EISDIR) code = F_execute_file_type_directory;
+ else if (errno == EIO) code = F_execute_input_output;
+ else if (errno == ELIBBAD) code = F_execute_valid_not;
+ else if (errno == ELOOP) code = F_execute_loop;
+ else if (errno == EMFILE) code = F_execute_resource_not;
+ else if (errno == ENAMETOOLONG) code = F_execute_name_not;
+ else if (errno == ENFILE) code = F_execute_resource_not;
+ else if (errno == ENOENT) code = F_execute_file_found_not;
+ else if (errno == ENOEXEC) code = F_execute_off;
+ else if (errno == ENOMEM) code = F_execute_memory_not;
+ else if (errno == ENOTDIR) code = F_execute_directory_not;
+ else if (errno == EPERM) code = F_execute_prohibited;
+ else if (errno == ETXTBSY) code = F_execute_busy;
+ else code = F_execute_failure;
+ }
+ else {
+ code = 0;
+ }
+
if (result) {
- *result = code;
+ int *r = (int *) result;
+ *r = code;
}
if (option & fl_execute_parameter_option_exit) {
* @param as
* (optional) This and most of its fields are optional and are disabled when set to NULL.
* @param result
- * (optional) The code returned after finishing execution of program.
+ * (optional) The execute status code returned after finishing or attempting to finish execution of program.
* When fl_execute_parameter_option_return is passed via parameter.option, then this instead stores the child process id (PID).
* This is should be of (int *) except when fl_execute_parameter_option_return this should instead be (pid_t *).
* Set to NULL to not use.
errno = 0;
if (nice(*as.nice) == -1 && errno == -1) {
- *result = -1;
-
if (parameter && parameter->option & fl_execute_parameter_option_exit) {
- exit(*result);
+ exit(F_execute_nice);
}
+ *result = F_execute_nice;
return F_status_set_error(F_nice);
}
}
const f_status_t status = f_capability_process_set(as.capability);
if (F_status_is_error(status) && F_status_set_fine(status) != F_supported_not) {
- *result = -1;
-
if (parameter && parameter->option & fl_execute_parameter_option_exit) {
- exit(*result);
+ exit(F_execute_capability);
}
+ *result = F_execute_capability;
return F_status_set_error(F_capability);
}
}
if (as.id_groups) {
if (setgroups(as.id_groups->used, (const gid_t *) as.id_groups->array) == -1) {
- *result = -1;
if (parameter && parameter->option & fl_execute_parameter_option_exit) {
- exit(*result);
+ exit(F_execute_group);
}
+ *result = F_execute_group;
return F_status_set_error(F_group);
}
}
if (as.id_group) {
if (setgid(*as.id_group) == -1) {
- *result = -1;
-
if (parameter && parameter->option & fl_execute_parameter_option_exit) {
- exit(*result);
+ exit(F_execute_group);
}
+ *result = F_execute_group;
return F_status_set_error(F_group);
}
}
if (as.id_user) {
if (setuid(*as.id_user) == -1) {
- *result = -1;
-
if (parameter && parameter->option & fl_execute_parameter_option_exit) {
- exit(*result);
+ exit(F_execute_user);
}
+ *result = F_execute_user;
return F_status_set_error(F_user);
}
}
if (result) {
int *r = (int *) result;
- *r = -1;
+ *r = F_execute_failure;
}
if (parameter && parameter->option & fl_execute_parameter_option_exit) {
- exit(-1);
+ exit(F_execute_failure);
}
return F_child;
if (F_status_is_error(status)) return status;
}
- const int code = direct ? execv(program, fixed_arguments) : execvp(program, fixed_arguments);
+ int code = direct ? execv(program, fixed_arguments) : execvp(program, fixed_arguments);
+
+ if (code < 0) {
+ if (errno == EACCES) code = F_execute_access;
+ else if (errno == E2BIG) code = F_execute_too_large;
+ else if (errno == EAGAIN) code = F_execute_resource_not;
+ else if (errno == EFAULT) code = F_execute_buffer;
+ else if (errno == EINVAL) code = F_execute_parameter;
+ else if (errno == EIO) code = F_execute_input_output;
+ else if (errno == EISDIR) code = F_execute_file_type_directory;
+ else if (errno == EIO) code = F_execute_input_output;
+ else if (errno == ELIBBAD) code = F_execute_valid_not;
+ else if (errno == ELOOP) code = F_execute_loop;
+ else if (errno == EMFILE) code = F_execute_resource_not;
+ else if (errno == ENAMETOOLONG) code = F_execute_name_not;
+ else if (errno == ENFILE) code = F_execute_resource_not;
+ else if (errno == ENOENT) code = F_execute_file_found_not;
+ else if (errno == ENOEXEC) code = F_execute_off;
+ else if (errno == ENOMEM) code = F_execute_memory_not;
+ else if (errno == ENOTDIR) code = F_execute_directory_not;
+ else if (errno == EPERM) code = F_execute_prohibited;
+ else if (errno == ETXTBSY) code = F_execute_busy;
+ else code = F_execute_failure;
+ }
+ else {
+ code = 0;
+ }
if (result) {
int *r = (int *) result;
close(descriptors[0]);
if (result) {
- int *r = (int *) result;
- *r = -1;
+ f_status_t *r = (f_status_t *) result;
+ *r = F_status_set_error(F_failure);
}
if (parameter && parameter->option & fl_execute_parameter_option_exit) {
if (F_status_is_error(status)) return status;
}
- const int code = direct ? execv(program, fixed_arguments) : execvp(program, fixed_arguments);
+ int code = direct ? execv(program, fixed_arguments) : execvp(program, fixed_arguments);
// close the write pipe for the child when done.
close(descriptors[0]);
+ if (code < 0) {
+ if (errno == EACCES) code = F_execute_access;
+ else if (errno == E2BIG) code = F_execute_too_large;
+ else if (errno == EAGAIN) code = F_execute_resource_not;
+ else if (errno == EFAULT) code = F_execute_buffer;
+ else if (errno == EINVAL) code = F_execute_parameter;
+ else if (errno == EIO) code = F_execute_input_output;
+ else if (errno == EISDIR) code = F_execute_file_type_directory;
+ else if (errno == EIO) code = F_execute_input_output;
+ else if (errno == ELIBBAD) code = F_execute_valid_not;
+ else if (errno == ELOOP) code = F_execute_loop;
+ else if (errno == EMFILE) code = F_execute_resource_not;
+ else if (errno == ENAMETOOLONG) code = F_execute_name_not;
+ else if (errno == ENFILE) code = F_execute_resource_not;
+ else if (errno == ENOENT) code = F_execute_file_found_not;
+ else if (errno == ENOEXEC) code = F_execute_off;
+ else if (errno == ENOMEM) code = F_execute_memory_not;
+ else if (errno == ENOTDIR) code = F_execute_directory_not;
+ else if (errno == EPERM) code = F_execute_prohibited;
+ else if (errno == ETXTBSY) code = F_execute_busy;
+ else code = F_execute_failure;
+ }
+ else {
+ code = 0;
+ }
+
+ if (result) {
+ int *r = (int *) result;
+ *r = code;
+ }
+
if (result) {
int *r = (int *) result;
*r = code;
* @param as
* (optional) This and most of its fields are optional and are disabled when set to NULL.
* @param result
- * (optional) The code returned after finishing execution of program.
+ * (optional) The execute status code returned after finishing or attempting to finish execution of program.
* When fl_execute_parameter_option_return is passed via parameter.option, then this instead stores the child process id (PID).
* This is should be of (int *) except when fl_execute_parameter_option_return this should instead be (pid_t *).
* Set to NULL to not use.
* @param as
* (optional) This and most of its fields are optional and are disabled when set to NULL.
* @param result
- * (optional) The code returned after finishing execution of program.
+ * (optional) The execute status code returned after finishing or attempting to finish execution of program.
* When fl_execute_parameter_option_return is passed via parameter.option, then this instead stores the child process id (PID).
* This is should be of (int *) except when fl_execute_parameter_option_return this should instead be (pid_t *).
* Set to NULL to not use.
build_indexer ar
build_language c
build_libraries -lc -lcap
-build_libraries-individual -lfl_control_group -lfl_environment -lf_account -lf_capability -lf_control_group -lf_environment -lf_file -lf_limit -lf_memory -lf_path -lf_signal -lf_string -lf_thread -lf_type_array -lf_utf
-build_libraries-individual_threadless -lfl_control_group -lfl_environment -lf_account -lf_capability -lf_control_group -lf_environment -lf_file -lf_limit -lf_memory -lf_path -lf_signal -lf_string -lf_type_array -lf_utf
+build_libraries-individual -lfl_control_group -lfl_environment -lf_account -lf_capability -lf_control_group -lf_environment -lf_execute -lf_file -lf_limit -lf_memory -lf_path -lf_signal -lf_string -lf_thread -lf_type_array -lf_utf
+build_libraries-individual_threadless -lfl_control_group -lfl_environment -lf_account -lf_capability -lf_control_group -lf_environment -lf_execute -lf_file -lf_limit -lf_memory -lf_path -lf_signal -lf_string -lf_type_array -lf_utf
build_sources_library execute.c private-execute.c
build_sources_program
build_sources_headers execute.h
return F_none;
}
+ if (fl_string_compare(string, FL_status_string_too_large, length, FL_status_string_too_large_length) == F_equal_to) {
+ *code = F_too_large;
+
+ return F_none;
+ }
+
+ if (fl_string_compare(string, FL_status_string_too_small, length, FL_status_string_too_small_length) == F_equal_to) {
+ *code = F_too_small;
+
+ return F_none;
+ }
+
if (fl_string_compare(string, FL_status_string_user, length, FL_status_string_user_length) == F_equal_to) {
*code = F_user;
}
#endif // _di_controller_time_
+#ifndef _di_controller_time_micro_
+ struct timespec controller_time_micro(const f_number_unsigned_t microseconds) {
+
+ struct timespec time;
+ time.tv_sec = microseconds / 1000;
+ time.tv_nsec = (time.tv_sec ? microseconds - time.tv_sec : microseconds) * 1000;
+
+ return time;
+ }
+#endif // _di_controller_time_micro_
+
#ifdef __cplusplus
} // extern "C"
#endif
* - control: The process is started from a control operation.
*
* id: The ID of this process relative to the processes array.
+ * result: The last return code from an execution of a process.
* status: The last execution status of the process.
* state: The state of the process.
* action: The action being performed.
uint8_t options;
uint8_t type;
+ int result;
+
f_thread_id_t id_thread;
f_thread_lock_t lock;
f_thread_lock_t active;
0, \
0, \
0, \
+ 0, \
f_thread_id_t_initialize, \
f_thread_lock_t_initialize, \
f_thread_lock_t_initialize, \
void controller_time(const time_t seconds, const long nanoseconds, struct timespec *time) f_attribute_visibility_internal;
#endif // _di_controller_time_
+/**
+ * Convert microseconds to nanoseconds.
+ *
+ * @param microseconds
+ * The number of microseconds.
+ *
+ * @return
+ * A time structure suitable for passing to nanosleep() and similar functions.
+ */
+#ifndef _di_controller_time_micro_
+ extern struct timespec controller_time_micro(const f_number_unsigned_t microseconds) f_attribute_visibility_internal;
+#endif // _di_controller_time_micro_
+
#ifdef __cplusplus
} // extern "C"
#endif
int result = 0;
- status = fll_execute_into(0, entry_action->parameters, fl_execute_parameter_option_path, 0, &result);
+ status = fll_execute_into(0, entry_action->parameters, fl_execute_parameter_option_path, 0, (void *) &result);
if (F_status_is_error(status)) {
if (F_status_set_fine(status) == F_file_found_not) {
}
#endif // _di_controller_rule_parameters_read_
+#ifndef _di_controller_rule_action_type_to_action_execute_type_
+ uint8_t controller_rule_action_type_to_action_execute_type(const uint8_t type) {
+
+ if (type == controller_rule_action_type_freeze) {
+ return controller_rule_action_type_execute_freeze;
+ }
+
+ if (type == controller_rule_action_type_kill) {
+ return controller_rule_action_type_execute_kill;
+ }
+
+ if (type == controller_rule_action_type_pause) {
+ return controller_rule_action_type_execute_pause;
+ }
+
+ if (type == controller_rule_action_type_reload) {
+ return controller_rule_action_type_execute_reload;
+ }
+
+ if (type == controller_rule_action_type_restart) {
+ return controller_rule_action_type_execute_restart;
+ }
+
+ if (type == controller_rule_action_type_resume) {
+ return controller_rule_action_type_execute_resume;
+ }
+
+ if (type == controller_rule_action_type_start) {
+ return controller_rule_action_type_execute_start;
+ }
+
+ if (type == controller_rule_action_type_stop) {
+ return controller_rule_action_type_execute_stop;
+ }
+
+ if (type == controller_rule_action_type_thaw) {
+ return controller_rule_action_type_execute_thaw;
+ }
+
+ return controller_rule_action_type_execute__enum_size;
+ }
+#endif // _di_controller_rule_action_type_to_action_execute_type_
+
#ifndef _di_controller_rule_action_type_name_
f_string_static_t controller_rule_action_type_name(const uint8_t type) {
}
#endif // _di_controller_rule_action_type_name_
+#ifndef _di_controller_rule_action_type_execute_name_
+ f_string_static_t controller_rule_action_type_execute_name(const uint8_t type) {
+
+ f_string_static_t buffer = f_string_static_t_initialize;
+
+ switch (type) {
+ case controller_rule_action_type_execute_freeze:
+ buffer.string = controller_string_freeze_s;
+ buffer.used = controller_string_freeze_length;
+ break;
+
+ case controller_rule_action_type_execute_kill:
+ buffer.string = controller_string_kill_s;
+ buffer.used = controller_string_kill_length;
+ break;
+
+ case controller_rule_action_type_execute_pause:
+ buffer.string = controller_string_pause_s;
+ buffer.used = controller_string_pause_length;
+ break;
+
+ case controller_rule_action_type_execute_reload:
+ buffer.string = controller_string_reload_s;
+ buffer.used = controller_string_reload_length;
+ break;
+
+ case controller_rule_action_type_execute_restart:
+ buffer.string = controller_string_restart_s;
+ buffer.used = controller_string_restart_length;
+ break;
+
+ case controller_rule_action_type_execute_resume:
+ buffer.string = controller_string_resume_s;
+ buffer.used = controller_string_resume_length;
+ break;
+
+ case controller_rule_action_type_execute_start:
+ buffer.string = controller_string_start_s;
+ buffer.used = controller_string_start_length;
+ break;
+
+ case controller_rule_action_type_execute_stop:
+ buffer.string = controller_string_stop_s;
+ buffer.used = controller_string_stop_length;
+ break;
+
+ case controller_rule_action_type_execute_thaw:
+ buffer.string = controller_string_thaw_s;
+ buffer.used = controller_string_thaw_length;
+ break;
+ }
+
+ buffer.size = buffer.used;
+
+ return buffer;
+ }
+#endif // _di_controller_rule_action_type_execute_name_
+
#ifndef _di_controller_rule_actions_increase_by_
f_status_t controller_rule_actions_increase_by(const f_array_length_t amount, controller_rule_actions_t *actions) {
fl_print_format("%['.%]%c", print.to.stream, print.context, print.context, f_string_eol_s[0]);
}
else if (code) {
- fl_print_format("%[' failed with the exit code %]", print.to.stream, print.context, print.context);
- fl_print_format("%[%i%]", print.to.stream, print.notable, code, print.notable);
- fl_print_format("%[.%]%c", print.to.stream, print.context, print.context, f_string_eol_s[0]);
+ if (code == F_execute_file_found_not) {
+ fl_print_format("%[' could not be executed because it was not found.%]%c", print.to.stream, print.context, print.context, f_string_eol_s[0]);
+ }
+ else {
+ // @todo improve reporting of all known status codes.
+ fl_print_format("%[' failed with the exit code %]", print.to.stream, print.context, print.context);
+ fl_print_format("%[%i%]", print.to.stream, print.notable, code, print.notable);
+ fl_print_format("%[.%]%c", print.to.stream, print.context, print.context, f_string_eol_s[0]);
+ }
}
else {
fl_print_format("%[' failed.%]%c", print.to.stream, print.context, print.context, f_string_eol_s[0]);
}
#endif // _di_controller_rule_item_error_print_execute_
-#ifndef _di_controller_rule_item_error_print_execute_not_found_
- void controller_rule_item_error_print_execute_not_found(const fll_error_print_t print, const bool script_is, const f_string_t name) {
-
- if (print.verbosity == f_console_verbosity_quiet) return;
-
- fl_print_format("%c%[%SThe %s '%]", print.to.stream, f_string_eol_s[0], print.context, print.prefix, script_is ? controller_string_script_s : controller_string_program_s, print.context);
- fl_print_format("%[%S%]", print.to.stream, print.notable, name, print.notable);
- fl_print_format("%[' could not be executed because it was not found.%]%c", print.to.stream, print.context, print.context, f_string_eol_s[0]);
- }
-#endif // _di_controller_rule_item_error_print_execute_not_found_
-
#ifndef _di_controller_rule_item_error_print_need_want_wish_
void controller_rule_item_error_print_need_want_wish(const fll_error_print_t print, const f_string_t need_want_wish, const f_string_t value, const f_string_t why) {
execute_set.parameter.option |= fl_execute_parameter_option_path;
}
- // @todo: wrap these executions (foreground and background) in an additional loop to re-execution on the given re-run conditions.
if (process->rule.items.array[i].type == controller_rule_item_type_command) {
- status = controller_rule_execute_foreground(process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], 0, process->rule.items.array[i].actions.array[j].parameters, options, global, &execute_set, process);
+ for (;;) {
+
+ status = controller_rule_execute_foreground(process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], 0, process->rule.items.array[i].actions.array[j].parameters, options, global, &execute_set, process);
+
+ if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break;
+ if (F_status_is_error(status) && F_status_set_fine(status) != F_failure) break;
+
+ if (controller_rule_execute_rerun(global, controller_rule_action_type_to_action_execute_type(action), process, &process->rule.items.array[i]) > 0) {
+ continue;
+ }
+
+ break;
+ } // for
if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break;
else if (process->rule.items.array[i].type == controller_rule_item_type_script) {
execute_set.parameter.data = &process->rule.items.array[i].actions.array[j].parameters.array[0];
- status = controller_rule_execute_foreground(process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], process->rule.script.used ? process->rule.script.string : controller_default_program_script, arguments_none, options, global, &execute_set, process);
+ for (;;) {
+
+ status = controller_rule_execute_foreground(process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], process->rule.script.used ? process->rule.script.string : controller_default_program_script, arguments_none, options, global, &execute_set, process);
+
+ if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break;
+ if (F_status_is_error(status) && F_status_set_fine(status) != F_failure) break;
+
+ if (controller_rule_execute_rerun(global, controller_rule_action_type_to_action_execute_type(action), process, &process->rule.items.array[i]) > 0) {
+ continue;
+ }
+
+ break;
+ } // for
if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break;
}
else if (process->rule.items.array[i].type == controller_rule_item_type_service) {
if (process->rule.items.array[i].pid_file.used) {
- status = controller_rule_execute_pid_with(process->rule.items.array[i].pid_file, process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], 0, process->rule.items.array[i].actions.array[j].parameters, options, process->rule.items.array[i].with, global, &execute_set, process);
+ for (;;) {
+
+ status = controller_rule_execute_pid_with(process->rule.items.array[i].pid_file, process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], 0, process->rule.items.array[i].actions.array[j].parameters, options, process->rule.items.array[i].with, global, &execute_set, process);
+
+ if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break;
+ if (F_status_is_error(status) && F_status_set_fine(status) != F_failure) break;
+
+ if (controller_rule_execute_rerun(global, controller_rule_action_type_to_action_execute_type(action), process, &process->rule.items.array[i]) > 0) {
+ continue;
+ }
+
+ break;
+ } // for
if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break;
if (process->rule.items.array[i].pid_file.used) {
execute_set.parameter.data = &process->rule.items.array[i].actions.array[j].parameters.array[0];
- status = controller_rule_execute_pid_with(process->rule.items.array[i].pid_file, process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], process->rule.script.used ? process->rule.script.string : controller_default_program_script, arguments_none, options, process->rule.items.array[i].with, global, &execute_set, process);
+ for (;;) {
+
+ status = controller_rule_execute_pid_with(process->rule.items.array[i].pid_file, process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], process->rule.script.used ? process->rule.script.string : controller_default_program_script, arguments_none, options, process->rule.items.array[i].with, global, &execute_set, process);
+
+ if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break;
+ if (F_status_is_error(status) && F_status_set_fine(status) != F_failure) break;
+
+ if (controller_rule_execute_rerun(global, controller_rule_action_type_to_action_execute_type(action), process, &process->rule.items.array[i]) > 0) {
+ continue;
+ }
+
+ break;
+ } // for
if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break;
f_status_t status = F_none;
f_status_t status_lock = F_none;
- int result = 0;
- pid_t id_child = 0;
+ f_execute_result_t result = f_execute_result_t_initialize;
status = controller_pids_increase(&process->childs);
}
// sleep for less than a second to better show simulation of synchronous vs asynchronous.
- usleep(controller_thread_simulation_timeout);
+ {
+ struct timespec delay = controller_time_micro(controller_thread_simulation_timeout);
+ nanosleep(&delay, 0);
+ }
const f_string_static_t simulated_program = macro_f_string_static_t_initialize(f_string_empty_s, 0);
const f_string_statics_t simulated_arguments = f_string_statics_t_initialize;
fl_execute_parameter_t simulated_parameter = macro_fl_execute_parameter_t_initialize(execute_set->parameter.option, execute_set->parameter.wait, process->rule.has & controller_rule_has_environment ? execute_set->parameter.environment : 0, execute_set->parameter.signals, &simulated_program);
- status = fll_execute_program(controller_default_program_script, simulated_arguments, &simulated_parameter, &execute_set->as, simulated_parameter.option & fl_execute_parameter_option_return ? (void *) &id_child : (void *) &result);
+ status = fll_execute_program(controller_default_program_script, simulated_arguments, &simulated_parameter, &execute_set->as, (void *) &result);
}
else {
- status = fll_execute_program(program, arguments, &execute_set->parameter, &execute_set->as, execute_set->parameter.option & fl_execute_parameter_option_return ? (void *) &id_child : (void *) &result);
+ status = fll_execute_program(program, arguments, &execute_set->parameter, &execute_set->as, (void *) &result);
}
if (status == F_parent) {
- result = 0;
+ const pid_t id_child = result.pid;
+ result.status = 0;
f_thread_unlock(&process->lock);
if (status_lock != F_signal) {
// have the parent wait for the child process to finish.
- waitpid(id_child, &result, 0);
+ waitpid(id_child, &result.status, 0);
}
if (status_lock == F_signal || !controller_thread_is_enabled_process(process, global.thread)) {
return F_status_set_error(F_lock);
}
+ process->result = result.status;
+
// remove the pid now that waidpid() has returned.
*child = 0;
return F_status_set_error(F_lock);
}
- // this must explicitly check for 0 (as opposed to checking (!result)).
- if (!WIFEXITED(result)) {
+ if (WIFEXITED(result.status) ? WEXITSTATUS(result.status) : 0) {
status = F_status_set_error(F_failure);
}
else {
}
}
else {
+ global.main->child = result.status;
+
if (!controller_thread_is_enabled_process(process, global.thread)) {
return F_signal;
}
return status;
}
- if (result != 0) {
- status = F_status_set_error(F_failure);
- }
-
if (F_status_is_error(status)) {
status = F_status_set_fine(status);
- if (status == F_control_group || status == F_failure || status == F_limit || status == F_processor || status == F_schedule) {
- controller_rule_item_error_print_execute(global.main->error, type == controller_rule_item_type_script, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, result, status, global.thread);
- }
- else if (status == F_file_found_not) {
- controller_print_lock(global.main->error.to, global.thread);
-
- controller_rule_item_error_print_execute_not_found(global.main->error, F_false, program);
-
- controller_print_unlock_flush(global.main->error.to, global.thread);
+ if ((WIFEXITED(process->result) && WEXITSTATUS(process->result)) || status == F_control_group || status == F_failure || status == F_limit || status == F_processor || status == F_schedule) {
+ controller_rule_item_error_print_execute(global.main->error, type == controller_rule_item_type_script, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, WIFEXITED(process->result) ? WEXITSTATUS(process->result) : 0, status, global.thread);
}
else {
controller_error_print(global.main->error, F_status_set_fine(status), "fll_execute_program", F_true, global.thread);
f_status_t status = F_none;
f_status_t status_lock = F_none;
- int result = 0;
- pid_t id_child = 0;
+ f_execute_result_t result = f_execute_result_t_initialize;
status = controller_pids_increase(&process->childs);
}
// sleep for less than a second to better show simulation of synchronous vs asynchronous.
- usleep(controller_thread_simulation_timeout);
+ {
+ struct timespec delay = controller_time_micro(controller_thread_simulation_timeout);
+ nanosleep(&delay, 0);
+ }
const f_string_static_t simulated_program = macro_f_string_static_t_initialize(f_string_empty_s, 0);
const f_string_statics_t simulated_arguments = f_string_statics_t_initialize;
fl_execute_parameter_t simulated_parameter = macro_fl_execute_parameter_t_initialize(execute_set->parameter.option, execute_set->parameter.wait, process->rule.has & controller_rule_has_environment ? execute_set->parameter.environment : 0, execute_set->parameter.signals, &simulated_program);
- status = fll_execute_program(controller_default_program_script, simulated_arguments, &simulated_parameter, &execute_set->as, simulated_parameter.option & fl_execute_parameter_option_return ? (void *) &id_child : (void *) &result);
+ status = fll_execute_program(controller_default_program_script, simulated_arguments, &simulated_parameter, &execute_set->as, (void *) &result);
}
else {
- status = fll_execute_program(program, arguments, &execute_set->parameter, &execute_set->as, execute_set->parameter.option & fl_execute_parameter_option_return ? (void *) &id_child : (void *) &result);
+ status = fll_execute_program(program, arguments, &execute_set->parameter, &execute_set->as, (void *) &result);
}
if (status == F_parent) {
- result = 0;
+ const pid_t id_child = result.pid;
+ result.status = 0;
f_thread_unlock(&process->lock);
if (status_lock != F_signal) {
// the child process should perform the change into background, therefore it is safe to wait for the child to exit (another process is spawned).
- waitpid(id_child, &result, 0);
+ waitpid(id_child, &result.status, 0);
}
if (!controller_thread_is_enabled_process(process, global.thread)) {
return F_status_set_error(F_lock);
}
+ process->result = result.status;
+
// remove the pid now that waidpid() has returned.
*child = 0;
return F_status_set_error(F_lock);
}
- // this must explicitly check for 0 (as opposed to checking (!result)).
- // @todo expand this to provide user more control over what is or is not an error to designate as a failure.
- if (!WIFEXITED(result)) {
+ if (WIFEXITED(result.status) ? WEXITSTATUS(result.status) : 0) {
status = F_status_set_error(F_failure);
}
else {
}
}
else {
+ global.main->child = result.status;
+
if (!controller_thread_is_enabled_process(process, global.thread)) {
return F_signal;
}
return status;
}
- if (result != 0) {
- status = F_status_set_error(F_failure);
- }
-
if (F_status_is_error(status)) {
status = F_status_set_fine(status);
- if (status == F_control_group || status == F_failure || status == F_limit || status == F_processor || status == F_schedule) {
- controller_rule_item_error_print_execute(global.main->error, type == controller_rule_item_type_utility, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, result, status, global.thread);
- }
- else if (status == F_file_found_not) {
- controller_print_lock(global.main->error.to, global.thread);
-
- controller_rule_item_error_print_execute_not_found(global.main->error, F_false, program);
-
- controller_print_unlock_flush(global.main->error.to, global.thread);
+ if ((WIFEXITED(process->result) && WEXITSTATUS(process->result)) || status == F_control_group || status == F_failure || status == F_limit || status == F_processor || status == F_schedule) {
+ controller_rule_item_error_print_execute(global.main->error, type == controller_rule_item_type_utility, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, WIFEXITED(process->result) ? WEXITSTATUS(process->result) : 0, status, global.thread);
}
else {
controller_error_print(global.main->error, F_status_set_fine(status), "fll_execute_program", F_true, global.thread);
}
#endif // _di_controller_rule_execute_pid_with_
+#ifndef _di_controller_rule_execute_rerun_
+ int8_t controller_rule_execute_rerun(const controller_global_t global, const uint8_t action, controller_process_t *process, controller_rule_item_t *item) {
+
+ const int result = WIFEXITED(process->result) ? WEXITSTATUS(process->result) : 0;
+
+ if (item->reruns[action].is & (result ? controller_rule_rerun_is_failure : controller_rule_rerun_is_success)) {
+ controller_rule_rerun_item_t *rerun_item = result ? &item->reruns[action].failure : &item->reruns[action].success;
+
+ if (!controller_thread_is_enabled_process(process, global.thread)) return -2;
+
+ if (!rerun_item->max || rerun_item->count < rerun_item->max) {
+ if (global.main->error.verbosity == f_console_verbosity_debug) {
+ controller_print_lock(global.main->output, global.thread);
+
+ fl_print_format("%cRe-running '", global.main->output.stream, f_string_eol_s[0]);
+ fl_print_format("%[%q%]", global.main->output.stream, global.main->context.set.title, process->rule.alias, global.main->context.set.title);
+ f_print_terminated("' '", global.main->output.stream);
+ fl_print_format("%[%q%]", global.main->output.stream, global.main->context.set.notable, controller_rule_action_type_execute_name(action), global.main->context.set.notable);
+ f_print_terminated("' with a ", global.main->output.stream);
+ fl_print_format("%[%s%]", global.main->output.stream, global.main->context.set.notable, controller_string_delay_s, global.main->context.set.notable);
+ f_print_terminated(" of ", global.main->output.stream);
+ fl_print_format("%[%ul%] MegaTime", global.main->output.stream, global.main->context.set.notable, rerun_item->delay, global.main->context.set.notable);
+
+ if (rerun_item->max) {
+ f_print_terminated(" for ", global.main->output.stream);
+ fl_print_format("%[%ul%]", global.main->output.stream, global.main->context.set.notable, rerun_item->count, global.main->context.set.notable);
+ f_print_terminated(" of ", global.main->output.stream);
+ fl_print_format("%[%s%] ", global.main->output.stream, global.main->context.set.notable, controller_string_max_s, global.main->context.set.notable);
+ fl_print_format("%[%ul%]", global.main->output.stream, global.main->context.set.notable, rerun_item->max, global.main->context.set.notable);
+ fl_print_format(".%c", global.main->output.stream, f_string_eol_s[0]);
+ }
+ else {
+ fl_print_format(" with no %[%s%].%c", global.main->output.stream, global.main->context.set.notable, controller_string_max_s, global.main->context.set.notable, f_string_eol_s[0]);
+ }
+
+ controller_print_unlock_flush(global.main->output, global.thread);
+ }
+
+ if (rerun_item->delay) {
+ struct timespec time = controller_time_micro(rerun_item->delay);
+
+ if (nanosleep(&time, 0) < 0) {
+ return -1;
+ }
+
+ if (!controller_thread_is_enabled_process(process, global.thread)) return -2;
+ }
+
+ if (item->reruns[action].is & (result ? controller_rule_rerun_is_failure_reset : controller_rule_rerun_is_success_reset)) {
+ if (result) {
+ item->reruns[action].success.count = 0;
+ }
+ else {
+ item->reruns[action].failure.count = 0;
+ }
+ }
+
+ if (rerun_item->max) {
+ ++rerun_item->count;
+ }
+
+ return F_true;
+ }
+ }
+
+ return F_false;
+ }
+#endif // _di_controller_rule_execute_rerun_
+
#ifndef _di_controller_rule_id_construct_
f_status_t controller_rule_id_construct(const controller_global_t global, const f_string_static_t source, const f_string_range_t directory, const f_string_range_t basename, f_string_dynamic_t *alias) {
if (process->rule.items.used) {
fl_print_format("%c%[%SThe rule '%]", global.main->error.to.stream, f_string_eol_s[0], global.main->error.context, global.main->error.prefix, global.main->error.context);
fl_print_format("%[%Q%]", global.main->error.to.stream, global.main->error.notable, process->rule.name, global.main->error.notable);
- fl_print_format("%[' has no '%]", global.main->error.to.stream, global.main->error.context, process->rule.name, global.main->error.context);
+ fl_print_format("%[' has no '%]", global.main->error.to.stream, global.main->error.context, global.main->error.context);
fl_print_format("%[%q%]", global.main->error.to.stream, global.main->error.notable, controller_rule_action_type_name(process->action), global.main->error.notable);
fl_print_format("%[' action to execute.%]%c", global.main->error.to.stream, global.main->error.context, global.main->error.context, f_string_eol_s[0]);
}
#endif // _di_controller_rule_parameters_read_
/**
+ * Convert the action type to an action execute type.
+ *
+ * @param type
+ * The action type to convert from.
+ *
+ * @return
+ * The converted action type, converted into an action execute type.
+ *
+ * The code controller_rule_action_type_execute__enum_size is returned for unknown types.
+ *
+ */
+#ifndef _di_controller_rule_action_type_to_action_execute_type_
+ extern uint8_t controller_rule_action_type_to_action_execute_type(const uint8_t type) f_attribute_visibility_internal;
+#endif // _di_controller_rule_action_type_to_action_execute_type_
+
+/**
* Get a string representing the rule action type.
*
* @param type
#endif // _di_controller_rule_action_type_name_
/**
+ * Get a string representing the rule action execute type.
+ *
+ * @param type
+ * The rule action type execute code.
+ *
+ * @return
+ * The string with used > 0 on success.
+ * The string with used == 0 if no match was found.
+ */
+#ifndef _di_controller_rule_action_type_execute_name_
+ extern f_string_static_t controller_rule_action_type_execute_name(const uint8_t type) f_attribute_visibility_internal;
+#endif // _di_controller_rule_action_type_execute_name_
+
+/**
* Increase the size of the rule actions array by the specified amount, but only if necessary.
*
* This only increases size if the current used plus amount is greater than the currently allocated size.
#endif // _di_controller_rule_item_error_print_execute_
/**
- * Print an error or warning message related to the failed execution of some program or script for when the program or script is not found.
- *
- * @param print
- * The error or warning print structure.
- * @param script_is
- * If TRUE, then this represents a script.
- * If FALSE, then this represents a program.
- * @param code
- * The code returned by the executed program or script.
- */
-#ifndef _di_controller_rule_item_error_print_execute_not_found_
- extern void controller_rule_item_error_print_execute_not_found(const fll_error_print_t print, const bool script_is, const f_string_t name) f_attribute_visibility_internal;
-#endif // _di_controller_rule_item_error_print_execute_not_found_
-
-/**
* Print an error or warning message related to need/want/wish settings of some rule.
*
* @param print
#endif // _di_controller_rule_execute_pid_with_
/**
+ * Determine whether or not an execute rule should be re-run, applying a delay as requested.
+ *
+ * @param global
+ * The global data.
+ * @param action
+ * The action type.
+ * @param process
+ * The process data for processing this rule.
+ * @param item
+ * The rule item being executed.
+ *
+ * @return
+ * A positive number to designate re-run.
+ * 0 to designate do not re-run.
+ * -1 to designate an error from nanosleep(), with errno set to values like:
+ * - EFAULT: Designates that there was a problem copying information from user space.
+ * - EINTR: Consider this having returned F_signal.
+ * - EINVAL: Consider this having returned F_status_set_error(F_parameter);
+ * -2 to designate exit due to signal/disabled thread.
+ */
+#ifndef _di_controller_rule_execute_rerun_
+ extern int8_t controller_rule_execute_rerun(const controller_global_t global, const uint8_t action, controller_process_t *process, controller_rule_item_t *item) f_attribute_visibility_internal;
+#endif // _di_controller_rule_execute_rerun_
+
+/**
* Construct an id from two distinct strings found within a single given source.
*
* @param global
controller_thread_delete_simple(thread);
controller_setting_delete_simple(setting);
controller_main_delete(main);
+
+ // According to the manpages, pthread_exit() calls exit(0), which is not good because a non-zero exit code may be returned.
+ exit(main->child);
}
}
#endif // _di_controller_thread_process_
controller_setting_delete_simple(entry->global->setting);
controller_main_delete(entry->global->main);
+ const int code = main->child;
+
+ // According to the manpages, pthread_exit() calls exit(0), which is not good because a non-zero exit code may be returned.
+ exit(main->child);
+
return 0;
}
build_indexer ar
build_language c
build_libraries -lc -lcap
-build_libraries-individual -lfll_control_group -lfll_error -lfll_execute -lfll_fss -lfll_path -lfll_print -lfll_program -lfl_console -lfl_control_group -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_iki -lfl_print -lfl_status -lfl_string -lf_account -lf_capability -lf_color -lf_console -lf_control_group -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_iki -lf_limit -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_string -lf_thread -lf_type_array -lf_utf
+build_libraries-individual -lfll_control_group -lfll_error -lfll_execute -lfll_fss -lfll_path -lfll_print -lfll_program -lfl_console -lfl_control_group -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_iki -lfl_print -lfl_status -lfl_string -lf_account -lf_capability -lf_color -lf_console -lf_control_group -lf_conversion -lf_directory -lf_environment -lf_execute -lf_file -lf_fss -lf_iki -lf_limit -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_string -lf_thread -lf_type_array -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library controller.c private-common.c private-control.c private-controller.c private-entry.c private-rule.c private-thread.c
--- /dev/null
+# fss-0005
+
+setting:
+ mode program
+
+main:
+ start command htop
--- /dev/null
+# fss-000d
+
+setting:
+ name "Run htop"
+
+command:
+ start htop
+
+ rerun start success delay 3000 max 3
build_indexer ar
build_language c
build_libraries -lc -lcap
-build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_path -lfll_print -lfll_program -lfl_console -lfl_control_group -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_iki -lfl_print -lfl_status -lfl_string -lf_account -lf_capability -lf_color -lf_console -lf_control_group -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_iki -lf_limit -lf_memory -lf_path -lf_print -lf_signal -lf_string -lf_thread -lf_type_array -lf_utf
+build_libraries-individual -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_path -lfll_print -lfll_program -lfl_console -lfl_control_group -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_iki -lfl_print -lfl_status -lfl_string -lf_account -lf_capability -lf_color -lf_console -lf_control_group -lf_conversion -lf_directory -lf_environment -lf_execute -lf_file -lf_fss -lf_iki -lf_limit -lf_memory -lf_path -lf_print -lf_signal -lf_string -lf_thread -lf_type_array -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library fake.c private-common.c private-fake.c private-clean.c private-build.c private-make.c private-print.c private-skeleton.c
build_indexer ar
build_language c
build_libraries -lc -lcap
-build_libraries-individual -lfll_error -lfll_execute -lfll_fss -lfll_print -lfll_program -lfl_console -lfl_control_group -lfl_conversion -lfl_environment -lfl_fss -lfl_print -lfl_status -lfl_string -lf_account -lf_capability -lf_color -lf_console -lf_control_group -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_limit -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_string -lf_thread -lf_type_array -lf_utf
+build_libraries-individual -lfll_error -lfll_execute -lfll_fss -lfll_print -lfll_program -lfl_console -lfl_control_group -lfl_conversion -lfl_environment -lfl_fss -lfl_print -lfl_status -lfl_string -lf_account -lf_capability -lf_color -lf_console -lf_control_group -lf_conversion -lf_directory -lf_environment -lf_execute -lf_file -lf_fss -lf_limit -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_string -lf_thread -lf_type_array -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_sources_library firewall.c private-common.c private-firewall.c