]> Kevux Git Server - kevux-tools/commitdiff
Progress: Further work in TacocaT.
authorKevin Day <kevin@kevux.org>
Sun, 9 Jul 2023 16:36:00 +0000 (11:36 -0500)
committerKevin Day <kevin@kevux.org>
Sun, 9 Jul 2023 16:36:00 +0000 (11:36 -0500)
Of note, this changes IP address and port extraction processing logic.

12 files changed:
data/build/tacocat/dependencies
data/build/tacocat/settings
sources/c/tacocat/main/common.c
sources/c/tacocat/main/common.h
sources/c/tacocat/main/common/define.h
sources/c/tacocat/main/common/print.c
sources/c/tacocat/main/common/print.h
sources/c/tacocat/main/print/warning.c
sources/c/tacocat/main/print/warning.h
sources/c/tacocat/main/process.c
sources/c/tacocat/main/signal.h
sources/c/tacocat/main/tacocat.h

index a58383055afafec2ccfdc9a2e82e41755cafb812..8b9bf310e20c72087fc7075803ccea3d16c962cb 100644 (file)
@@ -9,6 +9,7 @@ f_utf
 f_color
 f_console
 f_compare
+f_conversion
 f_file
 f_network
 f_path
@@ -18,6 +19,7 @@ f_signal
 f_socket
 f_thread
 
+fl_conversion
 fl_print
 
 fll_error
index 154bf091bc101c6606d3b17cb31f85d880a5e02a..3e234b7d4d9278d60f1eab0211ffc14963431029 100644 (file)
@@ -32,7 +32,7 @@ build_indexer_arguments rcs
 build_language c
 
 build_libraries -lc
-build_libraries-individual -lfll_error -lfll_print -lfll_program -lfl_print -lf_color -lf_compare -lf_console -lf_file -lf_memory -lf_network -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_string -lf_type_array -lf_utf
+build_libraries-individual -lfll_error -lfll_print -lfll_program -lfl_conversion -lfl_print -lf_color -lf_compare -lf_console -lf_conversion -lf_file -lf_memory -lf_network -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_string -lf_type_array -lf_utf
 build_libraries-individual_thread -lf_thread
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
index 60ae83f871bd139bac5d7a946c39237909489d23..8083e09b68504b52ae2f02b4e260b2e28273c248 100644 (file)
@@ -167,11 +167,6 @@ extern "C" {
       kt_tacocat_long_send_s,
     };
 
-    f_string_dynamics_t * const strings[] = {
-      &main->setting.receives,
-      &main->setting.sends,
-    };
-
     f_files_t * const files[] = {
       &main->setting.file_receives,
       &main->setting.file_sends,
@@ -187,6 +182,11 @@ extern "C" {
       &main->setting.status_sends,
     };
 
+    f_string_dynamics_t * const strings[] = {
+      &main->setting.receives,
+      &main->setting.sends,
+    };
+
     const bool const is_receive[] = {
       F_true,
       F_false,
@@ -199,6 +199,8 @@ extern "C" {
     f_status_t failed = F_none;
     struct hostent host;
     f_network_family_ip_t family = f_network_family_ip_t_initialize;
+    f_number_unsigned_t port = 0;
+    f_string_static_t address = f_string_static_t_initialize;
 
     for (uint8_t i = 0; i < 2; ++i) {
 
@@ -223,37 +225,37 @@ extern "C" {
 
         main->setting.state.status = f_string_dynamics_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, strings[i]);
 
-        macro_setting_load_handle_send_receive_error_continue_basic(f_string_dynamics_increase_by);
+        macro_setting_load_handle_send_receive_error_continue_1(f_string_dynamics_increase_by);
 
         main->setting.state.status = f_files_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, files[i]);
 
-        macro_setting_load_handle_send_receive_error_continue_basic(f_files_increase_by);
+        macro_setting_load_handle_send_receive_error_continue_1(f_files_increase_by);
 
         main->setting.state.status = f_sockets_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, sockets[i]);
 
-        macro_setting_load_handle_send_receive_error_continue_basic(f_sockets_increase_by);
+        macro_setting_load_handle_send_receive_error_continue_1(f_sockets_increase_by);
 
         main->setting.state.status = f_statuss_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, statuss[i]);
 
-        macro_setting_load_handle_send_receive_error_continue_basic(f_statuss_increase_by);
+        macro_setting_load_handle_send_receive_error_continue_1(f_statuss_increase_by);
 
         for (j = 0; j < main->program.parameters.array[parameters[i]].values.used; j += 2) {
 
           // First parameter value represents the network address or the socket file path.
           index = main->program.parameters.array[parameters[i]].values.array[j];
+          statuss[i]->array[j] = F_none;
           strings[i]->array[j].used = 0;
 
           if (main->program.parameters.arguments.array[index].used) {
             if (f_path_is_absolute(main->program.parameters.arguments.array[index]) == F_true || f_path_is_relative_current(main->program.parameters.arguments.array[index]) == F_true) {
 
-              // Two is added to support a trailing NULL and a type character.
               main->setting.state.status = f_string_dynamic_increase_by(main->program.parameters.arguments.array[index].used + 2, &strings[i]->array[j]);
 
-              macro_setting_load_handle_send_receive_error_continue_basic(f_string_dynamic_increase_by);
+              macro_setting_load_handle_send_receive_error_continue_2(f_string_dynamic_increase_by);
 
               main->setting.state.status = f_string_dynamic_append_nulless(main->program.parameters.arguments.array[index], &strings[i]->array[j]);
 
-              macro_setting_load_handle_send_receive_error_continue_basic(f_string_dynamic_append_nulless);
+              macro_setting_load_handle_send_receive_error_continue_2(f_string_dynamic_append_nulless);
 
               // Designate this as a socket file by appending after the terminating NULL, past the used length.
               strings[i]->array[j].string[strings[i]->array[j].used] = 0;
@@ -262,7 +264,7 @@ extern "C" {
               if (is_receive[i]) {
                 main->setting.state.status = f_file_exists(strings[i]->array[j], F_true);
 
-                macro_setting_load_handle_send_receive_error_continue_basic(f_string_dynamic_append_nulless);
+                macro_setting_load_handle_send_receive_error_continue_2(f_string_dynamic_append_nulless);
               }
 
               strings[i]->array[j].string[strings[i]->array[j].used] = 0;
@@ -274,90 +276,148 @@ extern "C" {
             else if (main->setting.flag & kt_tacocat_main_flag_resolve_classic_e) {
               memset(&host, 0, sizeof(struct hostent));
 
-              main->setting.state.status = f_network_from_ip_name(main->program.parameters.arguments.array[index], &host);
-
-              // @todo provide network-specific error messages.
-              macro_setting_load_handle_send_receive_error_continue_basic(f_network_from_ip_name);
+              port = 0;
+              address = main->program.parameters.arguments.array[index];
+              f_char_t address_string[address.used];
 
-              if (main->setting.state.status == F_data_not || !host.h_addr_list || !host.h_addr_list[0]) {
-                macro_setting_load_print_first();
+              memcpy(address_string, address.string, address.used);
+              address.string = address_string;
 
-                // @todo provide network-specific error messages for when no hosts are returned.
-                kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_network_from_ip_name));
+              f_network_is_ip_address(address, &port, &main->setting.state);
 
-                if (F_status_is_error_not(failed)) {
-                  failed = main->setting.state.status;
-                }
+              if (F_status_is_error(main->setting.state.status)) {
+                // @todo print error message about bad port number or similar.
+                macro_setting_load_handle_send_receive_error_continue_2(f_network_is_ip_address);
+              }
 
-                continue;
+              if (main->setting.state.status == F_network_version_four) {
+                host.h_addrtype = f_socket_address_family_inet4_e;
+              }
+              else if (main->setting.state.status == F_network_version_six) {
+                host.h_addrtype = f_socket_address_family_inet6_e;
+              }
+              else {
+                host.h_addrtype = 0;
               }
 
-              // Two is added to support a trailing NULL and a type character.
-              main->setting.state.status = f_string_dynamic_increase_by(INET6_ADDRSTRLEN + 1, &strings[i]->array[j]);
+              kt_tacocat_setting_load_address_port_extract(main, &address, &port);
 
-              macro_setting_load_handle_send_receive_error_continue_basic(f_string_dynamic_increase_by);
+              if (F_status_is_error(main->setting.state.status)) {
+                // @todo print error message about bad port number or similar.
+                macro_setting_load_handle_send_receive_error_continue_2(kt_tacocat_setting_load_address_port_extract);
+              }
 
-              // Randomly select one of the addresses when there are more than one.
-              if (host.h_addr_list[1]) {
-                k = 2;
+              // Fail forward if port number is not supported by the system.
+              if (port != (in_port_t) port) {
+                kt_tacocat_print_warning_port_number_overflow(&main->program.warning, main->program.parameters.arguments.array[index], port);
 
-                while (host.h_addr_list[k++]);
+                port = 0;
+              }
+
+              if (host.h_addrtype) {
+                main->setting.state.status = f_string_dynamic_append(address, &strings[i]->array[j]);
 
-                // Real randomness or security is not needed here, so fiddle with predictable but somewhat dynamic numbers.
-                srand(main->program.pid + j + host.h_addr_list[0][0]);
-                k = rand() % (k - 1);
+                macro_setting_load_handle_send_receive_error_continue_2(f_string_dynamic_append);
               }
               else {
-                k = 0;
-              }
+                // @todo move this block into its own function.
+                main->setting.state.status = f_network_from_ip_name(address, &host);
 
-              // Two is added to support a trailing NULL and a type character.
-              main->setting.state.status = f_string_dynamic_increase_by(INET6_ADDRSTRLEN + 1, &strings[i]->array[j]);
+                // @todo provide network-specific error messages.
+                macro_setting_load_handle_send_receive_error_continue_2(f_network_from_ip_name);
 
-              macro_setting_load_handle_send_receive_error_continue_basic(f_string_dynamic_increase_by);
+                if (main->setting.state.status == F_data_not || !host.h_addr_list || !host.h_addr_list[0]) {
+                  main->setting.state.status = F_status_set_error(F_parameter);
 
-              if (host.h_addrtype == f_socket_address_family_inet4_e) {
-                family.type = f_network_family_ip_4_e;
-                family.address.v4 = *((struct in_addr *) host.h_addr_list[k]);
-              }
-              else {
-                family.type = f_network_family_ip_6_e;
-                family.address.v6 = *((struct in6_addr *) host.h_addr_list[k]);
-              }
+                  macro_setting_load_print_first();
+
+                  // @todo provide network-specific error messages for when no hosts are returned.
+                  kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_network_from_ip_name));
+
+                  if (F_status_is_error_not(failed)) {
+                    failed = main->setting.state.status;
+                  }
+
+                  statuss[i]->array[j] = main->setting.state.status;
+
+                  continue;
+                }
+
+                main->setting.state.status = f_string_dynamic_increase_by(INET6_ADDRSTRLEN + 1, &strings[i]->array[j]);
+
+                macro_setting_load_handle_send_receive_error_continue_2(f_string_dynamic_increase_by);
+
+                // Randomly select one of the addresses when there are more than one.
+                if (host.h_addr_list[1]) {
+                  k = 2;
+
+                  while (host.h_addr_list[k++]);
+
+                  // Real randomness or security is not needed here, so fiddle with predictable but somewhat dynamic numbers.
+                  srand(main->program.pid + j + host.h_addr_list[0][0]);
+                  k = rand() % (k - 1);
+                }
+                else {
+                  k = 0;
+                }
+
+                main->setting.state.status = f_string_dynamic_increase_by(INET6_ADDRSTRLEN + 1, &strings[i]->array[j]);
+
+                macro_setting_load_handle_send_receive_error_continue_2(f_string_dynamic_increase_by);
+
+                if (host.h_addrtype == f_socket_address_family_inet4_e) {
+                  family.type = f_network_family_ip_4_e;
+                  family.address.v4 = *((struct in_addr *) host.h_addr_list[k]);
+                }
+                else {
+                  family.type = f_network_family_ip_6_e;
+                  family.address.v6 = *((struct in6_addr *) host.h_addr_list[k]);
+                }
+
+                main->setting.state.status = f_network_to_ip_string(family, &strings[i]->array[j]);
+
+                if (main->setting.state.status == F_data_not || !host.h_addr_list || !host.h_addr_list[0]) {
+                  main->setting.state.status = F_status_set_error(F_parameter);
+
+                  macro_setting_load_print_first();
 
-              main->setting.state.status = f_network_to_ip_string(family, &strings[i]->array[j]);
+                  // @todo provide network-specific error messages for when no hosts are returned.
+                  kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_network_from_ip_name));
 
-              if (main->setting.state.status == F_data_not || !host.h_addr_list || !host.h_addr_list[0]) {
-                macro_setting_load_print_first();
+                  if (F_status_is_error_not(failed)) {
+                    failed = main->setting.state.status;
+                  }
 
-                // @todo provide network-specific error messages for when no hosts are returned.
-                kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_network_from_ip_name));
+                  statuss[i]->array[j] = main->setting.state.status;
 
-                if (F_status_is_error_not(failed)) {
-                  failed = main->setting.state.status;
+                  continue;
                 }
 
-                continue;
+                strings[i]->array[j].string[strings[i]->array[j].used] = 0;
               }
 
-              strings[i]->array[j].string[strings[i]->array[j].used] = 0;
               sockets[i]->array[j].protocol = f_socket_protocol_tcp_e;
               sockets[i]->array[j].type = host.h_addrtype;
 
               if (host.h_addrtype == f_socket_address_family_inet4_e) {
                 sockets[i]->array[j].domain = f_socket_protocol_family_inet4_e;
-                sockets[i]->array[j].address.inet4.sin_port = 0; // @todo detect and pull port number from host name if supplied.
+                sockets[i]->array[j].address.inet4.sin_port = (in_port_t) port;
                 sockets[i]->array[j].address.inet4.sin_addr.s_addr = INADDR_ANY;
               }
               else if (host.h_addrtype == f_socket_address_family_inet6_e) {
                 sockets[i]->array[j].domain = f_socket_protocol_family_inet6_e;
-                sockets[i]->array[j].address.inet6.sin6_port = 0; // @todo detect and pull port number from host name if supplied.
+                sockets[i]->array[j].address.inet6.sin6_port = (in_port_t) port;
                 sockets[i]->array[j].address.inet6.sin6_addr = in6addr_any;
               }
             }
             else {
               // @todo Kevux DNS resolution.
             }
+
+            ++files[i]->used;
+            ++sockets[i]->used;
+            ++statuss[i]->used;
+            ++strings[i]->used;
           }
           else {
             main->setting.state.status = F_status_set_error(F_parameter);
@@ -370,6 +430,8 @@ extern "C" {
               failed = main->setting.state.status;
             }
 
+            statuss[i]->array[j] = main->setting.state.status;
+
             continue;
           }
 
@@ -379,26 +441,29 @@ extern "C" {
           if (main->program.parameters.arguments.array[index].used) {
 
             // Make sure the current file is closed.
-            f_file_close(&files[i]->array[files[i]->used]);
+            f_file_close(&files[i]->array[j]);
 
             if (is_receive[i]) {
-              files[i]->array[files[i]->used].flag = F_file_flag_append_wo_d;
-              files[i]->array[files[i]->used].size_read = main->setting.block_size_send;
-              files[i]->array[files[i]->used].size_write = main->setting.block_size_send;
+              files[i]->array[j].flag = F_file_flag_append_wo_d;
+              files[i]->array[j].size_read = main->setting.block_size_send;
+              files[i]->array[j].size_write = main->setting.block_size_send;
             }
             else {
-              files[i]->array[files[i]->used].flag = F_file_flag_read_only_d;
-              files[i]->array[files[i]->used].size_read = main->setting.block_size_receive;
-              files[i]->array[files[i]->used].size_write = main->setting.block_size_receive;
+              files[i]->array[j].flag = F_file_flag_read_only_d;
+              files[i]->array[j].size_read = main->setting.block_size_receive;
+              files[i]->array[j].size_write = main->setting.block_size_receive;
             }
 
-            main->setting.state.status = f_file_open(main->program.parameters.arguments.array[index], F_file_mode_all_rw_d, &files[i]->array[files[i]->used]);
+            main->setting.state.status = f_file_open(main->program.parameters.arguments.array[index], F_file_mode_all_rw_d, &files[i]->array[j]);
 
             if (F_status_is_error(main->setting.state.status)) {
-              macro_setting_load_handle_send_receive_error_file_continue_basic(f_file_open, main->program.parameters.arguments.array[index], f_file_operation_open_s, fll_error_file_type_file_e);
-            }
-            else {
-              ++files[i]->used;
+              macro_setting_load_handle_send_receive_error_file_continue_1(f_file_open, main->program.parameters.arguments.array[index], f_file_operation_open_s, fll_error_file_type_file_e);
+
+              if (F_status_is_error_not(failed)) {
+                failed = main->setting.state.status;
+              }
+
+              statuss[i]->array[j] = main->setting.state.status;
             }
           }
           else {
@@ -412,6 +477,8 @@ extern "C" {
               failed = main->setting.state.status;
             }
 
+            statuss[i]->array[j] = main->setting.state.status;
+
             continue;
           }
         } // for
@@ -435,7 +502,70 @@ extern "C" {
       main->setting.state.status = failed;
     }
   }
-#endif // _di_kt_tacocat_setting_load_
+#endif // _di_kt_tacocat_setting_load_send_receive_
+
+#ifndef _di_kt_tacocat_setting_load_address_port_extract_
+  void kt_tacocat_setting_load_address_port_extract(kt_tacocat_main_t * const main, f_string_static_t * const address, f_number_unsigned_t * const port) {
+
+    if (!main) return;
+
+    if (!address || !port) {
+      main->setting.state.status = F_status_set_error(F_parameter);
+
+      return;
+    }
+
+    if (!address->used) {
+      main->setting.state.status = F_data_not;
+
+      return;
+    }
+
+    f_number_unsigned_t i = 0;
+
+    if (main->setting.state.status == F_network_version_four || main->setting.state.status == F_network_version_six) {
+      if (*port) {
+        i = *port;
+        *port = 0;
+
+        const f_string_static_t adjusted = macro_f_string_static_t_initialize_1(address->string + i, 0, address->used - i);
+
+        main->setting.state.status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, adjusted, port);
+        if (F_status_is_error(main->setting.state.status)) return;
+
+        address->string[i] = 0;
+        address->used = i;
+
+        while (address->used && address->string[address->used] != f_string_ascii_colon_s.string[0]) --address->used;
+      }
+
+      main->setting.state.status = F_none;
+
+      return;
+    }
+
+    *port = 0;
+    i = address->used;
+
+    while (--i) {
+      if (address->string[i] == f_string_ascii_colon_s.string[0]) break;
+    } // while
+
+    if (i && i + 1 < address->used) {
+      const f_string_static_t adjusted = macro_f_string_static_t_initialize_1(address->string + i + 1, 0, address->used - i - 1);
+
+      main->setting.state.status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, adjusted, port);
+      if (F_status_is_error(main->setting.state.status)) return;
+
+      address->string[i] = 0;
+      address->used = i;
+      main->setting.state.status = F_none;
+    }
+    else {
+      main->setting.state.status = F_number_not;
+    }
+  }
+#endif // _di_kt_tacocat_setting_load_address_port_extract_
 
 #ifdef __cplusplus
 } // extern "C"
index 513254efc0268378119a6e6db95a76867c5a6518..5f265cdf014a2596f6d41ae840d6cc5e3638a480 100644 (file)
@@ -67,7 +67,7 @@ extern "C" {
  *
  *   This must be of type kt_tacocat_main_t.
  *
- *   This alters setting.status:
+ *   This alters main.setting.state.status:
  *     F_none on success.
  *
  *     F_parameter (with error bit) on parameter error.
@@ -94,6 +94,49 @@ extern "C" {
   extern void kt_tacocat_setting_load_send_receive(const f_console_arguments_t arguments, void * const main);
 #endif // _di_kt_tacocat_setting_load_send_receive_
 
+/**
+ * Process the string and extract any potential port numbers.
+ *
+ * A port number is expected to be a digit following the last ':' at the end of the string.
+ *
+ * This does not print error messages.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   The main.setting.state.status can be set to either F_network_version_four or F_network_version_six when calling this function to bypass IP type detection.
+ *
+ *   This alters main.setting.state.status:
+ *     F_none on success.
+ *     F_data_not on success but there is nothing in the address string (address.used is 0).
+ *     F_number_not on success but there is no port number.
+ *
+ *     F_parameter (with error bit) on parameter error.
+ *
+ *     Errors (with error bit) from: fl_conversion_dynamic_to_unsigned_detect().
+ * @param address
+ *   The string representing the address to extract the port number from.
+ *   If a valid number is found, then this is updated to truncate the length at the colon and a NULL termination is inserted at the colon.
+ *   For IPv6, only bracket wrapped addresses are supported when using port number (like [2001:db8::1]:80).
+ *   Base notations for port numbers are supported (such as specifying hexidecimal like [2001:db8::1]:0x50 or specifying octal like 127.0.0.1:0o120)
+ *
+ *   Supported base notations:
+ *   - Hexidecimals (base 16) begin with either '0x' or '0X'.
+ *   - Duodecimals (base 12) begin with either '0d' or '0D'.
+ *   - Octals (base 8) begin with either '0o' or '0O'.
+ *   - Binaries (base 2) begin with either '0b' or '0B'.
+ *   - Decimal (base 10) is used for all other cases.
+ * @param port
+ *   The extracted port number.
+ *
+ *   When main.setting.state.status is set to either F_network_version_four or F_network_version_six when calling this function, the port represents the location within the address string that the port number begins.
+ *
+ * @see fl_conversion_dynamic_to_unsigned_detect()
+ */
+#ifndef _di_kt_tacocat_setting_load_address_port_extract_
+  extern void kt_tacocat_setting_load_address_port_extract(kt_tacocat_main_t * const main, f_string_static_t * const address, f_number_unsigned_t * const port);
+#endif // _di_kt_tacocat_setting_load_address_port_extract_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 5fafccbce35a22ac50d9c655df5a6f15bc6e2c56..2d8922a776bc25785ce3c3a0257b30a79381bc59 100644 (file)
@@ -55,12 +55,12 @@ extern "C" {
  * macro_setting_load_print_first:
  *   Intended to be used to simplify the code in kt_tacocat_setting_load() and make it more readable.
  *
- * macro_setting_load_handle_send_receive_error_continue_basic:
+ * macro_setting_load_handle_send_receive_error_continue_1:
  *   Intended to be used to simplify the code in kt_tacocat_setting_load_send_receive() and make it more readable.
  *   This is for the basic error that calls kt_tacocat_print_error() when printing.
  *
- * macro_setting_load_handle_send_receive_error_file_continue_basic:
- *   The same as macro_setting_load_handle_send_receive_error_continue_basic() but intended for file errors.
+ * macro_setting_load_handle_send_receive_error_file_continue_1:
+ *   The same as macro_setting_load_handle_send_receive_error_continue_1() but intended for file errors.
  */
 #ifndef _di_kt_tacocat_macros_d_
   #define macro_setting_load_print_first() \
@@ -68,7 +68,7 @@ extern "C" {
       fll_print_dynamic_raw(f_string_eol_s, main->program.message.to); \
     }
 
-  #define macro_setting_load_handle_send_receive_error_continue_basic(method) \
+  #define macro_setting_load_handle_send_receive_error_continue_1(method) \
     if (F_status_is_error(main->setting.state.status)) { \
       macro_setting_load_print_first(); \
       \
@@ -81,7 +81,22 @@ extern "C" {
       continue; \
     }
 
-  #define macro_setting_load_handle_send_receive_error_file_continue_basic(method, name, operation, type) \
+  #define macro_setting_load_handle_send_receive_error_continue_2(method) \
+    if (F_status_is_error(main->setting.state.status)) { \
+      macro_setting_load_print_first(); \
+      \
+      kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(method)); \
+      \
+      if (F_status_is_error_not(failed)) { \
+        failed = main->setting.state.status; \
+      } \
+      \
+      statuss[i]->array[j] = main->setting.state.status; \
+      \
+      continue; \
+    }
+
+  #define macro_setting_load_handle_send_receive_error_file_continue_1(method, name, operation, type) \
     if (F_status_is_error(main->setting.state.status)) { \
       macro_setting_load_print_first(); \
       \
@@ -91,6 +106,8 @@ extern "C" {
         failed = main->setting.state.status; \
       } \
       \
+      statuss[i]->array[j] = main->setting.state.status; \
+      \
       continue; \
     }
 #endif // _di_kt_tacocat_macro_d_
index 94f0aed84999fc39def443c92fce5dca30dafabe..1036b71ac77fce4403ad5077ae77e849cc74fa0f 100644 (file)
@@ -10,6 +10,7 @@ extern "C" {
     "f_file_open",
     "f_files_increase_by",
     "f_network_from_ip_name",
+    "f_network_is_ip_address",
     "f_socket_bind_inet4",
     "f_socket_bind_inet6",
     "f_socket_bind_local",
@@ -20,12 +21,14 @@ extern "C" {
     "f_sockets_increase_by",
     "f_statuss_increase_by",
     "f_string_append_nulless",
+    "f_string_dynamic_append",
     "f_string_dynamic_append_nulless",
     "f_string_dynamic_increase_by",
     "f_string_dynamics_increase_by",
     "f_thread_create",
     "fll_program_parameter_process_context",
     "fll_program_parameter_process_verbosity",
+    "kt_tacocat_setting_load_address_port_extract",
   };
 #endif // _di_kt_tacocat_f_a_
 
index 36235ed0a18c4045e855f3ddcfbdea130a75f4f6..a0fb4092792ff23f1b0aa017a81a6d617030d31d 100644 (file)
@@ -43,6 +43,7 @@ extern "C" {
     kt_tacocat_f_f_file_open_e,
     kt_tacocat_f_f_files_increase_by_e,
     kt_tacocat_f_f_network_from_ip_name_e,
+    kt_tacocat_f_f_network_is_ip_address_e,
     kt_tacocat_f_f_socket_bind_inet4_e,
     kt_tacocat_f_f_socket_bind_inet6_e,
     kt_tacocat_f_f_socket_bind_local_e,
@@ -53,12 +54,14 @@ extern "C" {
     kt_tacocat_f_f_sockets_increase_by_e,
     kt_tacocat_f_f_statuss_increase_by_e,
     kt_tacocat_f_f_string_append_nulless_e,
+    kt_tacocat_f_f_string_dynamic_append_e,
     kt_tacocat_f_f_string_dynamic_append_nulless_e,
     kt_tacocat_f_f_string_dynamic_increase_by_e,
     kt_tacocat_f_f_string_dynamics_increase_by_e,
     kt_tacocat_f_f_thread_create_e,
     kt_tacocat_f_fll_program_parameter_process_context_e,
     kt_tacocat_f_fll_program_parameter_process_verbosity_e,
+    kt_tacocat_f_kt_tacocat_setting_load_address_port_extract_e,
   }; // enum
 #endif // _di_kt_tacocat_f_e_
 
index 87f19561790cf54e63870902c82fbd1ed88a2719..e8207e382577080333ff918186ce466979baa703 100644 (file)
@@ -4,6 +4,25 @@
 extern "C" {
 #endif
 
+#ifndef _di_fake_build_print_warning_setting_boolean_may_only_be_
+  f_status_t kt_tacocat_print_warning_port_number_overflow(fl_print_t * const print, const f_string_static_t address, const f_number_unsigned_t port) {
+
+    if (print->verbosity < f_console_verbosity_verbose_e) return F_output_not;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("%[%QThe port number '%]", print->to, print->context, print->prefix, print->context);
+    fl_print_format("%[%ul%]", print->to, print->notable, port, print->notable);
+    fl_print_format("%[' from the address '%]", print->to, print->context, print->context);
+    fl_print_format("%[%Q%]", print->to, print->notable, address, print->notable);
+    fl_print_format("%['is too large for this system and so the port is being autodetermined.%]%r", print->to, print->context, print->context, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_fake_build_print_warning_setting_boolean_may_only_be_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 7cd756bcdc2ce57d80185cf2304c45161a2f29de..b6d40f0255e85174d8eee1a1fe0ff49a4d1f28a2 100644 (file)
 extern "C" {
 #endif
 
+/**
+ * Print warning message about given port number being out of range for this system.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This requires print.custom to be fake_main_t.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param address
+ *   The original address string.
+ * @param port
+ *   The out of range port.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ *
+ * @see f_file_stream_lock()
+ * @see f_file_stream_unlock()
+ * @see fl_print_format()
+ */
+#ifndef _di_kt_tacocat_print_warning_port_number_overflow_
+  extern f_status_t kt_tacocat_print_warning_port_number_overflow(fl_print_t * const print, const f_string_static_t address, const f_number_unsigned_t port);
+#endif // _di_kt_tacocat_print_warning_port_number_overflow_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index a2dd618a20f2cc67097558113d7ea01623ffb7de..8e87adabec58772f4519b17ad4fb3defeed1be1b 100644 (file)
@@ -34,6 +34,7 @@ extern "C" {
     for (; i < main->setting.socket_receives.used; ++i) {
 
       if (kt_tacocat_signal_check(main)) return;
+      if (F_status_is_error(main->setting.status_receives.array[i])) continue;
 
       main->setting.status_receives.array[i] = f_socket_create(&main->setting.socket_receives.array[i]);
 
@@ -85,6 +86,7 @@ extern "C" {
     for (i = 0; i < main->setting.socket_sends.used; ++i) {
 
       if (kt_tacocat_signal_check(main)) return;
+      if (F_status_is_error(main->setting.status_sends.array[i])) continue;
 
       // @todo check to see if connection is one of "local", "inet" (ipv4), or "inet6" (ipv6) and configure socket appropriately.
 
index bc5f375446d083c6b6e3769ba692f7c85ee79a40..e44651f20b78ea924341131e4bad6b665efb3621 100644 (file)
@@ -63,7 +63,7 @@ extern "C" {
  *
  *   This alters main.program.signal_received, setting it to a received signal.
  *
- *   This alters setting.status:
+ *   This alters main.setting.state.status:
  *     Errors (with error bit) from: f_signal_open()
  *     Errors (with error bit) from: f_signal_wait()
  *
index 92c32bee830871c08b57e1a0fac3d6acc1bc43ba..f0c837c606fee3802d3a149cc6b52a50ec824615 100644 (file)
@@ -37,6 +37,7 @@
 #include <fll/level_0/thread.h>
 
 // FLL-1 includes.
+#include <fll/level_1/conversion.h>
 #include <fll/level_1/print.h>
 
 // FLL-2 includes.