Fix bug in control where parameter should be "settings" and not "socket".
The controller can now detect the current path and provide a canonical relative path only for paths whose actual canonical path is within the current working directory that the controller program started in.
Fix printing of the help in the controller program (missing slashes).
Don't create socket and pid files when running validate and simulate.
When running simulate, still create the pid and socket files as appropriate.
Add new entry setting to allow explicitly setting the pid file path.
Remove no longer necessary functions that ensure terminating NULL.
The recent changes in the string functions now guarantee this.
Remove a lot of todo comments.
I will either get to them or not.
I plan on getting to writing IKI support.
It needs to happen and I can use the Fake program as an example.
data->cache.buffer_small.used = 0;
- if (main->parameters.array[control_parameter_socket_e].result == f_console_result_additional_e) {
+ if (main->parameters.array[control_parameter_settings_e].result == f_console_result_additional_e) {
const f_array_length_t index = main->parameters.array[control_parameter_settings_e].values.array[main->parameters.array[control_parameter_settings_e].values.used - 1];
status = f_string_dynamic_append(data->argv[index], &data->cache.buffer_small);
f_string_dynamic_resize(0, &setting->path_control);
f_string_dynamic_resize(0, &setting->path_cgroup);
+ f_string_dynamic_resize(0, &setting->path_current);
f_string_dynamic_resize(0, &setting->path_pid);
f_string_dynamic_resize(0, &setting->path_setting);
f_string_dynamic_t path_cgroup;
f_string_dynamic_t path_control;
+ f_string_dynamic_t path_current;
f_string_dynamic_t path_pid;
f_string_dynamic_t path_setting;
f_string_dynamic_t_initialize, \
f_string_dynamic_t_initialize, \
f_string_dynamic_t_initialize, \
+ f_string_dynamic_t_initialize, \
controller_entry_t_initialize, \
controller_entry_t_initialize, \
controller_rules_t_initialize, \
fll_program_print_help_option(main->output.to, main->context, controller_short_daemon_s, controller_long_daemon_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Run in daemon only mode (do not process the entry).");
fll_program_print_help_option(main->output.to, main->context, controller_short_init_s, controller_long_init_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The program will run as an init replacement.");
fll_program_print_help_option(main->output.to, main->context, controller_short_interruptible_s, controller_long_interruptible_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate that this program can be interrupted by a signal.");
- fll_program_print_help_option(main->output.to, main->context, controller_short_pid_s, controller_long_pid_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom pid file path, such as '" CONTROLLER_path_pid_s CONTROLLER_default_s CONTROLLER_path_pid_suffix_s "'.");
- fll_program_print_help_option(main->output.to, main->context, controller_short_settings_s, controller_long_settings_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom settings path, such as '" CONTROLLER_path_settings_s "'.");
+ fll_program_print_help_option(main->output.to, main->context, controller_short_pid_s, controller_long_pid_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom pid file path, such as '" CONTROLLER_path_pid_s F_path_separator_s CONTROLLER_default_s CONTROLLER_path_pid_suffix_s "'.");
+ fll_program_print_help_option(main->output.to, main->context, controller_short_settings_s, controller_long_settings_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom settings path, such as '" CONTROLLER_path_settings_s F_path_separator_s "'.");
fll_program_print_help_option(main->output.to, main->context, controller_short_simulate_s, controller_long_simulate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Run as a simulation.");
- fll_program_print_help_option(main->output.to, main->context, controller_short_socket_s, controller_long_socket_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom socket file path, such as '" CONTROLLER_path_socket_s CONTROLLER_default_s CONTROLLER_path_socket_suffix_s "'.");
+ fll_program_print_help_option(main->output.to, main->context, controller_short_socket_s, controller_long_socket_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom socket file path, such as '" CONTROLLER_path_socket_s F_path_separator_s CONTROLLER_default_s CONTROLLER_path_socket_suffix_s "'.");
fll_program_print_help_option(main->output.to, main->context, controller_short_uninterruptible_s, controller_long_uninterruptible_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Designate that this program cannot be interrupted by a signal.");
fll_program_print_help_option(main->output.to, main->context, controller_short_validate_s, controller_long_validate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Validate the settings (entry and rules) without running (does not simulate).");
setting.mode = controller_setting_mode_service_e;
}
- if (main->parameters.array[controller_parameter_settings_e].result == f_console_result_found_e) {
- if (main->error.verbosity != f_console_verbosity_quiet_e) {
- controller_lock_print(main->error.to, 0);
+ status = f_path_current(F_false, &setting.path_current);
- fl_print_format("%r%[%QThe parameter '%]", main->error.to.stream, f_string_eol_s, main->error.context, main->error.prefix, main->error.context);
- fl_print_format("%[%r%r%]", main->error.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, controller_long_settings_s, main->context.set.notable);
- fl_print_format("%[' is specified, but no value is given.%]%r", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s);
-
- controller_unlock_print_flush(main->error.to, 0);
- }
-
- status = F_status_set_error(F_parameter);
+ if (F_status_is_error(status)) {
+ fll_error_print(main->error, F_status_set_fine(status), "f_path_current", F_true);
}
- else if (main->parameters.array[controller_parameter_settings_e].locations.used) {
- const f_array_length_t index = main->parameters.array[controller_parameter_settings_e].values.array[main->parameters.array[controller_parameter_settings_e].values.used - 1];
+ else {
+ if (main->parameters.array[controller_parameter_settings_e].result == f_console_result_found_e) {
+ if (main->error.verbosity != f_console_verbosity_quiet_e) {
+ controller_lock_print(main->error.to, 0);
- status = fll_path_canonical(argv[index], &setting.path_setting);
+ fl_print_format("%r%[%QThe parameter '%]", main->error.to.stream, f_string_eol_s, main->error.context, main->error.prefix, main->error.context);
+ fl_print_format("%[%r%r%]", main->error.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, controller_long_settings_s, main->context.set.notable);
+ fl_print_format("%[' is specified, but no value is given.%]%r", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s);
- if (F_status_is_error(status)) {
- fll_error_file_print(main->error, F_status_set_fine(status), "fll_path_canonical", F_true, argv[index], f_file_operation_verify_s, fll_error_file_type_path_e);
- }
- }
- else {
- if (main->parameters.array[controller_parameter_init_e].result == f_console_result_found_e && !main->as_init) {
- status = f_string_dynamic_append(controller_path_settings_init_s, &setting.path_setting);
+ controller_unlock_print_flush(main->error.to, 0);
+ }
+
+ status = F_status_set_error(F_parameter);
}
- else if (main->default_path_setting->used) {
- status = f_string_dynamic_append(*main->default_path_setting, &setting.path_setting);
+ else if (main->parameters.array[controller_parameter_settings_e].locations.used) {
+ const f_array_length_t index = main->parameters.array[controller_parameter_settings_e].values.array[main->parameters.array[controller_parameter_settings_e].values.used - 1];
+
+ status = controller_path_canonical_relative(&setting, argv[index], &setting.path_setting);
+
+ if (F_status_is_error(status)) {
+ fll_error_file_print(main->error, F_status_set_fine(status), "controller_path_canonical_relative", F_true, argv[index], f_file_operation_verify_s, fll_error_file_type_path_e);
+ }
}
else {
- status = f_string_dynamic_append(controller_path_settings_s, &setting.path_setting);
- }
+ if (main->parameters.array[controller_parameter_init_e].result == f_console_result_found_e && !main->as_init) {
+ status = f_string_dynamic_append(controller_path_settings_init_s, &setting.path_setting);
+ }
+ else if (main->default_path_setting->used) {
+ status = f_string_dynamic_append(*main->default_path_setting, &setting.path_setting);
+ }
+ else {
+ status = f_string_dynamic_append(controller_path_settings_s, &setting.path_setting);
+ }
- if (F_status_is_error(status)) {
- fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_append", F_true);
+ if (F_status_is_error(status)) {
+ fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_append", F_true);
+ }
}
}
const f_array_length_t index = main->parameters.array[controller_parameter_pid_e].values.array[main->parameters.array[controller_parameter_pid_e].values.used - 1];
if (argv[index].used) {
- status = fll_path_canonical(argv[index], &setting.path_pid);
+ status = controller_path_canonical_relative(&setting, argv[index], &setting.path_pid);
if (F_status_is_error(status)) {
- fll_error_file_print(main->error, F_status_set_fine(status), "fll_path_canonical", F_true, argv[index], f_file_operation_verify_s, fll_error_file_type_path_e);
+ fll_error_file_print(main->error, F_status_set_fine(status), "controller_path_canonical_relative", F_true, argv[index], f_file_operation_verify_s, fll_error_file_type_path_e);
}
}
else {
const f_array_length_t index = main->parameters.array[controller_parameter_cgroup_e].values.array[main->parameters.array[controller_parameter_cgroup_e].values.used - 1];
if (argv[index].used) {
- status = fll_path_canonical(argv[index], &setting.path_cgroup);
+ status = controller_path_canonical_relative(&setting, argv[index], &setting.path_cgroup);
if (F_status_is_error(status)) {
- fll_error_file_print(main->error, F_status_set_fine(status), "fll_path_canonical", F_true, argv[index], f_file_operation_verify_s, fll_error_file_type_path_e);
+ fll_error_file_print(main->error, F_status_set_fine(status), "controller_path_canonical_relative", F_true, argv[index], f_file_operation_verify_s, fll_error_file_type_path_e);
}
else {
status = f_string_append_assure(F_path_separator_s, 1, &setting.path_cgroup);
* This program provides system service management, much like sysvcontroller and controllerng.
* This program can be controlled from user-space via the "control" program.
* This program can be used in an initrd and should be capable of pivot root operations.
- *
- * @todo Implement "exit" files that are the opposite of "entry" files whereas rules specified within are all called via the "stop" action type.
- * This would then allow for switching modes.
- * The "exit" would be specified in the "entry", by name and would be found under "exits" directory alongside the "entries" directory.
- *
- * @todo check the return status of unlocks.
- *
- * @todo the read/write locks (and unlocks) needs to be more robust in that they need to attempt to keep going even on failure or need to wait until resolvable.
- * this is done to help ensure that the controller program always continues onward.
- *
- * @todo just like with the read/write locks, the out of memory cases need to be handled to keep going instead of bailing.
- * likely these will need to be sleeps on the premise that eventually memory will clear itself up.
*/
#ifndef _controller_h
#define _controller_h
}
#endif // _di_controller_range_after_number_sign_
-#ifndef _di_controller_string_dynamic_rip_nulless_terminated_
- f_status_t controller_dynamic_rip_nulless_terminated(const f_string_static_t source, const f_string_range_t range, f_string_dynamic_t *destination) {
-
- return fl_string_dynamic_partial_rip_nulless(source, range, destination);
- }
-#endif // _di_controller_string_dynamic_rip_nulless_terminated_
-
-#ifndef _di_controller_string_dynamic_append_terminated_
- f_status_t controller_dynamic_append_terminated(const f_string_static_t source, f_string_dynamic_t *destination) {
-
- return f_string_dynamic_append_nulless(source, destination);
- }
-#endif // _di_controller_string_dynamic_append_terminated_
-
-#ifndef _di_controller_string_dynamic_partial_append_terminated_
- f_status_t controller_dynamic_partial_append_terminated(const f_string_static_t source, const f_string_range_t range, f_string_dynamic_t *destination) {
-
- return f_string_dynamic_partial_append(source, range, destination);
- }
-#endif // _di_controller_string_dynamic_partial_append_terminated_
-
#ifndef _di_controller_file_load_
f_status_t controller_file_load(const controller_global_t global, const bool required, const f_string_static_t path_prefix, const f_string_static_t path_name, const f_string_static_t path_suffix, controller_cache_t * const cache) {
if (F_status_set_fine(status) == F_number) {
cache->action.generic.used = 0;
- status = controller_dynamic_rip_nulless_terminated(buffer, range, &cache->action.generic);
+ status = fl_string_dynamic_partial_rip_nulless(buffer, range, &cache->action.generic);
if (F_status_is_error(status)) return status;
status = f_account_id_by_name(cache->action.generic, id);
if (F_status_set_fine(status) == F_number) {
cache->action.generic.used = 0;
- status = controller_dynamic_rip_nulless_terminated(buffer, range, &cache->action.generic);
+ status = fl_string_dynamic_partial_rip_nulless(buffer, range, &cache->action.generic);
if (F_status_is_error(status)) return status;
status = f_account_group_id_by_name(cache->action.generic, id);
}
#endif // _di_controller_get_id_group_
+#ifndef _di_controller_path_canonical_relative_
+ f_status_t controller_path_canonical_relative(const controller_setting_t * const setting, const f_string_static_t source, f_string_dynamic_t * const destination) {
+
+ {
+ const f_status_t status = fll_path_canonical(source, destination);
+ if (F_status_is_error(status)) return status;
+ }
+
+ if (destination->used >= setting->path_current.used) {
+ const f_string_range_t range = macro_f_string_range_t_initialize(setting->path_current.used);
+
+ if (fl_string_dynamic_partial_compare(*destination, setting->path_current, range, range) == F_equal_to) {
+ f_array_length_t length = destination->used - setting->path_current.used;
+
+ if (length) {
+ char temporary[--length];
+ temporary[length] = 0;
+
+ memcpy(temporary, destination->string + setting->path_current.used + 1, length);
+ memcpy(destination->string, temporary, length);
+
+ destination->string[length] = 0;
+ destination->used = length;
+ }
+ else {
+ destination->used = 0;
+ }
+ }
+ }
+
+ return F_none;
+ }
+#endif // _di_controller_path_canonical_relative_
+
#ifndef _di_controller_perform_ready_
f_status_t controller_perform_ready(const controller_global_t * const global, controller_cache_t * const cache, const bool is_entry) {
return F_none;
}
+ if (global->main->parameters.array[controller_parameter_validate_e].result == f_console_result_found_e) {
+ if (global->main->parameters.array[controller_parameter_simulate_e].result == f_console_result_found_e && global->main->output.verbosity == f_console_verbosity_debug_e) {
+ controller_lock_print(global->main->output.to, global->thread);
+
+ fl_print_format("%rPID file '", global->main->output.to.stream, f_string_eol_s);
+ fl_print_format("%[%Q%]'.%r", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_pid, global->main->context.set.notable, f_string_eol_s);
+
+ if (global->setting->path_control.used) {
+ fl_print_format("%rControl socket '", global->main->output.to.stream, f_string_eol_s);
+ fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
+ fl_print_format("'.%r", global->main->output.to.stream, f_string_eol_s);
+ }
+
+ controller_unlock_print_flush(global->main->output.to, global->thread);
+ }
+
+ return F_none;
+ }
+
f_status_t status = F_none;
if (global->setting->entry.pid != controller_entry_pid_disable_e && !global->setting->path_pid.used) {
- if (global->main->parameters.array[controller_parameter_validate_e].result == f_console_result_additional_e) {
- status = controller_file_pid_create(global->main->pid, global->setting->path_pid);
- }
+ status = controller_file_pid_create(global->main->pid, global->setting->path_pid);
// Report pid file error but because this could be an "init" program, consider the pid file as optional and continue on.
if (F_status_is_error(status)) {
controller_lock_print(global->main->output.to, global->thread);
fl_print_format("%rPID file '", global->main->output.to.stream, f_string_eol_s);
- fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_pid, global->main->context.set.notable);
-
- if (global->main->parameters.array[controller_parameter_validate_e].result == f_console_result_none_e) {
- fl_print_format("' created.%r", global->main->output.to.stream, f_string_eol_s);
- }
- else {
- fl_print_format("'.%r", global->main->output.to.stream, f_string_eol_s);
- }
+ fl_print_format("%[%Q%]' created.%r", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_pid, global->main->context.set.notable, f_string_eol_s);
controller_unlock_print_flush(global->main->output.to, global->thread);
}
fl_print_format("%rControl socket '", global->main->output.to.stream, f_string_eol_s);
fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
-
- if (global->main->parameters.array[controller_parameter_validate_e].result == f_console_result_none_e) {
- fl_print_format("' created.%r", global->main->output.to.stream, f_string_eol_s);
- }
- else {
- fl_print_format("'.%r", global->main->output.to.stream, f_string_eol_s);
- }
+ fl_print_format("' created.%r", global->main->output.to.stream, f_string_eol_s);
controller_unlock_print_flush(global->main->output.to, global->thread);
}
#endif // _di_controller_range_after_number_sign_
/**
- * Rip a string from the source and then add a NULL after the end of the string.
- *
- * @param source
- * The string to copy from.
- * @param destination
- * The string to copy to.
- *
- * @return
- * F_none on success.
- *
- * Errors (with error bit) from: fl_string_dynamic_partial_rip_nulless().
- *
- * @see fl_string_dynamic_partial_rip_nulless()
- */
-#ifndef _di_controller_string_dynamic_rip_nulless_terminated_
- extern f_status_t controller_dynamic_rip_nulless_terminated(const f_string_static_t source, const f_string_range_t range, f_string_dynamic_t *destination) F_attribute_visibility_internal_d;
-#endif // _di_controller_string_dynamic_rip_nulless_terminated_
-
-/**
- * Append a string and then add a NULL after the end of the string.
- *
- * @param source
- * The string to copy from.
- * @param destination
- * The string to copy to.
- *
- * @return
- * F_none on success.
- *
- * Errors (with error bit) from: f_string_dynamic_append_nulless().
- *
- * @see f_string_dynamic_append_nulless()
- */
-#ifndef _di_controller_string_dynamic_append_terminated_
- extern f_status_t controller_dynamic_append_terminated(const f_string_static_t from, f_string_dynamic_t *destination) F_attribute_visibility_internal_d;
-#endif // _di_controller_string_dynamic_append_terminated_
-
-/**
- * Append given range from within a string and then add a NULL after the end of the string.
- *
- * @param from
- * The string to copy from.
- * @param range
- * The range within the from string to copy.
- * @param destination
- * The string to copy to.
- *
- * @return
- * F_none on success.
- *
- * Errors (with error bit) from: f_string_dynamic_append().
- *
- * @see f_string_dynamic_append()
- */
-#ifndef _di_controller_string_dynamic_partial_append_terminated_
- extern f_status_t controller_dynamic_partial_append_terminated(const f_string_static_t from, const f_string_range_t range, f_string_dynamic_t *destination) F_attribute_visibility_internal_d;
-#endif // _di_controller_string_dynamic_partial_append_terminated_
-
-/**
* Load a file from the controller settings directory.
*
* @param global
#endif // _di_controller_get_id_group_
/**
+ * Determine a canonical path and then if it is relative to the current working directory, make it relative.
+ *
+ * For example, given the paths "../hello/world/" and "../controller/files/" with a current working directory of "/tmp/controller", then a canonical path for these might look like:
+ * - "/tmp/hello/world/"
+ * - "/tmp/controller/files/"
+ *
+ * This function would instead result in the following:
+ * - "/tmp/hello/world/"
+ * - "files/"
+ *
+ * @param setting
+ * The controller settings data.
+ * @param source
+ * The source path to determine the relative canonical from.
+ * @param destination
+ * The resulting relative canonical path.
+ * The destination will be completely replaced on success.
+ *
+ * @return
+ * F_none on success.
+ *
+ * Errors (with error bit) from: fll_path_canonical().
+ *
+ * @see fll_path_canonical()
+ */
+#ifndef _di_controller_path_canonical_relative_
+ extern f_status_t controller_path_canonical_relative(const controller_setting_t * const global, const f_string_static_t source, f_string_dynamic_t * const destination) F_attribute_visibility_internal_d;
+#endif // _di_controller_path_canonical_relative_
+
+/**
* Perform all activities requiring the state to be "ready".
*
* This prints messages on errors.
* @param main
* The main program data.
* @param setting
- * The settings.
+ * The controller settings data.
* @param time
* The number of nanoseconds to sleep.
*
action->line = ++cache->action.line_action;
- status = controller_dynamic_rip_nulless_terminated(cache->buffer_file, cache->object_actions.array[i], &cache->action.name_action);
+ status = fl_string_dynamic_partial_rip_nulless(cache->buffer_file, cache->object_actions.array[i], &cache->action.name_action);
if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "controller_dynamic_rip_nulless_terminated", F_true, global.thread);
+ controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "fl_string_dynamic_partial_rip_nulless", F_true, global.thread);
+
break;
}
if (action->parameters.array[0].used) {
// Force the path to be canonical (removing all '../' parts).
- status = fll_path_canonical(action->parameters.array[0], &cache->buffer_path);
+ status = controller_path_canonical_relative(global.setting, action->parameters.array[0], &cache->buffer_path);
if (F_status_is_error(status)) {
- // @todo instead call: fll_error_file_print().
- // fll_error_file_print(main->error, F_status_set_fine(status), "fll_path_canonical", F_true, argv[index], f_file_operation_verify_s, fll_error_file_type_path_e);
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "fll_path_canonical", F_true, global.thread);
+ controller_entry_print_error_file(is_entry, global.main->error, cache->action, F_status_set_fine(status), "controller_path_canonical_relative", F_true, cache->action.generic, f_file_operation_analyze_s, fll_error_file_type_path_e, global.thread);
action->status = status;
if (F_status_set_fine(status) == F_memory_not) {
status_action = status;
+
break;
}
if (F_status_set_fine(status) == F_memory_not) {
status_action = status;
+
break;
}
uint8_t error_has = F_false;
// This effectively sets the read for an entry and resets the ready for an exit.
- // @todo should there be a ready_exit instead?
- // @todo the global.setting->ready in this function may need mutex lock protection.
- // @todo disconnect the socket file if applicable.
global.setting->ready = controller_setting_ready_no_e;
cache->ats.used = 0;
cache->action.line_item = entry->items.array[0].line;
cache->action.name_item.used = 0;
- status = controller_dynamic_append_terminated(entry->items.array[0].name, &cache->action.name_item);
+ status = f_string_dynamic_append_nulless(entry->items.array[0].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "controller_dynamic_append_terminated", F_true, global.thread);
+ controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true, global.thread);
return status;
}
cache->action.line_action = actions->array[cache->ats.array[at_j]].line;
cache->action.name_action.used = 0;
- status2 = controller_dynamic_append_terminated(controller_entry_action_type_name(actions->array[cache->ats.array[at_j]].type), &cache->action.name_action);
+ status2 = f_string_dynamic_append_nulless(controller_entry_action_type_name(actions->array[cache->ats.array[at_j]].type), &cache->action.name_action);
if (F_status_is_error(status2)) {
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status2), "controller_dynamic_append_terminated", F_true, global.thread);
+ controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status2), "f_string_dynamic_append_nulless", F_true, global.thread);
return status2;
}
cache->action.name_item.used = 0;
cache->action.line_item = entry->items.array[i].line;
- status2 = controller_dynamic_append_terminated(entry->items.array[i].name, &cache->action.name_item);
+ status2 = f_string_dynamic_append_nulless(entry->items.array[i].name, &cache->action.name_item);
if (F_status_is_error(status2)) {
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status2), "controller_dynamic_append_terminated", F_true, global.thread);
+ controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status2), "f_string_dynamic_append_nulless", F_true, global.thread);
return status2;
}
cache->action.line_item = entry->items.array[cache->ats.array[at_i]].line;
cache->action.name_item.used = 0;
- status2 = controller_dynamic_append_terminated(entry->items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
+ status2 = f_string_dynamic_append_nulless(entry->items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
if (F_status_is_error(status2)) {
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status2), "controller_dynamic_append_terminated", F_true, global.thread);
+ controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status2), "f_string_dynamic_append_nulless", F_true, global.thread);
return status2;
}
controller_entry_actions_t *entry_actions = 0;
controller_process_t *process = 0;
- // an empty stack is used here because each rule here is the first rule run in the rule's scope.
+ // An empty stack is used here because each rule here is the first rule run in the rule's scope.
const f_array_lengths_t stack = f_array_lengths_t_initialize;
cache->ats.used = 0;
cache->action.line_item = entry->items.array[cache->ats.array[0]].line;
cache->action.name_item.used = 0;
- status = controller_dynamic_append_terminated(entry->items.array[cache->ats.array[0]].name, &cache->action.name_item);
+ status = f_string_dynamic_append_nulless(entry->items.array[cache->ats.array[0]].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global->main->error, cache->action, F_status_set_fine(status), "controller_dynamic_append_terminated", F_true, global->thread);
+ controller_entry_print_error(is_entry, global->main->error, cache->action, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true, global->thread);
return status;
}
cache->action.line_action = entry_action->line;
cache->action.name_action.used = 0;
- status = controller_dynamic_append_terminated(controller_entry_action_type_name(entry_action->type), &cache->action.name_action);
+ status = f_string_dynamic_append_nulless(controller_entry_action_type_name(entry_action->type), &cache->action.name_action);
if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global->main->error, cache->action, F_status_set_fine(status), "controller_dynamic_append_terminated", F_true, global->thread);
+ controller_entry_print_error(is_entry, global->main->error, cache->action, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true, global->thread);
return status;
}
cache->action.name_item.used = 0;
cache->action.line_item = entry->items.array[cache->ats.array[at_i]].line;
- status = controller_dynamic_append_terminated(entry->items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
+ status = f_string_dynamic_append_nulless(entry->items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global->main->error, cache->action, F_status_set_fine(status), "controller_dynamic_append_terminated", F_true, global->thread);
+ controller_entry_print_error(is_entry, global->main->error, cache->action, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true, global->thread);
return status;
}
cache->action.line_item = entry->items.array[cache->ats.array[at_i]].line;
cache->action.name_item.used = 0;
- status = controller_dynamic_append_terminated(entry->items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
+ status = f_string_dynamic_append_nulless(entry->items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global->main->error, cache->action, F_status_set_fine(status), "controller_dynamic_append_terminated", F_true, global->thread);
+ controller_entry_print_error(is_entry, global->main->error, cache->action, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true, global->thread);
break;
}
break;
}
- status = controller_dynamic_partial_append_terminated(cache->buffer_file, cache->object_items.array[i], &cache->action.name_item);
+ status = f_string_dynamic_partial_append(cache->buffer_file, cache->object_items.array[i], &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "controller_dynamic_partial_append_terminated", F_true, global.thread);
+ controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "f_string_dynamic_partial_append", F_true, global.thread);
+
break;
}
if (F_status_is_error(status)) {
controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "f_fss_count_lines", F_true, global.thread);
+
break;
}
entry->items.array[at].line = cache->action.line_item;
- status = controller_dynamic_append_terminated(cache->action.name_item, &entry->items.array[at].name);
+ status = f_string_dynamic_append_nulless(cache->action.name_item, &entry->items.array[at].name);
if (F_status_is_error(status)) {
- controller_print_error(global.thread, global.main->error, F_status_set_fine(status), "controller_dynamic_append_terminated", F_true);
+ controller_print_error(global.thread, global.main->error, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true);
break;
}
cache->action.line_action = action->line;
cache->action.line_item = entry->items.array[i].line;
- status = controller_dynamic_append_terminated(entry->items.array[i].name, &cache->action.name_item);
+ status = f_string_dynamic_append_nulless(entry->items.array[i].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_print_error(global.thread, global.main->error, F_status_set_fine(status), "controller_dynamic_append_terminated", F_true);
+ controller_print_error(global.thread, global.main->error, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true);
break;
}
line = ++cache->action.line_action;
cache->action.name_action.used = 0;
- status = controller_dynamic_rip_nulless_terminated(cache->buffer_file, cache->object_actions.array[i], &cache->action.name_action);
+ status = fl_string_dynamic_partial_rip_nulless(cache->buffer_file, cache->object_actions.array[i], &cache->action.name_action);
if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "controller_dynamic_rip_nulless_terminated", F_true, global.thread);
+ controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "fl_string_dynamic_partial_rip_nulless", F_true, global.thread);
break;
}
cache->action.generic.used = 0;
global.setting->path_control.used = 0;
- status = controller_dynamic_rip_nulless_terminated(cache->buffer_file, cache->content_actions.array[i].array[0], &global.setting->path_control);
+ status = fl_string_dynamic_partial_rip_nulless(cache->buffer_file, cache->content_actions.array[i].array[0], &cache->action.generic);
if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "controller_dynamic_rip_nulless_terminated", F_true, global.thread);
+ controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "fl_string_dynamic_partial_rip_nulless", F_true, global.thread);
global.setting->path_control.used = 0;
break;
}
- if (f_path_is_relative(global.setting->path_control) == F_true) {
-
- // Use the PID file path for creating a relative path to the control socket.
- status = f_file_name_directory(global.setting->path_pid, &cache->action.generic);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "f_file_name_directory", F_true, global.thread);
-
- global.setting->path_control.used = 0;
-
- break;
- }
-
- status = f_string_dynamic_append(f_path_separator_s, &cache->action.generic);
-
- if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(global.setting->path_control, &cache->action.generic);
- }
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "f_string_dynamic_append", F_true, global.thread);
-
- global.setting->path_control.used = 0;
-
- break;
- }
- }
- else {
- status = f_string_dynamic_append(global.setting->path_control, &cache->action.generic);
-
- if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "f_string_dynamic_append", F_true, global.thread);
-
- global.setting->path_control.used = 0;
-
- break;
- }
- }
-
- status = fll_path_canonical(cache->action.generic, &global.setting->path_control);
+ status = controller_path_canonical_relative(global.setting, cache->action.generic, &global.setting->path_control);
if (F_status_is_error(status)) {
- controller_entry_print_error_file(is_entry, global.main->error, cache->action, F_status_set_fine(status), "fll_path_canonical", F_true, cache->action.generic, f_file_operation_analyze_s, fll_error_file_type_path_e, global.thread);
+ controller_entry_print_error_file(is_entry, global.main->error, cache->action, F_status_set_fine(status), "controller_path_canonical_relative", F_true, cache->action.generic, f_file_operation_analyze_s, fll_error_file_type_path_e, global.thread);
global.setting->path_control.used = 0;
cache->action.generic.used = 0;
- status = controller_dynamic_rip_nulless_terminated(cache->buffer_file, cache->content_actions.array[i].array[0], &cache->action.generic);
+ status = fl_string_dynamic_partial_rip_nulless(cache->buffer_file, cache->content_actions.array[i].array[0], &cache->action.generic);
if (F_status_is_error(status)) {
- controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "controller_dynamic_rip_nulless_terminated", F_true, global.thread);
+ controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "fl_string_dynamic_partial_rip_nulless", F_true, global.thread);
break;
}
continue;
}
}
+ else if (is_entry && fl_string_dynamic_compare(controller_pid_file_s, cache->action.name_action) == F_equal_to) {
+ if (cache->content_actions.array[i].used != 1) {
+ controller_entry_settings_read_print_setting_requires_exactly(global, is_entry, *cache, 1);
+
+ continue;
+ }
+
+ if (global.main->parameters.array[controller_parameter_pid_e].result == f_console_result_additional_e) {
+ controller_entry_settings_read_print_setting_ignored(global, is_entry, *cache, i);
+ }
+ else {
+ cache->action.generic.used = 0;
+
+ status = fl_string_dynamic_partial_rip_nulless(cache->buffer_file, cache->content_actions.array[i].array[0], &cache->action.generic);
+
+ if (F_status_is_error(status)) {
+ controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "fl_string_dynamic_partial_rip_nulless", F_true, global.thread);
+
+ continue;
+ }
+
+ global.setting->path_pid.used = 0;
+
+ status = controller_path_canonical_relative(global.setting, cache->action.generic, &global.setting->path_pid);
+
+ if (F_status_is_error(status)) {
+ controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "controller_path_canonical_relative", F_true, global.thread);
+
+ continue;
+ }
+ }
+ }
else if (fl_string_dynamic_compare(controller_session_s, cache->action.name_action) == F_equal_to) {
if (cache->content_actions.array[i].used != 1) {
controller_entry_settings_read_print_setting_requires_exactly(global, is_entry, *cache, 1);
* F_critical (with error bit) on any critical error.
* F_execute (with error bit) if the "execute" Item Action failed.
*
+ * Errors (with error bit) from: f_string_dynamic_append_nulless().
+ *
* Errors (with error bit) from: macro_f_array_lengths_t_increase_by().
* Errors (with error bit) from: controller_perform_ready().
- * Errors (with error bit) from: controller_dynamic_append_terminated().
+ *
+ * @see f_string_dynamic_append_nulless()
*
* @see macro_f_array_lengths_t_increase_by()
* @see controller_perform_ready()
- * @see controller_dynamic_append_terminated()
*/
#ifndef _di_controller_entry_process_
extern f_status_t controller_entry_process(const controller_global_t * const global, controller_cache_t * const cache, const bool failsafe, const bool is_entry) F_attribute_visibility_internal_d;
* Errors (with error bit) from: controller_entry_items_increase_by().
* Errors (with error bit) from: controller_file_load().
* Errors (with error bit) from: controller_status_simplify_error().
- * Errors (with error bit) from: controller_dynamic_append_terminated().
- * Errors (with error bit) from: controller_dynamic_partial_append_terminated().
+ *
* Errors (with error bit) from: f_fss_count_lines().
- * Errors (with error bit) from: fl_fss_apply_delimit().
* Errors (with error bit) from: f_string_dynamic_append().
+ * Errors (with error bit) from: f_string_dynamic_append_nulless().
+ * Errors (with error bit) from: f_string_dynamic_partial_append().
* Errors (with error bit) from: f_string_dynamic_partial_append_nulless().
* Errors (with error bit) from: f_string_dynamic_terminate().
+ * Errors (with error bit) from: fl_fss_apply_delimit().
* Errors (with error bit) from: fll_fss_basic_list_read().
*
* @see controller_entry_actions_read()
* @see controller_entry_items_increase_by()
* @see controller_file_load()
* @see controller_status_simplify_error()
- * @see controller_dynamic_append_terminated()
- * @see controller_dynamic_partial_append_terminated()
+ *
* @see f_fss_count_lines()
- * @see fl_fss_apply_delimit()
* @see f_string_dynamic_append()
+ * @see f_string_dynamic_append_nulless()
+ * @see f_string_dynamic_partial_append()
* @see f_string_dynamic_partial_append_nulless()
* @see f_string_dynamic_terminate()
+ * @see fl_fss_apply_delimit()
* @see fll_fss_basic_list_read()
*/
#ifndef _di_controller_entry_read_
* The range in the list buffer representing the content.
* @param cache
* A structure for containing and caching relevant data.
+ *
+ * Errors (with error bit) from: controller_entry_print_error_file().
+ *
+ * @see controller_entry_print_error_file()
*/
#ifndef _di_controller_entry_settings_read_
extern f_status_t controller_entry_settings_read(const controller_global_t global, const bool is_entry, const f_string_range_t content_range, controller_cache_t * const cache) F_attribute_visibility_internal_d;
}
#endif // _di_controller_entry_setting_read_print_error_with_range_
+#ifndef _di_controller_entry_settings_read_print_setting_ignored_
+ void controller_entry_settings_read_print_setting_ignored(const controller_global_t global, const bool is_entry, const controller_cache_t cache, const f_array_length_t index) {
+
+ if (global.main->warning.verbosity != f_console_verbosity_debug_e) return;
+
+ controller_lock_print(global.main->warning.to, global.thread);
+
+ fl_print_format("%r%[%QThe %Q item setting '%]", global.main->warning.to.stream, f_string_eol_s, global.main->warning.context, global.main->warning.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->warning.context);
+ fl_print_format("%[%Q%]", global.main->warning.to.stream, global.main->warning.notable, cache.action.name_action, global.main->warning.notable);
+ fl_print_format("%[' is being ignored.%]%r", global.main->warning.to.stream, global.main->warning.context, global.main->warning.context, f_string_eol_s);
+
+ controller_entry_print_error_cache(is_entry, global.main->warning, cache.action);
+
+ controller_unlock_print_flush(global.main->warning.to, global.thread);
+ }
+#endif // _di_controller_entry_settings_read_print_setting_ignored_
+
#ifndef _di_controller_entry_settings_read_print_setting_requires_exactly_
void controller_entry_settings_read_print_setting_requires_exactly(const controller_global_t global, const bool is_entry, const controller_cache_t cache, const f_number_unsigned_t total) {
fl_print_format("%r%[%QThe %Q item setting '%]", global.main->warning.to.stream, f_string_eol_s, global.main->warning.context, global.main->warning.prefix, is_entry ? controller_entry_s : controller_exit_s, global.main->warning.context);
fl_print_format("%[%Q%]", global.main->warning.to.stream, global.main->warning.notable, cache.action.name_action, global.main->warning.notable);
- fl_print_format("%[' has an unknown value '%]", global.main->warning.to.stream, f_string_eol_s, global.main->warning.context, global.main->warning.context);
- fl_print_format("%[%Q%]", global.main->warning.to.stream, global.main->warning.notable, cache.content_actions.array[index].array[0], global.main->warning.notable);
+ fl_print_format("%[' has an unknown value '%]", global.main->warning.to.stream, global.main->warning.context, global.main->warning.context);
+ fl_print_format("%[%/Q%]", global.main->warning.to.stream, global.main->warning.notable, cache.buffer_file, cache.content_actions.array[index].array[0], global.main->warning.notable);
fl_print_format("%['.%]%r", global.main->warning.to.stream, global.main->warning.context, global.main->warning.context, f_string_eol_s);
controller_entry_print_error_cache(is_entry, global.main->warning, cache.action);
#endif // _di_controller_entry_setting_read_print_error_with_range_
/**
+ * Print a message for when an entry setting is being ignored.
+ *
+ * @param global
+ * The global data.
+ * @param is_entry
+ * If TRUE, then this loads as an entry.
+ * If FALSE, then this loads as an exit.
+ * @param cache
+ * A structure for containing and caching relevant data.
+ * @param total
+ * The expected number of arguments.
+ */
+#ifndef _di_controller_entry_settings_read_print_setting_ignored_
+ extern void controller_entry_settings_read_print_setting_ignored(const controller_global_t global, const bool is_entry, const controller_cache_t cache, const f_array_length_t index) F_attribute_visibility_internal_d;
+#endif // _di_controller_entry_settings_read_print_setting_ignored_
+
+/**
* Print a message for when an entry setting action has the incorrect number of parameters.
*
* @param global
return F_status_set_error(F_file_found);
}
- status = controller_dynamic_append_terminated(pid_file, child_pid_file);
+ status = f_string_dynamic_append_nulless(pid_file, child_pid_file);
if (F_status_is_error(status)) {
- controller_print_error(thread, main->error, F_status_set_fine(status), "controller_dynamic_append_terminated", F_true);
+ controller_print_error(thread, main->error, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true);
return status;
}
cache->action.line_action += ++item->line;
cache->action.name_action.used = 0;
- status = controller_dynamic_rip_nulless_terminated(cache->buffer_item, cache->range_action, &cache->action.name_action);
+ status = fl_string_dynamic_partial_rip_nulless(cache->buffer_item, cache->range_action, &cache->action.name_action);
if (F_status_is_error(status)) {
- controller_print_error(global.thread, global.main->error, F_status_set_fine(status), "controller_dynamic_rip_nulless_terminated", F_true);
+ controller_print_error(global.thread, global.main->error, F_status_set_fine(status), "fl_string_dynamic_partial_rip_nulless", F_true);
break;
}
rule->items.array[rule->items.used].line = ++cache->action.line_item;
- status = controller_dynamic_rip_nulless_terminated(cache->buffer_file, cache->object_items.array[i], &cache->action.name_item);
+ status = fl_string_dynamic_partial_rip_nulless(cache->buffer_file, cache->object_items.array[i], &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_print_error(global.thread, global.main->error, F_status_set_fine(status), "controller_dynamic_rip_nulless_terminated", F_true);
+ controller_print_error(global.thread, global.main->error, F_status_set_fine(status), "fl_string_dynamic_partial_rip_nulless", F_true);
break;
}
}
if (type == controller_rule_setting_type_name_e || type == controller_rule_setting_type_script_e) {
- status = controller_dynamic_rip_nulless_terminated(cache->buffer_item, cache->content_actions.array[i].array[0], setting_value);
+ status = fl_string_dynamic_partial_rip_nulless(cache->buffer_item, cache->content_actions.array[i].array[0], setting_value);
if (F_status_is_error(status)) {
setting_value->used = 0;
cache->action.generic.used = 0;
- status = controller_dynamic_rip_nulless_terminated(cache->buffer_item, cache->content_actions.array[i].array[1], &cache->action.generic);
+ status = fl_string_dynamic_partial_rip_nulless(cache->buffer_item, cache->content_actions.array[i].array[1], &cache->action.generic);
if (F_status_is_error(status)) {
- controller_print_error(global.thread, global.main->error, F_status_set_fine(status), "controller_dynamic_rip_nulless_terminated", F_true);
+ controller_print_error(global.thread, global.main->error, F_status_set_fine(status), "fl_string_dynamic_partial_rip_nulless", F_true);
break;
}
* Errors (with error bit) from: f_string_dynamics_increase().
* Errors (with error bit) from: f_string_maps_increase().
* Errors (with error bit) from: fll_fss_extended_read().
- * Errors (with error bit) from: fll_path_canonical().
+ *
+ * Errors (with error bit) from: controller_path_canonical_relative().
*
* @see f_string_dynamic_partial_append_nulless()
* @see f_string_dynamics_increase()
* @see f_string_maps_increase()
* @see fl_string_dynamic_partial_rip_nulless()
* @see fll_fss_extended_read()
- * @see fll_path_canonical()
+ *
+ * @see controller_path_canonical_relative()
*/
#ifndef _di_controller_rule_setting_read_
extern f_status_t controller_rule_setting_read(const controller_global_t global, const bool is_normal, const controller_setting_t setting, controller_cache_t * const cache, controller_rule_t * const rule) F_attribute_visibility_internal_d;
# fss-0005
+setting:
+ control controller/run/up.socket
+ pid ready
+ pid_file controller/run/up.pid
+
main:
failsafe maintenance
+ start script create_socket_path
+
ready
maintenance:
--- /dev/null
+# fss-000d
+
+setting:
+ name "Create Socket Path"
+
+ parameter verbose -v
+ parameter socket controller/run/
+
+script:
+ start {
+ if [[ ! -d "parameter:"socket"" ]] ; then
+ mkdir parameter:"verbose" -p parameter:"socket"
+ fi
+ }
- The "setting" item Object\:
Represents settings and is not an "item" that can be executed.
A number of settings are supported, but if this Item Object is not specified, then defaults are used.
- The following settings are available: "mode", "pid", "session", and "show".
+ The following settings are available: "mode", "pid", "pid_file", "session", and "show".
- The "mode" setting\:
Represents the mode in which the Entry is operating in.
For "require", check to see if the PID file exists for an entry at startup and then when "ready" create a pid file, display error on pid file already exists or on failure and then fail.
For "ready", when "ready" create a pid file, display error on failure and then fail (does not check if PID file exists).
+ - The "pid_file" setting\:
+ When "pid" is not disabed this represents the path to the pid file.
+ If -p or --pid is passed to the controller program, then this value is ignored in favor of the value passed along the command line.
+
- The "session" setting\:
Represents the default way in which child processes are executed.
This default can be overriden by individual Rules.
This should be possible in the cases of file systems that have pre-created a socket file at the designated path.
When "readonly", the group, mode, and user are also not processed effectively resulting in the "control_group", "control_mode", and "control_user" settings being ignored.
+ Future versions might expand this into supporting network addresses in addition to socket files.
+
- The "control_group" setting\:
Represents the group name or group ID to assign to the socket file as the group.
- "name": A name used to represent this rule, which is printed to the user, screen, logs, etc...
- "nice": A single niceness value to run all processes executed within this rule as (-20 gets to be greediest in CPU usage and 19 being the nicest in CPU usage).
- "on": Define a Rule Action in which a specified dependency is needed, wanted, or wished for.
- - "parameter": A statically defined IKI name and its associated value for use in this rule file. @todo make sure this is implemented and make sure to perform iki substitutions (with "define" being a reserved iki parameter name for environment variable usage, such as define:"PATH").
+ - "parameter": A statically defined IKI name and its associated value for use in this rule file.
- "path": A single Content used to set a custom PATH environment variable value.
- "script": An executable name of a script, such as "bash", to use for the "script" Rule Type (which likely defaults to "bash" if not specified).
- "scheduler": A valid name of a scheduler to use followed by an optional priority number.
These parameters are only exposed in the specific rule file in which they are defined and cannot be shared between rules.
A "parameter" variable and an "environment" variable are mutually exclusive but an environment variable, in theory, can have an IKI variable assigned to it inside of a "script".
These IKI variables are only substituted within a Rule Item's Content (and not within a Rule Setting nor within a Rule Item's Object).
- Note: IKI variables are not yet implemented.
- In the case of "scheduler"\:
The valid range of the priority number is dependent on the scheduler.
- "setting": optional, Actions may be one of\:
- "mode": Exactly one Content that is one of "program" or "service".
- "pid": Exactly one Content that is one of "disable", "require", or "ready".
+ - "pid_file": Exactly one Content that is a relative or absolute path to a pid file.
- "session": Exactly one Content that is one of "new" or "same".
- "show": Exactly one Content that is one of "normal" or "init".
- "control": One to two Content.