]> Kevux Git Server - fll/commitdiff
Progress: controller.
authorKevin Day <thekevinday@gmail.com>
Sun, 22 Nov 2020 03:44:11 +0000 (21:44 -0600)
committerKevin Day <thekevinday@gmail.com>
Sun, 22 Nov 2020 03:44:11 +0000 (21:44 -0600)
In particular, this adds most of the settings loading information.
There is more work to do in this regard.

level_3/controller/c/controller.c
level_3/controller/c/controller.h
level_3/controller/c/private-control.c [new file with mode: 0644]
level_3/controller/c/private-control.h [new file with mode: 0644]
level_3/controller/c/private-rule.c
level_3/controller/c/private-rule.h
level_3/controller/data/build/dependencies
level_3/controller/data/build/settings
level_3/controller/documents/rule.txt
level_3/controller/specifications/rule.txt

index dd3d041d9d20504aac0ec9d744efc38791fb53d1..a469219ed732c7175c6997cb895bb6ce080fcc0a 100644 (file)
@@ -26,6 +26,7 @@ extern "C" {
 
     fll_program_print_help_option(output, context, controller_short_interruptable, controller_long_interruptable, f_console_symbol_short_enable, f_console_symbol_long_enable, "     Designate that this program can be interrupted.");
     fll_program_print_help_option(output, context, controller_short_settings, controller_long_settings, f_console_symbol_short_enable, f_console_symbol_long_enable, "     Specify a custom settings path.");
+    fll_program_print_help_option(output, context, controller_short_test, controller_long_test, f_console_symbol_short_enable, f_console_symbol_long_enable, "     Run in test mode, where nothing is actually run (a simulation).");
 
     fll_program_print_help_usage(output, context, controller_name, "");
 
index 6b258f8053c597feca3dde69a9398db0b6b2d26f..0e9b15fb7a3f7c4a6eb7c4c25d2a721768453269 100644 (file)
@@ -28,6 +28,7 @@
 #include <level_0/directory.h>
 #include <level_0/file.h>
 #include <level_0/fss.h>
+#include <level_0/path.h>
 #include <level_0/pipe.h>
 #include <level_0/print.h>
 
@@ -43,6 +44,7 @@
 #include <level_2/fss_basic_list.h>
 #include <level_2/fss_extended.h>
 #include <level_2/fss_extended_list.h>
+#include <level_2/path.h>
 #include <level_2/program.h>
 
 #ifdef __cplusplus
@@ -71,6 +73,8 @@ extern "C" {
   #define controller_string_environment "environment"
   #define controller_string_group       "group"
   #define controller_string_name        "name"
+  #define controller_string_need        "need"
+  #define controller_string_path        "path"
   #define controller_string_pid         "pid"
   #define controller_string_restart     "restart"
   #define controller_string_reload      "reload"
@@ -83,6 +87,8 @@ extern "C" {
   #define controller_string_stop        "stop"
   #define controller_string_use         "use"
   #define controller_string_user        "user"
+  #define controller_string_want        "want"
+  #define controller_string_wish        "wish"
 
   #define controller_string_create_length      6
   #define controller_string_command_length     7
@@ -93,6 +99,8 @@ extern "C" {
   #define controller_string_environment_length 11
   #define controller_string_group_length       5
   #define controller_string_name_length        4
+  #define controller_string_need_length        4
+  #define controller_string_path_length        4
   #define controller_string_pid_length         3
   #define controller_string_restart_length     7
   #define controller_string_reload_length      6
@@ -105,6 +113,8 @@ extern "C" {
   #define controller_string_stop_length        4
   #define controller_string_use_length         3
   #define controller_string_user_length        4
+  #define controller_string_want_length        4
+  #define controller_string_wish_length        4
 
   #define controller_path_settings "/etc/controller"
 
@@ -112,9 +122,11 @@ extern "C" {
 
   #define controller_short_interruptable "i"
   #define controller_short_settings      "s"
+  #define controller_short_test          "t"
 
   #define controller_long_interruptable "interruptable"
   #define controller_long_settings      "settings"
+  #define controller_long_test          "test"
 
   enum {
     controller_parameter_help,
@@ -129,6 +141,7 @@ extern "C" {
 
     controller_parameter_interruptable,
     controller_parameter_settings,
+    controller_parameter_test,
   };
 
   #define controller_console_parameter_t_initialize \
@@ -144,9 +157,10 @@ extern "C" {
       f_console_parameter_t_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, 0, f_console_type_inverse), \
       f_console_parameter_t_initialize(controller_short_interruptable, controller_long_interruptable, 0, 0, f_console_type_normal), \
       f_console_parameter_t_initialize(controller_short_settings, controller_long_settings, 0, 1, f_console_type_normal), \
+      f_console_parameter_t_initialize(controller_short_test, controller_long_test, 0, 0, f_console_type_normal), \
     }
 
-  #define controller_total_parameters 11
+  #define controller_total_parameters 12
 #endif // _di_controller_defines_
 
 #ifndef _di_controller_rule_action_t_
@@ -295,6 +309,7 @@ extern "C" {
 
     f_string_dynamic_t id;
     f_string_dynamic_t name;
+    f_string_dynamic_t path;
     f_string_dynamic_t pid;
 
     f_string_maps_t defines;
@@ -313,6 +328,7 @@ extern "C" {
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
+      f_string_dynamic_t_initialize, \
       f_string_maps_t_initialize, \
       f_string_dynamics_t_initialize, \
       f_string_dynamics_t_initialize, \
@@ -324,6 +340,7 @@ extern "C" {
   #define f_macro_controller_rule_t_delete_simple(setting) \
     f_string_dynamic_t_delete_simple(setting.id) \
     f_string_dynamic_t_delete_simple(setting.name) \
+    f_string_dynamic_t_delete_simple(setting.path) \
     f_string_dynamic_t_delete_simple(setting.pid) \
     f_string_maps_t_delete_simple(setting.defines) \
     f_string_dynamics_t_delete_simple(setting.environments) \
diff --git a/level_3/controller/c/private-control.c b/level_3/controller/c/private-control.c
new file mode 100644 (file)
index 0000000..24d836a
--- /dev/null
@@ -0,0 +1,10 @@
+#include "controller.h"
+#include "private-control.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_3/controller/c/private-control.h b/level_3/controller/c/private-control.h
new file mode 100644 (file)
index 0000000..3bcc4e2
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+ * FLL - Level 3
+ *
+ * Project: Controller
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ */
+#ifndef _PRIVATE_control_h
+#define _PRIVATE_control_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_control_h
index a46a91f6b936f90308f8b6036187e8345b5e29cb..ad3d45aa511eb7e8f794ba71f2dd279dfc24ecbc 100644 (file)
@@ -105,10 +105,6 @@ extern "C" {
         }
       }
 
-      if (F_status_is_error(status)) {
-        controller_rule_error_print(data.error, *cache);
-      }
-
       return status;
     }
 
@@ -220,15 +216,12 @@ extern "C" {
       }
     }
 
-    if (F_status_is_error(status)) {
-      controller_rule_error_print(data.error, *cache);
-    }
-    else if (status == F_data_not) {
+    if (F_status_is_error_not(status) && status == F_data_not) {
       if (data.warning.verbosity == f_console_verbosity_debug) {
         fprintf(data.warning.to.stream, "%c", f_string_eol[0]);
         fprintf(data.warning.to.stream, "%s%sAction is empty, nothing to do.%s%c", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : "", data.warning.context.after->string, f_string_eol[0]);
 
-        controller_rule_error_print(data.warning, *cache);
+        controller_rule_error_print(data.warning, *cache, F_true);
       }
     }
 
@@ -237,13 +230,13 @@ extern "C" {
 #endif // _di_controller_rule_actions_read_
 
 #ifndef _di_controller_rule_error_print_
-  void controller_rule_error_print(const fll_error_print_t output, const controller_rule_cache_t cache) {
+  void controller_rule_error_print(const fll_error_print_t output, const controller_rule_cache_t cache, const bool item) {
 
     if (output.verbosity != f_console_verbosity_quiet) {
       fprintf(output.to.stream, "%s%sWhile processing ", output.context.before->string, output.prefix ? output.prefix : "");
 
       if (cache.name_action.used) {
-        fprintf(output.to.stream, "action '");
+        fprintf(output.to.stream, "%s '", item ? "action" : "value");
         fprintf(output.to.stream, "%s%s%s%s", output.context.after->string, output.notable.before->string, cache.name_action.string, output.notable.after->string);
         fprintf(output.to.stream, "%s' on line ", output.context.before->string);
         fprintf(output.to.stream, "%s%s%llu%s", output.context.after->string, output.notable.before->string, cache.line_action, output.notable.after->string);
@@ -251,7 +244,7 @@ extern "C" {
       }
 
       if (cache.name_item.used) {
-        fprintf(output.to.stream, "item '");
+        fprintf(output.to.stream, "%s '", item ? "item" : "setting");
         fprintf(output.to.stream, "%s%s%s%s", output.context.after->string, output.notable.before->string, cache.name_item.string, output.notable.after->string);
         fprintf(output.to.stream, "%s' on line ", output.context.before->string);
         fprintf(output.to.stream, "%s%s%llu%s", output.context.after->string, output.notable.before->string, cache.line_item, output.notable.after->string);
@@ -306,10 +299,10 @@ extern "C" {
         cache->delimits.used = 0;
 
         // The current line is not an Extended List object, so the next possibility is a Basic List (and Extended List, both use the same Object structure).
-        status = fl_fss_basic_object_read(cache->buffer_item, &range, &cache->range_action, &quote, &cache->delimits);
+        status = fl_fss_extended_object_read(cache->buffer_item, &range, &cache->range_action, &quote, &cache->delimits);
 
         if (F_status_is_error(status)) {
-          fll_error_print(data.error, F_status_set_fine(status), "fl_fss_basic_object_read", F_true);
+          fll_error_print(data.error, F_status_set_fine(status), "fl_fss_extended_object_read", F_true);
           break;
         }
       }
@@ -390,7 +383,7 @@ extern "C" {
             fprintf(data.warning.to.stream, "%c", f_string_eol[0]);
             fprintf(data.warning.to.stream, "%s%sUnknown action type.%s%c", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : "", data.warning.context.after->string, f_string_eol[0]);
 
-            controller_rule_error_print(data.warning, *cache);
+            controller_rule_error_print(data.warning, *cache, F_true);
           }
 
           continue;
@@ -418,10 +411,6 @@ extern "C" {
       }
     } // for
 
-    if (F_status_is_error(status)) {
-      controller_rule_error_print(data.error, *cache);
-    }
-
     return status;
   }
 #endif // _di_controller_rule_item_read_
@@ -452,9 +441,22 @@ extern "C" {
   f_return_status controller_rule_read(const controller_data_t data, const f_string_static_t rule_id, controller_rule_cache_t *cache, controller_rule_t *rule) {
     f_status_t status = F_none;
 
+    bool for_item = F_true;
+
+    rule->status = F_unknown;
+
     rule->id.used = 0;
+    rule->name.used = 0;
+    rule->pid.used = 0;
+
+    rule->defines.used = 0;
+
+    rule->environment.used = 0;
+    rule->need.used = 0;
+    rule->want.used = 0;
+    rule->wish.used = 0;
+
     rule->items.used = 0;
-    rule->status = F_unknown;
 
     cache->comments.used = 0;
     cache->delimits.used = 0;
@@ -529,6 +531,7 @@ extern "C" {
           cache->delimits.used = 0;
 
           cache->content_action.used = 0;
+          cache->contents_action.used = 0;
           cache->objects_action.used = 0;
 
           cache->buffer_item.used = 0;
@@ -537,6 +540,8 @@ extern "C" {
           cache->name_file.used = 0;
           cache->name_item.used = 0;
 
+          for_item = F_true;
+
           status = f_fss_count_lines(cache->buffer_items, cache->range_item.start, &cache->line_item);
 
           if (F_status_is_error(status)) {
@@ -584,7 +589,7 @@ extern "C" {
               fprintf(data.warning.to.stream, "%c", f_string_eol[0]);
               fprintf(data.warning.to.stream, "%s%sUnknown item type.%s%c", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : "", data.warning.context.after->string, f_string_eol[0]);
 
-              controller_rule_error_print(data.warning, *cache);
+              controller_rule_error_print(data.warning, *cache, F_true);
             }
 
             continue;
@@ -597,8 +602,9 @@ extern "C" {
             rule->items.used++;
           }
           else {
-            status = controller_rule_setting_read(data, cache, rule);
-            if (F_status_is_error(status)) break;
+            for_item = F_false;
+
+            controller_rule_setting_read(data, cache, rule);
           }
         } // for
       }
@@ -607,9 +613,9 @@ extern "C" {
     if (F_status_is_error(status)) {
       status = F_status_set_fine(status);
 
-      controller_rule_error_print(data.error, *cache);
+      controller_rule_error_print(data.error, *cache, for_item);
 
-      if (status == F_memory_not) {
+      if (status == F_memory_not || status == F_memory_allocation || status == F_memory_reallocation) {
         rule->status = F_memory;
       }
       else if (status == F_file_open_max || status == F_space_not || status == F_busy) {
@@ -634,12 +640,261 @@ extern "C" {
 #endif // _di_controller_rule_read_
 
 #ifndef _di_controller_rule_setting_read_
-  f_return_status controller_rule_setting_read(const controller_data_t data, controller_rule_cache_t *cache, controller_rule_t *rule) {
+  void controller_rule_setting_read(const controller_data_t data, controller_rule_cache_t *cache, controller_rule_t *rule) {
     f_status_t status = F_none;
 
-    // @todo
+    f_string_range_t range = f_macro_string_range_t_initialize(cache->buffer_item.used);
+    f_string_range_t range2 = f_string_range_t_initialize;
 
-    return status;
+    f_fss_quote_t quote = 0;
+
+    status = fll_fss_extended_read(cache->buffer_item, &range, &cache->objects_action, &cache->contents_action, 0, 0, &cache->delimits, 0);
+
+    if (F_status_is_error(status)) {
+      fll_error_print(data.error, F_status_set_fine(status), "fll_fss_extended_read", F_true);
+      controller_rule_error_print(data.error, *cache, F_false);
+
+      return;
+    }
+
+    f_string_length_t path_original_length = 0;
+    f_string_dynamic_t *setting_value = 0;
+    f_string_dynamics_t *setting_values = 0;
+
+    f_array_length_t i = 0;
+    f_array_length_t j = 0;
+    uint8_t type = 0;
+
+    for (; i < cache->contents_action.used; ++i, type = 0) {
+
+      // name_item is used to store the setting name.
+      cache->name_item.used = 0;
+      status = fl_string_dynamic_partial_append_nulless(cache->buffer_item, cache->objects_action.array[i], &cache->name_item);
+
+      if (F_status_is_error(status)) {
+        fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append_nulless", F_true);
+        controller_rule_error_print(data.error, *cache, F_false);
+        continue;
+      }
+
+      if (fl_string_dynamic_compare_string(controller_string_define, cache->name_item, controller_string_define_length) == F_equal_to) {
+        type = 1;
+      }
+      else if (fl_string_dynamic_compare_string(controller_string_environment, cache->name_item, controller_string_environment_length) == F_equal_to) {
+        type = 2;
+      }
+      else if (fl_string_dynamic_compare_string(controller_string_name, cache->name_item, controller_string_name_length) == F_equal_to) {
+        type = 3;
+      }
+      else if (fl_string_dynamic_compare_string(controller_string_need, cache->name_item, controller_string_need_length) == F_equal_to) {
+        type = 4;
+      }
+      else if (fl_string_dynamic_compare_string(controller_string_path, cache->name_item, controller_string_path_length) == F_equal_to) {
+        type = 5;
+      }
+      else if (fl_string_dynamic_compare_string(controller_string_pid, cache->name_item, controller_string_pid_length) == F_equal_to) {
+        type = 6;
+      }
+      else if (fl_string_dynamic_compare_string(controller_string_want, cache->name_item, controller_string_want_length) == F_equal_to) {
+        type = 7;
+      }
+      else if (fl_string_dynamic_compare_string(controller_string_wish, cache->name_item, controller_string_wish_length) == F_equal_to) {
+        type = 8;
+      }
+      else {
+        if (data.warning.verbosity == f_console_verbosity_debug) {
+          fprintf(data.warning.to.stream, "%c", f_string_eol[0]);
+          fprintf(data.warning.to.stream, "%s%sUnknown rule setting.%s%c", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : "", data.warning.context.after->string, f_string_eol[0]);
+
+          controller_rule_error_print(data.warning, *cache, F_false);
+        }
+
+        continue;
+      }
+
+      if (!cache->contents_action.array[i].used) {
+        if (data.warning.verbosity == f_console_verbosity_debug) {
+          fprintf(data.warning.to.stream, "%c", f_string_eol[0]);
+          fprintf(data.warning.to.stream, "%s%sEmpty rule setting.%s%c", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : "", data.warning.context.after->string, f_string_eol[0]);
+
+          controller_rule_error_print(data.warning, *cache, F_false);
+        }
+
+        continue;
+      }
+
+      // name_action is used to store all setting values for a single setting.
+      cache->name_action.used = 0;
+
+      range2.start = cache->contents_action.array[i].array[0].start;
+      range2.stop = cache->contents_action.array[i].array[cache->contents_action.array[i].used - 1].stop;
+
+      status = fl_string_dynamic_partial_append_nulless(cache->buffer_item, range2, &cache->name_action);
+
+      if (F_status_is_error(status)) {
+        fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append_nulless", F_true);
+        controller_rule_error_print(data.error, *cache, F_false);
+        continue;
+      }
+
+      if (type == 1) {
+        if (cache->contents_action.array[i].used != 2) {
+          fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+          fprintf(data.error.to.stream, "%s%sRule setting requires exactly two Content.%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : "", data.error.context.after->string, f_string_eol[0]);
+
+          controller_rule_error_print(data.error, *cache, F_false);
+          continue;
+        }
+
+        rule->defines.array[rule->defines.used].name.used = 0;
+        rule->defines.array[rule->defines.used].value.used = 0;
+
+        status = fl_string_maps_increase(&rule->defines);
+
+        if (F_status_is_error(status)) {
+          fll_error_print(data.error, F_status_set_fine(status), "fl_string_maps_increase", F_true);
+          controller_rule_error_print(data.error, *cache, F_false);
+          continue;
+        }
+
+        status = fl_string_dynamic_partial_append_nulless(cache->buffer_item, cache->contents_action.array[i].array[0], &rule->defines.array[rule->defines.used].name);
+
+        if (F_status_is_error(status)) {
+          fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append_nulless", F_true);
+          controller_rule_error_print(data.error, *cache, F_false);
+          continue;
+        }
+
+        status = fl_string_dynamic_partial_append_nulless(cache->buffer_item, cache->contents_action.array[i].array[1], &rule->defines.array[rule->defines.used].value);
+
+        if (F_status_is_error(status)) {
+          fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append_nulless", F_true);
+          controller_rule_error_print(data.error, *cache, F_false);
+          continue;
+        }
+
+        rule->defines.used++;
+      }
+
+      if (type == 3 || type == 5 || type == 6) {
+        if (type == 3) {
+          setting_value = &rule->name;
+        }
+        else if (type == 5) {
+          setting_value = &rule->path;
+        }
+        else {
+          setting_value = &rule->pid;
+        }
+
+        if (type == 6) {
+          if (setting_value->used || cache->contents_action.array[i].used != 1) {
+            fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+            fprintf(data.error.to.stream, "%s%sRule setting requires exactly one Content.%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : "", data.error.context.after->string, f_string_eol[0]);
+
+            controller_rule_error_print(data.error, *cache, F_false);
+            continue;
+          }
+        }
+        else {
+          if (setting_value->used || cache->contents_action.array[i].used > 1) {
+            fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+            fprintf(data.error.to.stream, "%s%sRule setting requires no Content or exactly one Content.%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : "", data.error.context.after->string, f_string_eol[0]);
+
+            controller_rule_error_print(data.error, *cache, F_false);
+            continue;
+          }
+
+          if (!cache->contents_action.array[i].used) {
+            setting_value->used = 0;
+            continue;
+          }
+        }
+
+        status = fl_string_dynamic_partial_append_nulless(cache->buffer_item, cache->contents_action.array[i].array[0], setting_value);
+
+        if (F_status_is_error(status)) {
+          fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append_nulless", F_true);
+          controller_rule_error_print(data.error, *cache, F_false);
+          continue;
+        }
+
+        if (type == 3) {
+          // @todo validate must have at least 1 non-whitespace printing character.
+        }
+        else if (type == 6) {
+          path_original_length = setting_value->used;
+
+          // guarantee that path begins at the root.
+          if (!setting_value->used || setting_value->string[0] != f_path_separator[0]) {
+            path_original_length++;
+          }
+
+          char path_original[path_original_length + 1];
+
+          if (path_original_length == setting_value->used) {
+            memcpy(path_original, setting_value->string, setting_value->used);
+          }
+          else {
+            memcpy(path_original + 1, setting_value->string, setting_value->used - 1);
+            path_original[0] = f_path_separator[0];
+          }
+
+          path_original[path_original_length] = 0;
+
+          // force the path to be canonical (removing all '../' parts).
+          status = fll_path_canonical(path_original, setting_value);
+
+          if (F_status_is_error(status)) {
+            fll_error_print(data.error, F_status_set_fine(status), "fll_path_canonical", F_true);
+            controller_rule_error_print(data.error, *cache, F_false);
+            continue;
+          }
+        }
+
+        continue;
+      }
+
+      if (type == 2) {
+        setting_values = &rule->environment;
+      }
+      else if (type == 4) {
+        setting_values = &rule->need;
+      }
+      else if (type == 7) {
+        setting_values = &rule->want;
+      }
+      else {
+        setting_values = &rule->wish;
+      }
+
+      for (j = 0; j < cache->contents_action.array[i].used; ++j) {
+
+        status = fl_string_dynamics_increase(setting_values);
+
+        if (F_status_is_error(status)) {
+          fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamics_increase", F_true);
+          controller_rule_error_print(data.error, *cache, F_false);
+          continue;
+        }
+
+        setting_values->array[setting_values->used].used = 0;
+
+        status = fl_string_dynamic_partial_append_nulless(cache->buffer_item, cache->contents_action.array[i].array[j], &setting_values->array[setting_values->used]);
+
+        if (F_status_is_error(status)) {
+          fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append_nulless", F_true);
+          controller_rule_error_print(data.error, *cache, F_false);
+          continue;
+        }
+
+        if (type == 2) {
+          // @todo validate that this is a valid environment variable name: case-sensitive alpha-numeric or underscore, but no leading digits.
+        }
+
+        setting_values->used++;
+      } // for
+    } // for
   }
 #endif // _di_controller_rule_setting_read_
 
index 27c2c92e8ac6643efbdfc50a05a1c69f45babd02..b7ac4b355f85c479fe1b7a140f79a29d43fbf0e5 100644 (file)
@@ -164,13 +164,15 @@ extern "C" {
  *   The error or warning output structure.
  * @param cache
  *   A structure for containing and caching relevant data.
+ * @param item
+ *   If TRUE, then this error is associated with an item.
+ *   If FALSE, then this error is associated with a rule setting.
  *
  * @see controller_rule_actions_read()
  * @see controller_rule_items_read()
- * @see controller_rule_settings_read()
  */
 #ifndef _di_controller_rule_error_print_
-  void controller_rule_error_print(const fll_error_print_t output, const controller_rule_cache_t cache) f_gcc_attribute_visibility_internal;
+  void controller_rule_error_print(const fll_error_print_t output, const controller_rule_cache_t cache, const bool item) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_rule_error_print_
 
 /**
@@ -262,6 +264,8 @@ extern "C" {
  *
  * This will perform additional FSS read functions as appropriate.
  *
+ * Errors from this are not considered fatal, therefore errors may be printed but nothing is returned.
+ *
  * @param data
  *   The program data.
  * @param cache
@@ -269,15 +273,10 @@ extern "C" {
  * @param rule
  *   The processed rule.
  *
- * @return
- *   F_none on success.
- *
- *   Errors (with error bit) from: f_fss_count_lines().
- *
- * @see f_fss_count_lines()
+ * @todo consider making memory failures still critical errors, in which case a status does need to be returned.
  */
 #ifndef _di_controller_rule_setting_read_
-  extern f_return_status controller_rule_setting_read(const controller_data_t data, controller_rule_cache_t *cache, controller_rule_t *rule) f_gcc_attribute_visibility_internal;
+  extern void controller_rule_setting_read(const controller_data_t data, controller_rule_cache_t *cache, controller_rule_t *rule) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_rule_setting_read_
 
 #ifdef __cplusplus
index 977a55ca1361fddb8b4ce7f2d908f8632c783d0b..f33aaa7077f6f950cf82ae2256b77b8c569b75fe 100644 (file)
@@ -9,6 +9,7 @@ f_color
 f_console
 f_file
 f_fss
+f_path
 f_pipe
 f_print
 fl_color
@@ -17,5 +18,6 @@ fl_fss
 fl_string
 fll_error
 fll_fss
+fll_path
 fll_program
 fll_status
index 218975b5a2d8337d202acf7e80c37064c64bf3d8..01843e1c2e1d45853cfc7029b2154a5eeba39ccb 100644 (file)
@@ -19,10 +19,10 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfll_error -lfll_fss -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_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_status -lfl_string -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_utf
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
-build_sources_library controller.c private-controller.c private-entry.c private-rule.c
+build_sources_library controller.c private-control.c private-controller.c private-entry.c private-rule.c
 build_sources_program main.c
 build_sources_headers controller.h
 build_sources_script
index c6aff672ae4d259b6a89bac47cf61f74b69434e6..13a1c9281ec520f837c6ecf1a5bf47b41cc5c259 100644 (file)
@@ -11,7 +11,7 @@ Rule Documentation:
   The "settings" outer most list Object has the following FSS-0001 (Extended) Content:
     "define": Define a custom environment variable with a given variable, and automatically expose it to processes executed within this rule.
     "environment": A set of environment variables to expose to the processes executed within this rule (PATH is always exposed).
-    "name": A name used to represent this rule, which is printing to the user, screen, logs, etc.. (this is required).
+    "name": A name used to represent this rule, which is printing to the user, screen, logs, etc...
     "need": A list of relative rule path names that represent any given rule required to be executed (must exist and must succeed) before this rule starts.
     "path": A single Content used to set a custom PATH environment variable value.
     "pid": A path to a directory where the PID file is expected to be stored in.
index e2f072c4f0b2fc94c7422113e22cfb366162a8f5..471ce61d36cf0c54ad9cc4b818ce80bcb7571cb9 100644 (file)
@@ -16,7 +16,7 @@ Rule Specification:
   The "settings" outer most list Object has the following FSS-0001 (Extended) Content:
     "define": Two Content, the first Content must be a case-sensitive valid environment variable name (alpha-numeric or underscore, but no leading digits).
     "environment": Zero or more Content, each must be a case-sensitive valid environment variable name (alpha-numeric or underscore, but no leading digits).
-    "name": (Required) One Content, must have at least 1 non-whitespace printing character.
+    "name": Zero or One Content, must have at least 1 non-whitespace printing character.
     "need": Zero or more Content, each being a partial path and the rule file name without extension (such as "boot/modules").
     "path": Zero or One Content representing a valid PATH environment string (such as "/bin:/sbin:/usr/bin").
     "pid": One Content representing the full path to a PID file directory (such as "/var/run/service/ssh.pid").