}
}
+ // @todo create pid file but not until "ready", so be sure to add this after pre-processing the entry file.
+ if (setting.ready) {
+ controller_file_pid_create(*data, setting.path_pid);
+ }
+
if (F_status_is_error_not(status)) {
if (data->parameters[controller_parameter_test].result == f_console_result_found || data->parameters[controller_parameter_validate].result == f_console_result_found) {
// @todo validate happens first, report and handle validation problems or success.
}
}
+ controller_file_pid_delete(*data, setting.path_pid);
+
macro_controller_setting_t_delete_simple(setting);
macro_controller_entry_cache_t_delete_simple(cache_entry);
macro_controller_rule_cache_t_delete_simple(cache_rule);
+
controller_delete_data(data);
return status;
* This program can be controlled from user-space via the "control" program.
*
* @todo research containers and build in container support into this, providing "container" appropriate verbiage for individual rules.
+ * @todo research namespaces and user_namespaces, they may be important to support.
*/
#ifndef _controller_h
// libc includes
#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
// fll-0 includes
#include <level_0/type.h>
// must be at least 2.
#define controller_default_allocation_step 4
- #define controller_path_pid "/var/run/controller.pid"
+ #define controller_path_pid "/var/run/controller/controller.pid"
#define controller_path_settings "/etc/controller"
- #define controller_path_pid_length 23
+ #define controller_path_pid_length 34
#define controller_path_settings_length 15
#define controller_short_interruptable "i"
f_string_lengths_t remaining;
bool process_pipe;
+ pid_t pid;
f_file_t output;
fll_error_print_t error;
controller_console_parameter_t_initialize, \
f_string_lengths_t_initialize, \
F_false, \
+ 0, \
f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
fll_error_print_t_initialize, \
fll_macro_error_print_t_initialize_warning(), \
data.process_pipe = F_true;
}
+ data.pid = getpid();
+
if (F_status_is_error(controller_main(arguments, &data))) {
return 1;
}
}
#endif // _di_controller_file_load_
+#ifndef _di_controller_file_pid_create_
+ f_return_status controller_file_pid_create(const controller_data_t data, const f_string_static_t path_pid) {
+ f_status_t status = F_none;
+
+ // the file exists, do not attempt to overwrite.
+ if (f_file_exists(path_pid.string) == F_true) {
+ return F_status_set_error(F_file_found);
+ }
+
+ {
+ f_string_dynamic_t path_directory = f_string_dynamic_t_initialize;
+
+ status = f_file_name_directory(path_pid.string, path_pid.used, &path_directory);
+
+ if (F_status_is_error_not(status)) {
+ status = f_directory_exists(path_directory.string);
+ }
+
+ f_macro_string_dynamic_t_delete_simple(path_directory);
+
+ if (F_status_is_error(status)) return status;
+
+ // the directory does not exist so do not bother attempting to create a pid file.
+ if (status == F_false) {
+ return F_status_set_error(F_directory_not);
+ }
+ }
+
+ f_file_t file = f_file_t_initialize;
+
+ file.flag = f_file_flag_write_only;
+
+ status = f_file_stream_open(path_pid.string, f_macro_file_open_mode_truncate, &file);
+ if (F_status_is_error(status)) return status;
+
+ fprintf(file.stream, "%llu\n", data.pid);
+
+ f_file_stream_close(F_true, &file);
+
+ if (F_status_is_error(status)) return status;
+
+ return F_none;
+ }
+#endif // _di_controller_file_pid_create_
+
+#ifndef _di_controller_file_pid_delete_
+ void controller_file_pid_delete(const controller_data_t data, const f_string_static_t path_pid) {
+
+ if (f_file_exists(path_pid.string) != F_true) {
+ return;
+ }
+
+ f_status_t status = F_none;
+ f_file_t pid_file = f_file_t_initialize;
+
+ status = f_file_stream_open(path_pid.string, f_macro_file_open_mode_read, &pid_file);
+ if (F_status_is_error(status)) return;
+
+ f_string_dynamic_t pid_buffer = f_string_dynamic_t_initialize;
+
+ status = f_file_stream_read(pid_file, 1, &pid_buffer);
+
+ f_file_stream_close(F_true, &pid_file);
+
+ if (F_status_is_error_not(status)) {
+ f_number_unsigned_t number = 0;
+ f_string_range_t range = f_macro_string_range_t_initialize(pid_buffer.used);
+
+ for (; range.start < pid_buffer.used; ++range.start) {
+ if (!isspace(pid_buffer.string[range.start])) break;
+ } // for
+
+ for (; range.stop > 0; --range.stop) {
+ if (!isspace(pid_buffer.string[range.stop])) break;
+ } // for
+
+ status = fl_conversion_string_to_decimal_unsigned(pid_buffer.string, &number, range);
+
+ if (F_status_is_error_not(status) && number == data.pid) {
+ f_file_remove(path_pid.string);
+ }
+ }
+
+ f_macro_string_dynamic_t_delete_simple(pid_buffer);
+ }
+#endif // _di_controller_file_pid_delete_
+
#ifndef _di_controller_status_simplify_
f_return_status controller_status_simplify(const f_status_t status) {
#endif // _di_controller_file_load_
/**
+ * Create the pid file, if possible.
+ *
+ * @param data
+ * The program data.
+ * @param path_pid
+ * The file path to the pid file to create.
+ *
+ * @return
+ * F_none on success.
+ * F_access_denied if pid file is not created due to access denied errors.
+ * F_directory_not if pid file is not created due to a parent directory is unavailable or invalid.
+ *
+ * Errors (with error bit) from: f_directory_exists().
+ * Errors (with error bit) from: f_file_name_directory().
+ * Errors (with error bit) from: f_file_stream_open().
+ *
+ * @see f_directory_exists()
+ * @see f_file_name_directory()
+ * @see f_file_stream_open()
+ */
+#ifndef _di_controller_file_pid_create_
+ f_return_status controller_file_pid_create(const controller_data_t data, const f_string_static_t path_pid) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_file_pid_create_
+
+/**
+ * Delete the pid file, if exists and is valid.
+ *
+ * This is meant to be called on exit and avoids checking status codes, returning void.
+ *
+ * @param data
+ * The program data.
+ * @param path_pid
+ * The file path to the pid file to create.
+ */
+#ifndef _di_controller_file_pid_delete_
+ void controller_file_pid_delete(const controller_data_t data, const f_string_static_t path_pid) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_file_pid_delete_
+
+/**
* Given a wide range of status codes, simplify them down to a small subset.
*
* @param status
f_color
f_console
f_conversion
+f_directory
f_file
f_fss
f_iki
build_indexer ar
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_fss -lfll_path -lfll_program -lfll_status -lfl_color -lfl_console -lfl_conversion -lfl_fss -lfl_status -lfl_string -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
+build_libraries-individual -lfll_error -lfll_fss -lfll_path -lfll_program -lfll_status -lfl_color -lfl_console -lfl_conversion -lfl_fss -lfl_iki -lfl_status -lfl_string -lf_console -lf_conversion -lf_directory -lf_file -lf_fss -lf_iki -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 controller.c private-control.c private-controller.c private-entry.c private-rule.c