]> Kevux Git Server - fll/commitdiff
Update: Get the control program in a better state and update the control/controller...
authorKevin Day <thekevinday@gmail.com>
Sat, 2 Apr 2022 22:48:44 +0000 (17:48 -0500)
committerKevin Day <thekevinday@gmail.com>
Sat, 2 Apr 2022 22:48:44 +0000 (17:48 -0500)
I started realizing that there were things that I forgot all about that the control and controller programs need to do.
This is too many changes to make immediately before the release.

Wrap up the control program into a tolerable state and it will be published as is.
Release notes will be used to document that this program didn't make the cut in time.

level_3/control/c/common.h
level_3/control/c/private-common.c
level_3/control/c/private-common.h
level_3/control/c/private-control.c
level_3/control/c/private-control.h
level_3/control/c/private-print.c
level_3/control/c/private-print.h
level_3/control/documents/packet_request.txt [new file with mode: 0644]
level_3/control/documents/packet_response.txt
level_3/controller/documents/packet.txt
level_3/controller/specifications/packet.txt

index 7c86200dda1a8b5d4c3ca1153eb2f06c8625cb36..7bd59a9ce539572079df150f59b5349fcfab70af 100644 (file)
@@ -184,7 +184,7 @@ extern "C" {
  * Identify the action code the given name represents.
  *
  * @param action
- *   The string representing a action.
+ *   The string representing an action.
  *
  * @return
  *   The action type code on success.
index 4c62cf9713cbbaa8d82311f68651a2b87c23bf17..40d4f548356d6334d1667f7e95b997627e3cc635 100644 (file)
@@ -17,13 +17,16 @@ extern "C" {
   const f_string_static_t control_path_settings_s = macro_f_string_static_t_initialize(CONTROL_path_settings_s, 0, CONTROL_path_settings_s_length);
 
   const f_string_static_t control_action_s = macro_f_string_static_t_initialize(CONTROL_action_s, 0, CONTROL_action_s_length);
+  const f_string_static_t control_at_s = macro_f_string_static_t_initialize(CONTROL_at_s, 0, CONTROL_at_s_length);
   const f_string_static_t control_controller_s = macro_f_string_static_t_initialize(CONTROL_controller_s, 0, CONTROL_controller_s_length);
   const f_string_static_t control_default_s = macro_f_string_static_t_initialize(CONTROL_default_s, 0, CONTROL_default_s_length);
   const f_string_static_t control_error_s = macro_f_string_static_t_initialize(CONTROL_error_s, 0, CONTROL_error_s_length);
+  const f_string_static_t control_in_s = macro_f_string_static_t_initialize(CONTROL_in_s, 0, CONTROL_in_s_length);
   const f_string_static_t control_init_s = macro_f_string_static_t_initialize(CONTROL_init_s, 0, CONTROL_init_s_length);
   const f_string_static_t control_kexec_s = macro_f_string_static_t_initialize(CONTROL_kexec_s, 0, CONTROL_kexec_s_length);
   const f_string_static_t control_length_s = macro_f_string_static_t_initialize(CONTROL_length_s, 0, CONTROL_length_s_length);
   const f_string_static_t control_name_socket_s = macro_f_string_static_t_initialize(CONTROL_name_socket_s, 0, CONTROL_name_socket_s_length);
+  const f_string_static_t control_now_s = macro_f_string_static_t_initialize(CONTROL_now_s, 0, CONTROL_now_s_length);
   const f_string_static_t control_path_socket_s = macro_f_string_static_t_initialize(CONTROL_path_socket_s, 0, CONTROL_path_socket_s_length);
   const f_string_static_t control_path_socket_prefix_s = macro_f_string_static_t_initialize(CONTROL_path_socket_prefix_s, 0, CONTROL_path_socket_prefix_s_length);
   const f_string_static_t control_path_socket_suffix_s = macro_f_string_static_t_initialize(CONTROL_path_socket_suffix_s, 0, CONTROL_path_socket_suffix_s_length);
index 19b9ed82ba619448600c8ef6ae4c064c471f0ace..649133e9437a4c5648885ed0a4b65ce8a47dfc8a 100644 (file)
@@ -128,13 +128,16 @@ extern "C" {
   #endif // defined(_override_control_path_settings_) && defined(_override_control_path_settings_length_)
 
   #define CONTROL_action_s             "action"
+  #define CONTROL_at_s                 "at"
   #define CONTROL_controller_s         "controller"
   #define CONTROL_default_s            "default"
   #define CONTROL_error_s              "error"
   #define CONTROL_kexec_s              "kexec"
+  #define CONTROL_in_s                 "in"
   #define CONTROL_init_s               "init"
   #define CONTROL_length_s             "length"
   #define CONTROL_name_socket_s        "name_socket"
+  #define CONTROL_now_s                "now"
   #define CONTROL_path_socket_s        "path_socket"
   #define CONTROL_path_socket_prefix_s "path_socket_prefix"
   #define CONTROL_path_socket_suffix_s "path_socket_suffix"
@@ -155,13 +158,16 @@ extern "C" {
   #define CONTROL_thaw_s     "thaw"
 
   #define CONTROL_action_s_length             6
+  #define CONTROL_at_s_length                 2
   #define CONTROL_controller_s_length         10
   #define CONTROL_default_s_length            7
   #define CONTROL_error_s_length              5
+  #define CONTROL_in_s_length                 2
   #define CONTROL_init_s_length               4
   #define CONTROL_kexec_s_length              5
   #define CONTROL_length_s_length             6
   #define CONTROL_name_socket_s_length        11
+  #define CONTROL_now_s_length                3
   #define CONTROL_path_socket_s_length        11
   #define CONTROL_path_socket_prefix_s_length 18
   #define CONTROL_path_socket_suffix_s_length 18
@@ -184,13 +190,16 @@ extern "C" {
   extern const f_string_static_t control_path_settings_s;
 
   extern const f_string_static_t control_action_s;
+  extern const f_string_static_t control_at_s;
   extern const f_string_static_t control_controller_s;
   extern const f_string_static_t control_default_s;
   extern const f_string_static_t control_error_s;
+  extern const f_string_static_t control_in_s;
   extern const f_string_static_t control_init_s;
   extern const f_string_static_t control_kexec_s;
   extern const f_string_static_t control_length_s;
   extern const f_string_static_t control_name_socket_s;
+  extern const f_string_static_t control_now_s;
   extern const f_string_static_t control_path_socket_s;
   extern const f_string_static_t control_path_socket_prefix_s;
   extern const f_string_static_t control_path_socket_suffix_s;
index da49a2ff6498c89ac01b1ede9447e4be14963706..9e3c30f3cee58ed579ce4fd2cc6081fdc133cd15 100644 (file)
@@ -21,19 +21,49 @@ extern "C" {
       case control_action_type_start_e:
       case control_action_type_stop_e:
       case control_action_type_thaw_e:
-        if (main->parameters.remaining.used < 2) {
+        if (main->parameters.remaining.used < 3) {
           control_print_error_parameter_action_rule_not(main, data->argv[main->parameters.remaining.array[0]]);
 
           return F_status_set_error(F_parameter);
         }
-        else if (main->parameters.remaining.used > 3) {
-          control_print_error_parameter_action_rule_too_many(main, data->argv[main->parameters.remaining.array[0]]);
 
-          return F_status_set_error(F_parameter);
+        if (main->parameters.remaining.used > 3) {
+          if (fl_string_dynamic_compare(control_at_s, data->argv[main->parameters.remaining.array[3]]) == F_equal_to) {
+            if (main->parameters.remaining.used < 5) {
+              control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s);
+
+              return F_status_set_error(F_parameter);
+            }
+
+            if (main->parameters.remaining.used > 5) {
+              control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s);
+
+              return F_status_set_error(F_parameter);
+            }
+          }
+          else if (fl_string_dynamic_compare(control_in_s, data->argv[main->parameters.remaining.array[3]]) == F_equal_to) {
+            if (main->parameters.remaining.used < 6) {
+              control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_in_s);
+
+              return F_status_set_error(F_parameter);
+            }
+          }
+          else if (fl_string_dynamic_compare(control_now_s, data->argv[main->parameters.remaining.array[3]]) == F_equal_to) {
+            if (main->parameters.remaining.used > 4) {
+              control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_now_s);
+
+              return F_status_set_error(F_parameter);
+            }
+          }
+          else {
+            control_print_error_parameter_action_rule_with_unknown(main, data->argv[main->parameters.remaining.array[0]], data->argv[main->parameters.remaining.array[2]]);
+
+            return F_status_set_error(F_parameter);
+          }
         }
 
         if (!data->argv[main->parameters.remaining.array[1]].used) {
-          if (main->parameters.remaining.used == 2) {
+          if (main->parameters.remaining.used == 3) {
             control_print_error_parameter_action_rule_empty(main, data->argv[main->parameters.remaining.array[0]]);
           }
           else {
@@ -52,36 +82,95 @@ extern "C" {
         }
 
         return F_none;
+
+      case control_action_type_kexec_e:
+      case control_action_type_reboot_e:
+      case control_action_type_shutdown_e:
+        if (main->parameters.remaining.used < 2) {
+          control_print_error_parameter_action_rule_too_few(main, data->argv[main->parameters.remaining.array[0]]);
+
+          return F_status_set_error(F_parameter);
+        }
+
+        if (fl_string_dynamic_compare(control_at_s, data->argv[main->parameters.remaining.array[1]]) == F_equal_to) {
+          if (main->parameters.remaining.used < 3) {
+            control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s);
+
+            return F_status_set_error(F_parameter);
+          }
+
+          if (main->parameters.remaining.used > 3) {
+            control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s);
+
+            return F_status_set_error(F_parameter);
+          }
+        }
+        else if (fl_string_dynamic_compare(control_in_s, data->argv[main->parameters.remaining.array[1]]) == F_equal_to) {
+          if (main->parameters.remaining.used < 4) {
+            control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_in_s);
+
+            return F_status_set_error(F_parameter);
+          }
+        }
+        else if (fl_string_dynamic_compare(control_now_s, data->argv[main->parameters.remaining.array[1]]) == F_equal_to) {
+          if (main->parameters.remaining.used > 2) {
+            control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_now_s);
+
+            return F_status_set_error(F_parameter);
+          }
+        }
+        else {
+          control_print_error_parameter_action_rule_with_unknown(main, data->argv[main->parameters.remaining.array[0]], data->argv[main->parameters.remaining.array[1]]);
+
+          return F_status_set_error(F_parameter);
+        }
     }
 
-    // Handle "kexec", "reboot", and "shutdown".
-    // @todo the reboot and shutdown need to support date and time actions: "now", "in (a time)", and "at (a time)".
-    return F_status_set_error(F_supported_not);
+    return F_none;
   }
 #endif // _di_control_action_verify_
 
 #ifndef _di_control_packet_build_
   f_status_t control_packet_build(const fll_program_data_t * const main, control_data_t * const data) {
 
+    data->cache.packet.used = 0;
     data->cache.large.used = 0;
     data->cache.small.used = 0;
 
     f_array_length_t i = 0;
-    f_array_length_t length = 5 + f_fss_string_header_s.used + f_fss_string_payload_s.used + control_action_s.used + control_type_s.used;
-    length += f_fss_payload_list_open_s.used * 2;
-    length += f_fss_payload_list_close_s.used * 4;
-    length += f_string_ascii_0_s.used;
+    f_status_t status = F_none;
 
-    for (; i < main->parameters.remaining.used; ++i) {
-      length += f_fss_payload_header_open_s.used + data->argv[main->parameters.remaining.array[i]].used + f_fss_payload_header_close_s.used;
-    } // for
+    {
+      f_array_length_t length = 5 + f_fss_string_header_s.used + f_fss_string_payload_s.used;
+      length += control_action_s.used + control_length_s.used + control_type_s.used;
+      length += (f_fss_payload_list_open_s.used + f_fss_payload_list_close_s.used) * 2;
+      length += (f_fss_payload_header_open_s.used + f_fss_payload_header_close_s.used) * 3;
+      length += data->argv[main->parameters.remaining.array[0]].used + f_string_ascii_0_s.used;
+
+      // @todo This should properly handle escaping the FSS-0001 (Extended) Content and then count that length.
+      for (i = 1; i < main->parameters.remaining.used; ++i) {
+        length += f_fss_payload_header_next_s.used + data->argv[main->parameters.remaining.array[i]].used;
+      } // for
+
+      if (data->action == control_action_type_kexec_e || data->action == control_action_type_reboot_e || data->action == control_action_type_shutdown_e) {
+        length += control_init_s.used;
+      }
+      else {
+        length += control_controller_s.used;
+      }
+
+      if (length > 0xffffffffu) {
+        return F_status_set_error(F_too_large);
+      }
 
-    if (length > 0xffffffffu) {
-      return F_status_set_error(F_too_large);
+      status = f_string_dynamic_resize(length, &data->cache.packet);
+      if (F_status_is_error(status)) return status;
     }
 
-    f_status_t status = f_string_dynamic_resize(length, &data->cache.large);
-    if (F_status_is_error(status)) return status;
+    const f_state_t state = macro_f_state_t_initialize(control_allocation_large_d, control_allocation_small_d, 0, &fll_program_standard_signal_state, 0, (void *) main, 0);
+
+    f_string_static_t contents_array[main->parameters.remaining.used];
+    f_string_statics_t contents = macro_f_string_statics_t_initialize(contents_array, 0, main->parameters.remaining.used);
 
     // The Packet Control Block.
     {
@@ -91,79 +180,63 @@ extern "C" {
         block_control |= (f_char_t) control_packet_flag_endian_big_d;
       #endif // _is_F_endian_big
 
-      status = f_string_append(&block_control, 1, &data->cache.large);
+      status = f_string_append(&block_control, 1, &data->cache.packet);
       if (F_status_is_error(status)) return status;
     }
 
-    // The Packet Size Block.
-    {
-      status = f_string_append((f_char_t *) &length, 1, &data->cache.large);
-      if (F_status_is_error(status)) return status;
-    }
-
-    // The Payload "header:" line.
-    status = f_string_dynamic_append(f_fss_string_header_s, &data->cache.large);
-    if (F_status_is_error(status)) return status;
-
-    status = f_string_dynamic_append(f_fss_payload_list_open_s, &data->cache.large);
-    if (F_status_is_error(status)) return status;
-
-    status = f_string_dynamic_append(f_fss_payload_list_close_s, &data->cache.large);
-    if (F_status_is_error(status)) return status;
+    // Reserve the Packet Size Block to be calculated later.
+    data->cache.packet.used = 5;
 
-    // The Payload "type ..." line.
-    status = f_string_dynamic_append(control_type_s, &data->cache.large);
-    if (F_status_is_error(status)) return status;
+    // Payload Header: type.
+    if (data->action == control_action_type_kexec_e || data->action == control_action_type_reboot_e || data->action == control_action_type_shutdown_e) {
+      contents_array[0] = control_init_s;
+    }
+    else {
+      contents_array[0] = control_controller_s;
+    }
 
-    status = f_string_dynamic_append(f_fss_payload_header_open_s, &data->cache.large);
-    if (F_status_is_error(status)) return status;
+    contents.used = 1;
 
-    status = f_string_dynamic_append(data->argv[main->parameters.remaining.array[0]], &data->cache.large);
+    status = fll_fss_extended_write_string(control_type_s, contents, 0, state, &data->cache.large);
     if (F_status_is_error(status)) return status;
 
-    status = f_string_dynamic_append(f_fss_payload_header_close_s, &data->cache.large);
-    if (F_status_is_error(status)) return status;
-
-    // Each Payload "action ..." line.
-    for (i = 1; i < main->parameters.remaining.used; ++i) {
-
-      status = f_string_dynamic_append(control_action_s, &data->cache.large);
-      if (F_status_is_error(status)) return status;
-
-      status = f_string_dynamic_append(f_fss_payload_header_open_s, &data->cache.large);
-      if (F_status_is_error(status)) return status;
-
-      status = f_string_dynamic_append(data->argv[main->parameters.remaining.array[i]], &data->cache.large);
-      if (F_status_is_error(status)) return status;
-
-      status = f_string_dynamic_append(f_fss_payload_header_close_s, &data->cache.large);
-      if (F_status_is_error(status)) return status;
+    // Payload Header: action.
+    for (contents.used = 0; contents.used < main->parameters.remaining.used; ++contents.used) {
+      contents_array[contents.used] = data->argv[main->parameters.remaining.array[contents.used]];
     } // for
 
-    // The Payload "length 0" line.
-    status = f_string_dynamic_append(control_length_s, &data->cache.large);
+    status = fll_fss_extended_write_string(control_action_s, contents, 0, state, &data->cache.large);
     if (F_status_is_error(status)) return status;
 
-    status = f_string_dynamic_append(f_fss_payload_header_open_s, &data->cache.large);
-    if (F_status_is_error(status)) return status;
-
-    status = f_string_dynamic_append(f_string_ascii_0_s, &data->cache.large);
-    if (F_status_is_error(status)) return status;
+    // Payload Header: length.
+    contents_array[0] = f_string_ascii_0_s;
+    contents.used = 1;
 
-    status = f_string_dynamic_append(f_fss_payload_header_close_s, &data->cache.large);
+    status = fll_fss_extended_write_string(control_length_s, contents, 0, state, &data->cache.large);
     if (F_status_is_error(status)) return status;
 
-    // The Payload "payload:" line.
-    status = f_string_dynamic_append(f_fss_string_payload_s, &data->cache.large);
+    // Payload Packet: Header.
+    status = fll_fss_payload_write_string(f_fss_string_header_s, data->cache.large, F_false, 0, state, &data->cache.packet);
     if (F_status_is_error(status)) return status;
 
-    status = f_string_dynamic_append(f_fss_payload_list_open_s, &data->cache.large);
-    if (F_status_is_error(status)) return status;
+    // Payload Packet: Payload.
+    data->cache.large.used = 0;
 
-    status = f_string_dynamic_append(f_fss_payload_list_open_end_s, &data->cache.large);
+    status = fll_fss_payload_write_string(f_fss_string_payload_s, data->cache.large, F_false, 0, state, &data->cache.packet);
     if (F_status_is_error(status)) return status;
 
-    // The Payload "payload:" Content is empty.
+    // Construct Packet Size Block.
+    #ifdef _is_F_endian_big
+      data->cache.packet.string[1] = data->cache.packet.used & 0xffu;
+      data->cache.packet.string[2] = data->cache.packet.used & 0xff00u;
+      data->cache.packet.string[3] = data->cache.packet.used & 0xff0000u;
+      data->cache.packet.string[4] = data->cache.packet.used & 0xff000000u;
+    #else
+      data->cache.packet.string[1] = data->cache.packet.used & 0xff000000u;
+      data->cache.packet.string[2] = data->cache.packet.used & 0xff0000u;
+      data->cache.packet.string[3] = data->cache.packet.used & 0xff00u;
+      data->cache.packet.string[4] = data->cache.packet.used & 0xffu;
+    #endif // _is_F_endian_big
 
     return F_none;
   }
@@ -530,145 +603,12 @@ extern "C" {
 #ifndef _di_control_packet_send_
   f_status_t control_packet_send(const fll_program_data_t * const main, control_data_t * const data) {
 
-    {
-      f_status_t status = F_none;
-      f_string_dynamic_t payload = f_string_dynamic_t_initialize;
-
-      switch (data->action) {
-        case control_action_type_freeze_e:
-        case control_action_type_kill_e:
-        case control_action_type_pause_e:
-        case control_action_type_reload_e:
-        case control_action_type_rerun_e:
-        case control_action_type_restart_e:
-        case control_action_type_resume_e:
-        case control_action_type_start_e:
-        case control_action_type_stop_e:
-        case control_action_type_thaw_e:
-          payload = data->argv[main->parameters.remaining.array[1]];
-          break;
-
-        default:
-          // @todo construct message for kexec, reboot, and shutdown.
-          break;
-      }
-
-      status = control_packet_send_build(main, data, control_controller_s, control_action_type_name(data->action), f_string_empty_s, payload);
-
-      f_string_dynamic_resize(0, &payload);
-
-      if (F_status_is_error(status)) return status;
-    }
-
     data->socket.size_write = data->cache.packet.used;
 
     return f_socket_write(&data->socket, 0, (void *) &data->cache.packet, 0);
   }
 #endif // _di_control_packet_send_
 
-#ifndef _di_control_packet_send_build_
-  f_status_t control_packet_send_build(const fll_program_data_t * const main, control_data_t * const data, const f_string_static_t type, const f_string_static_t action, const f_string_static_t status, const f_string_static_t payload) {
-
-    f_status_t status2 = F_none;
-
-    const f_state_t state = f_state_t_initialize;
-    const f_conversion_data_t data_conversion = macro_f_conversion_data_t_initialize(10, 0, 1);
-
-    f_string_statics_t content = f_string_statics_t_initialize;
-    f_string_static_t contents[1];
-    content.array = contents;
-    content.used = 1;
-
-    data->cache.large.used = 0;
-    data->cache.small.used = 0;
-    data->cache.packet.used = 0;
-
-    // Reserve space in data->cache.packet.size for the packet header as well as other parts.
-    {
-      // 5 for packet header and 2 for ':\n" for both 'header' and 'payload'.
-      f_array_length_t total = 9 + f_fss_string_header_s.used + f_fss_string_payload_s.used + control_length_s.used + payload.used;
-
-      if (type.used) {
-        total += control_type_s.used + type.used + 2;
-      }
-
-      if (action.used) {
-        total += control_action_s.used + action.used + 2;
-      }
-
-      if (status.used) {
-        total += control_status_s.used + status.used + 2;
-      }
-
-      status2 = f_string_dynamic_increase_by(total, &data->cache.packet);
-    }
-
-    #ifdef _is_F_endian_big
-      data->cache.packet.string[0] = control_packet_flag_endian_big_d;
-    #else
-      data->cache.packet.string[0] = 0;
-    #endif // _is_F_endian_big
-
-    data->cache.packet.used = 5;
-
-    // Payload Header: type.
-    if (type.used) {
-      contents[0] = type;
-
-      status2 = fll_fss_extended_write_string(control_type_s, content, 0, state, &data->cache.large);
-      if (F_status_is_error(status2)) return status2;
-    }
-
-    // Payload Header: action.
-    if (action.used) {
-      contents[0] = action;
-
-      status2 = fll_fss_extended_write_string(control_action_s, content, 0, state, &data->cache.large);
-      if (F_status_is_error(status2)) return status2;
-    }
-
-    // Payload Header: status.
-    if (status.used) {
-      contents[0] = status;
-
-      status2 = fll_fss_extended_write_string(control_status_s, content, 0, state, &data->cache.large);
-      if (F_status_is_error(status2)) return status2;
-    }
-
-    // Payload Header: length.
-    status2 = f_conversion_number_unsigned_to_string(payload.used, data_conversion, &data->cache.small);
-    if (F_status_is_error(status2)) return status2;
-
-    contents[0] = data->cache.small;
-
-    status2 = fll_fss_extended_write_string(control_length_s, content, 0, state, &data->cache.large);
-    if (F_status_is_error(status2)) return status2;
-
-    // Payload Packet: Header.
-    status2 = fll_fss_payload_write_string(f_fss_string_header_s, data->cache.large, F_false, 0, state, &data->cache.packet);
-    if (F_status_is_error(status2)) return status2;
-
-    // Payload Packet: Payload.
-    status2 = fll_fss_payload_write_string(f_fss_string_payload_s, payload, F_false, 0, state, &data->cache.packet);
-    if (F_status_is_error(status2)) return status2;
-
-    // Construct packet size.
-    #ifdef _is_F_endian_big
-      data->cache.packet.string[1] = data->cache.packet.used & 0xffu;
-      data->cache.packet.string[2] = data->cache.packet.used & 0xff00u;
-      data->cache.packet.string[3] = data->cache.packet.used & 0xff0000u;
-      data->cache.packet.string[4] = data->cache.packet.used & 0xff000000u;
-    #else
-      data->cache.packet.string[1] = data->cache.packet.used & 0xff000000u;
-      data->cache.packet.string[2] = data->cache.packet.used & 0xff0000u;
-      data->cache.packet.string[3] = data->cache.packet.used & 0xff00u;
-      data->cache.packet.string[4] = data->cache.packet.used & 0xffu;
-    #endif // _is_F_endian_big
-
-    return F_none;
-  }
-#endif // _di_control_packet_send_build_
-
 #ifndef _di_control_settings_load_
   f_status_t control_settings_load(const fll_program_data_t * const main, control_data_t * const data) {
 
index 7a303f42c4cf8f49a1e31cfd44a5d38dbc39b6cc..64429fb1c7589772c5c005aeb1c510c6171bfc80 100644 (file)
@@ -19,6 +19,11 @@ extern "C" {
  *   The main program data.
  * @param data
  *   The control data.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) on parameter validation/verification failure.
  */
 #ifndef _di_control_action_verify_
   extern f_status_t control_action_verify(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
@@ -40,6 +45,8 @@ extern "C" {
  *   Errors (with error bit) from: f_string_append().
  *   Errors (with error bit) from: f_string_dynamic_append().
  *   Errors (with error bit) from: f_string_dynamic_resize().
+ *   Errors (with error bit) from: fll_fss_extended_write_string().
+ *   Errors (with error bit) from: fll_fss_payload_write_string().
  *
  * @see f_string_append()
  * @see f_string_dynamic_append()
@@ -136,6 +143,7 @@ extern "C" {
  *
  *   F_busy (with error bit)
  *   F_failure (with error bit) on success but controller returned failure for action.
+ *   F_known_not (with error bit) if the Payload type is unknown.
  *   Any error (with error bit) on failure where the error is defined by the controller service.
  */
 #ifndef _di_control_packet_process_
@@ -149,51 +157,18 @@ extern "C" {
  *   The main program data.
  * @param data
  *   The control data.
- */
-#ifndef _di_control_packet_send_
-  extern f_status_t control_packet_send(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
-#endif // _di_control_packet_send_
-
-/**
- * Construct the entire payload.
- *
- * This resets and uses data->cache.small, data->cache.large, and data->cache.packet.
- * Do not use any of these for passing strings to this function.
- *
- * The results of this function replaces data->cache.packet.
- *
- * @param global
- *   The global data.
- * @param data
- *   The control data.
- * @param type
- *   The packet type.
- *   Set type.used to 0 to not add to the header.
- * @param action
- *   The action code.
- *   Set action.used to 0 to not add to the header.
- * @param status
- *   The status code.
- *   Set status.used to 0 to not add to the header.
- * @param payload
- *   The payload Content.
  *
  * @return
  *   F_none on success.
  *
- *   Errors (with error bit) from: f_conversion_number_unsigned_to_string().
- *   Errors (with error bit) from: f_string_append().
- *   Errors (with error bit) from: fll_fss_extended_write_string().
- *   Errors (with error bit) from: fll_fss_payload_write_string().
+ *   Errors (with error bit) from: f_socket_write().
  *
- * @see f_conversion_number_unsigned_to_string()
- * @see f_string_append()
- * @see fll_fss_extended_write_string()
- * @see fll_fss_payload_write_string()
+ * @see f_socket_write()
  */
-#ifndef _di_control_packet_send_build_
-  extern f_status_t control_packet_send_build(const fll_program_data_t * const main, control_data_t * const data, const f_string_static_t type, const f_string_static_t action, const f_string_static_t status, const f_string_static_t payload) F_attribute_visibility_internal_d;
-#endif // _di_control_packet_send_build_
+#ifndef _di_control_packet_send_
+  extern f_status_t control_packet_send(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
+#endif // _di_control_packet_send_
+
 /**
  * Load and process the control settings file.
  *
index 9acb7ecb484cf408463813fadae4c5b65687fd55..4963f400c57c1e9a200110f8b4a86962211e0da9 100644 (file)
@@ -224,6 +224,38 @@ extern "C" {
   }
 #endif // _di_control_print_error_parameter_action_rule_not_
 
+#ifndef _di_control_print_error_parameter_action_rule_too_few_
+  void control_print_error_parameter_action_rule_too_few(const fll_program_data_t * const main, const f_string_static_t action) {
+
+    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
+
+    flockfile(main->error.to.stream);
+
+    fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
+    fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable);
+    fl_print_format("%[' has too few arguments.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
+
+    funlockfile(main->error.to.stream);
+  }
+#endif // _di_control_print_error_parameter_action_rule_too_few_
+
+#ifndef _di_control_print_error_parameter_action_rule_too_few_with_
+  void control_print_error_parameter_action_rule_too_few_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) {
+
+    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
+
+    flockfile(main->error.to.stream);
+
+    fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
+    fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable);
+    fl_print_format("%[' when used with '%]", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
+    fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, with, main->context.set.notable);
+    fl_print_format("%[' has too few arguments.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
+
+    funlockfile(main->error.to.stream);
+  }
+#endif // _di_control_print_error_parameter_action_rule_too_few_with_
+
 #ifndef _di_control_print_error_parameter_action_rule_too_many_
   void control_print_error_parameter_action_rule_too_many(const fll_program_data_t * const main, const f_string_static_t action) {
 
@@ -239,6 +271,40 @@ extern "C" {
   }
 #endif // _di_control_print_error_parameter_action_rule_too_many_
 
+#ifndef _di_control_print_error_parameter_action_rule_too_many_with_
+  void control_print_error_parameter_action_rule_too_many_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) {
+
+    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
+
+    flockfile(main->error.to.stream);
+
+    fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
+    fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable);
+    fl_print_format("%[' when used with '%]", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
+    fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, with, main->context.set.notable);
+    fl_print_format("%[' has too many arguments.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
+
+    funlockfile(main->error.to.stream);
+  }
+#endif // _di_control_print_error_parameter_action_rule_too_many_with_
+
+#ifndef _di_control_print_error_parameter_action_rule_with_unknown_
+  void control_print_error_parameter_action_rule_with_unknown(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) {
+
+    if (main->error.verbosity == f_console_verbosity_quiet_e) return;
+
+    flockfile(main->error.to.stream);
+
+    fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
+    fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable);
+    fl_print_format("%[' does not know the argument '%]", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
+    fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, with, main->context.set.notable);
+    fl_print_format("%['.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
+
+    funlockfile(main->error.to.stream);
+  }
+#endif // _di_control_print_error_parameter_action_rule_with_unknown_
+
 #ifndef _di_control_print_error_parameter_value_empty_
   void control_print_error_parameter_value_empty(const fll_program_data_t * const main, const f_string_static_t parameter) {
 
index 23f3d2ede38c3d6a5d615318403e8141de0feabd..a7f62173fb330d048b8b83434e691a2a55717e86 100644 (file)
@@ -99,7 +99,7 @@ extern "C" {
  * @param main
  *   The main program data.
  * @param action
- *   The parameter representing a action.
+ *   The parameter representing an action.
  */
 #ifndef _di_control_print_error_parameter_action_not_
   extern void control_print_error_parameter_action_not(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
@@ -111,7 +111,7 @@ extern "C" {
  * @param main
  *   The main program data.
  * @param action
- *   The parameter representing a action.
+ *   The parameter representing an action.
  */
 #ifndef _di_control_print_error_parameter_action_rule_basename_empty_
   extern void control_print_error_parameter_action_rule_basename_empty(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
@@ -123,7 +123,7 @@ extern "C" {
  * @param main
  *   The main program data.
  * @param action
- *   The parameter representing a action.
+ *   The parameter representing an action.
  */
 #ifndef _di_control_print_error_parameter_action_rule_directory_empty_
   extern void control_print_error_parameter_action_rule_directory_empty(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
@@ -135,7 +135,7 @@ extern "C" {
  * @param main
  *   The main program data.
  * @param action
- *   The parameter representing a action.
+ *   The parameter representing an action.
  */
 #ifndef _di_control_print_error_parameter_action_rule_empty_
   extern void control_print_error_parameter_action_rule_empty(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
@@ -147,25 +147,78 @@ extern "C" {
  * @param main
  *   The main program data.
  * @param action
- *   The parameter representing a action.
+ *   The parameter representing an action.
  */
 #ifndef _di_control_print_error_parameter_action_rule_not_
   extern void control_print_error_parameter_action_rule_not(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
 #endif // _di_control_print_error_parameter_action_rule_not_
 
 /**
+ * Print an error message about the given parameter being a rule action having too few arguments passed.
+ *
+ * @param main
+ *   The main program data.
+ * @param action
+ *   The parameter representing an action.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_too_few_
+  extern void control_print_error_parameter_action_rule_too_few(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
+#endif // _di_control_print_error_parameter_action_rule_too_few_
+
+/**
+ * Print an error message about the given parameter being a rule action having few many arguments passed for a given "with".
+ *
+ * @param main
+ *   The main program data.
+ * @param action
+ *   The parameter representing an action.
+ * @param with
+ *   The additional parameter in which is requiring additional arguments that are not met.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_too_few_with_
+  extern void control_print_error_parameter_action_rule_too_few_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) F_attribute_visibility_internal_d;
+#endif // _di_control_print_error_parameter_action_rule_too_few_with_
+
+/**
  * Print an error message about the given parameter being a rule action having too many arguments passed.
  *
  * @param main
  *   The main program data.
  * @param action
- *   The parameter representing a action.
+ *   The parameter representing an action.
  */
 #ifndef _di_control_print_error_parameter_action_rule_too_many_
   extern void control_print_error_parameter_action_rule_too_many(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
 #endif // _di_control_print_error_parameter_action_rule_too_many_
 
 /**
+ * Print an error message about the given parameter being a rule action having too many arguments passed for a given "with".
+ *
+ * @param main
+ *   The main program data.
+ * @param action
+ *   The parameter representing an action.
+ * @param with
+ *   The additional parameter in which is requiring additional arguments that are not met.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_too_many_with_
+  extern void control_print_error_parameter_action_rule_too_many_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) F_attribute_visibility_internal_d;
+#endif // _di_control_print_error_parameter_action_rule_too_many_with_
+/**
+ * Print an error message about the given parameter being unknown for the use with the given action.
+ *
+ * @param main
+ *   The main program data.
+ * @param action
+ *   The parameter representing an action.
+ * @param with
+ *   The additional parameter in which is requiring additional arguments that are not met.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_with_unknown_
+  extern void control_print_error_parameter_action_rule_with_unknown(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) F_attribute_visibility_internal_d;
+#endif // _di_control_print_error_parameter_action_rule_with_unknown_
+
+/**
  * Print an error message about the parameter's associated value being an empty string.
  *
  * @param main
diff --git a/level_3/control/documents/packet_request.txt b/level_3/control/documents/packet_request.txt
new file mode 100644 (file)
index 0000000..e3b98b1
--- /dev/null
@@ -0,0 +1,34 @@
+# fss-0002
+
+Packet Request:
+  The control program sends packets and receives packet responses from the controller program over the controller program's control socket.
+  This documentation describes the request packets sent by this program.
+
+  The purpose of these request packets are to ask the controller program to perform a requested action.
+
+  The communications to/from the controller program utilize the FSS-000F (Simple Packet).
+  This Simple Packet is expected to contain within it the FSS-000E (Payload) format.
+
+  The Payload contains within it a Header and a Payload.
+  Note the potential confusion here between the Payload when referring to the Packet format and the Payload referring to the Content within the Payload Packet.
+  To avoid this, henceforth "Payload Packet" refers to the FSS-000E (Payload) used within the FSS-000F (Simple Packet).
+  The "Payload Header" refers to eithe the Object ("header:") or Content within the Payload Packet representing the header.
+  The "Payload Object" refers to the Object within the Payload Packet (ie: "payload:").
+  The "Payload Content" refers to the Content within the Payload Packet.
+
+  The Payload Packet (FSS-000E) is very flexible in what it allows within the Header of the Payload Packet.
+  The Control program is more restrictive and supports only a subset of the possibilities (which this is explicitly allowed by the Specification).
+
+  The Control program only supports the following Payload Packet header Objects for the request\:
+    - type: Allowing only a single type header Object and may only be one of: "controller", "error", or "init".
+    - length: Allowing only a single length header Object and must properly describe the length of the entire Payload Packet as per the referenced Specifications.
+    - action: Allowing only a single action header Object and whose first Content must only be one of: "freeze", "kexec", "kill", "pause", "reboot", "reload", "rerun", "restart", "resume", "shutdown", "start", "stop", and "thaw".
+
+  The number of Content associated with a action are specific to the requirements of that action.
+
+  The Payload Content is not used and should always be of length 0.
+
+  The Payload Content represents the rule being started in FSS-0001 (Extended) format, such as "service sshd".
+
+  For example, given the command: "control start service sshd in 5 minutes".
+  The "action" Object would be "start service sshd in 5 minutes".
index 59de322082a44c645ca4cb7e1c20e66eb665b882..3c7dafb55dacb0924fb8c612892a793a41fca626 100644 (file)
@@ -4,20 +4,22 @@ Packet Response:
   The control program sends packets and receives packet responses from the controller program over the controller program's control socket.
   This documentation describes the expected response packets and how these response packets are handled.
 
-  The communications to/from the controller program utilize the FSS-000F (Simple Packet). 
+  The communications to/from the controller program utilize the FSS-000F (Simple Packet).
   This Simple Packet is expected to contain within it the FSS-000E (Payload) format.
 
   The Payload contains within it a Header and a Payload.
-  Note the potential confusion here between the Payload when referring to the Packet data format and the Payload referring to the Content within the Payload Packet.
-  To avoid this, henceforth "Payload Packet" refers to the FSS-000E (Payload) format used within the Simple Packet and "Payload Content" refers to the Content within the Payload Packet.
+  Note the potential confusion here between the Payload when referring to the Packet format and the Payload referring to the Content within the Payload Packet.
+  The "Payload Header" refers to eithe the Object ("header:") or Content within the Payload Packet representing the header.
+  The "Payload Object" refers to the Object within the Payload Packet (ie: "payload:").
+  The "Payload Content" refers to the Content within the Payload Packet.
 
   The Payload Packet (FSS-000E) is very flexible in what it allows within the Header of the Payload Packet.
   The Control program is more restrictive and supports only a subset of the possibilities (which this is explicitly allowed by the Specification).
 
-  The Control program only supports the following Payload Packet header Objects\:
+  The Control program only supports the following Payload Packet header Objects for the response\:
     - status: Allowing only a single status header Object.
-    - type: Allowing only a single type header Object and may only be one of: "controller", "error", or "kexec".
-    - action: Allowing only a single action header Object and may only be one of: "freeze", "kill", "pause", "reboot", "reload", "rerun", "restart", "resume", "shutdown", "start", "stop", and "thaw".
+    - type: Allowing only a single type header Object and may only be one of: "controller", "error", or "init".
+    - action: Allowing only a single action header Object and must only be one of: "freeze", "kexec", "kill", "pause", "reboot", "reload", "rerun", "restart", "resume", "shutdown", "start", "stop", and "thaw".
     - length: Allowing only a single length header Object and must properly describe the length of the entire Payload Packet as per the referenced Specifications.
 
   The "error" type response Payload Packet is treated as an error response.
@@ -29,7 +31,7 @@ Packet Response:
   The "controller" type response Payload Packet represents a response regarding the result of performing a requested action.
   There must always be an "action" designating the action this response is in regards to.
   Only the following are (currently) supported as a status\:
-    - F_busy: When unable to perform the action as because the service is too busy or the 
+    - F_busy: When unable to perform the action as because the service is too busy or the
     - F_done: When successfully performed the action but the action does not return success or failure.
     - F_failure: When successfully performed the action and the action returned some sort of failure or error.
     - F_success: When successfully performed the action and the action returned some sort of success.
index 968b7ed9baaa58bbf49169840f9e48d84decbd6e..88c46b7531a039a6e52a76a36e7f0780b03c8218 100644 (file)
@@ -54,7 +54,7 @@ Packet Documentation:
 
     The "payload" is expected to be empty and have a length of 0 for a request.
     The "payload" may have an FSS-0000 (Basic) format containing a single Object "message" to represent a message associated with an action.
-    Multuple "message" may exist in the response so long as they each match an "action" in the request.
+    Multiple "message" may exist in the response so long as they each match an "action" in the request.
 
   The error payload\:
     The error payload is intended to communicate some sort of failure.
index 1ce92c5eaca056547b15824a359ffea367348df3..a290d205c7f1cae09565833746b0df305fc758d8 100644 (file)
@@ -16,7 +16,7 @@ Packet Specification:
       - size: A single 4-byte block representing the size of the entire packet, including the control block.
 
   The "header" Object contains the following FSS-0001 Extended Objects (depending on "type")\:
-    - action: A valid action type: "freeze", "kill", "pause", "reboot", "reload", "rerun", "restart", "resume", "shutdown", "start", "stop", or "thaw".
+    - action: A valid action type: "freeze", "kexec", "kill", "pause", "reboot", "reload", "rerun", "restart", "resume", "shutdown", "start", "stop", or "thaw".
     - length: A positive whole number inclusively between 0 and 4294965248 representing the length of the "payload" (may be in binary, octal, decimal, duodecimal, or hexidecimal).
     - status: The status code name or number representing an FSS status code, such as F_none, F_failure, or 200 (where a number may have error and warning bits and may be in binary, octal, decimal, duodecimal, or hexidecimal).
     - type: The packet type that is one of "controller", "error", or "init".