From 162c91b8c4eff481e6aa41b23d84efae948ef015 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 3 Jan 2021 21:20:05 -0600 Subject: [PATCH] Progress: controller program and other minor tweaks. Add support for "affinity" and "limit" to the controller program (and the execute functions from the execute projects). The "affinity" allows settings specific CPUs to run the process on. The "limit" allows for customizing the resource limits (ie: ulimit) in the process. The resource names are used as-is, such as defined in /etc/security/limits.conf on some Linux systems. Only the well known resource types are supported. (For example, debian systems has 'chroot', which is not supported by this implementation at this time.) New projects are added to address these features. A project f_schedule is suggested by the comments added in this commit and may be introduced on a later date. Minor tweaks includes using a global static variable for the space as a string " ". --- build/level_0/settings | 8 +- build/level_2/settings | 2 +- build/monolithic/settings | 10 +- build/scripts/bootstrap-example.sh | 2 +- level_0/f_control_group/c/control_group.h | 2 +- level_0/f_execute/c/execute-common.h | 2 + level_0/f_execute/c/execute.h | 4 + level_0/f_fss/c/fss.h | 2 +- level_0/f_limit/c/limit-common.h | 120 ++ level_0/f_limit/c/limit.c | 192 +++ level_0/f_limit/c/limit.h | 262 ++++ level_0/f_limit/c/private-limit.c | 50 + level_0/f_limit/c/private-limit.h | 116 ++ level_0/f_limit/data/build/defines | 1 + level_0/f_limit/data/build/dependencies | 5 + level_0/f_limit/data/build/settings | 55 + level_0/f_status/c/status.h | 4 + level_0/f_string/c/string-common.h | 41 +- level_0/f_string/c/string.h | 4 + level_0/f_type/c/type_array.h | 8 +- level_1/fl_execute/c/execute-common.h | 10 +- level_1/fl_execute/c/execute.h | 3 +- level_1/fl_execute/data/build/dependencies | 1 + level_1/fl_execute/data/build/settings | 2 +- level_1/fl_status/c/status.c | 20 +- level_1/fl_status/c/status.h | 8 + level_2/fll_execute/c/execute.h | 8 +- level_2/fll_execute/c/private-execute.c | 49 +- level_2/fll_execute/c/private-execute.h | 21 +- level_2/fll_execute/data/build/dependencies | 1 + level_2/fll_execute/data/build/settings | 4 +- level_2/fll_program/c/program.c | 4 +- level_2/fll_status/c/status.c | 20 + level_3/byte_dump/c/private-byte_dump.c | 80 +- level_3/controller/c/controller.c | 2 +- level_3/controller/c/private-common.h | 154 ++- level_3/controller/c/private-controller.c | 30 +- level_3/controller/c/private-entry.c | 60 +- level_3/controller/c/private-rule.c | 1248 ++++++++++++++++---- level_3/controller/c/private-rule.h | 14 + level_3/controller/data/build/settings | 2 +- .../settings/example/rules/command/multiple.rule | 30 +- level_3/controller/documents/rule.txt | 11 +- level_3/controller/specifications/rule.txt | 2 + level_3/fake/c/private-build.c | 2 +- level_3/fake/c/private-make.c | 12 +- level_3/fake/data/build/settings | 2 +- level_3/firewall/data/build/settings | 2 +- level_3/iki_read/c/iki_read.c | 4 +- 49 files changed, 2290 insertions(+), 406 deletions(-) create mode 100644 level_0/f_limit/c/limit-common.h create mode 100644 level_0/f_limit/c/limit.c create mode 100644 level_0/f_limit/c/limit.h create mode 100644 level_0/f_limit/c/private-limit.c create mode 100644 level_0/f_limit/c/private-limit.h create mode 100644 level_0/f_limit/data/build/defines create mode 100644 level_0/f_limit/data/build/dependencies create mode 100644 level_0/f_limit/data/build/settings diff --git a/build/level_0/settings b/build/level_0/settings index 68b9c74..7952ea0 100644 --- a/build/level_0/settings +++ b/build/level_0/settings @@ -21,11 +21,11 @@ build_language c build_libraries -lc -lcap build_libraries-level build_libraries-level_threadless -build_sources_library account.c private-account.c capability.c console.c conversion.c directory.c private-directory.c environment.c private-environment.c file.c private-file.c fss.c iki.c private-iki.c memory.c path.c private-path.c pipe.c print.c private-print.c serialize.c private-serialize.c signal.c socket.c utf.c private-utf.c -build_sources_library-level thread.c private-thread.c +build_sources_library-level account.c private-account.c capability.c console.c conversion.c directory.c private-directory.c environment.c private-environment.c file.c private-file.c fss.c iki.c private-iki.c limit.c private-limit.c memory.c path.c private-path.c pipe.c print.c private-print.c serialize.c private-serialize.c signal.c socket.c thread.c private-thread.c utf.c private-utf.c +build_sources_library-level_threadless account.c private-account.c capability.c console.c conversion.c directory.c private-directory.c environment.c private-environment.c file.c private-file.c fss.c iki.c private-iki.c limit.c private-limit.c memory.c path.c private-path.c pipe.c print.c private-print.c serialize.c private-serialize.c signal.c socket.c utf.c private-utf.c build_sources_program -build_sources_headers account.h account-common.h capability.h capability-common.h color.h console.h console-common.h control_group.h control_group-common.h conversion.h conversion-common.h directory.h directory_type.h directory-common.h environment.h environment-common.h execute.h execute-common.h file.h file-common.h fss.h fss-common.h fss_comment.h fss_delimit.h fss_named.h fss_nest.h fss_quote.h fss_set.h iki.h iki-common.h memory.h memory_structure.h path.h path-common.h pipe.h print.h serialize.h serialize-common.h signal.h signal-common.h socket.h socket-common.h status.h status_array.h string.h string-common.h string_dynamic.h string_map.h string_quantity.h string_range.h string_triple.h type.h type_array.h utf.h utf-common.h -build_sources_headers-level thread.h thread-common.h +build_sources_headers-level account.h account-common.h capability.h capability-common.h color.h console.h console-common.h control_group.h control_group-common.h conversion.h conversion-common.h directory.h directory_type.h directory-common.h environment.h environment-common.h execute.h execute-common.h file.h file-common.h fss.h fss-common.h fss_comment.h fss_delimit.h fss_named.h fss_nest.h fss_quote.h fss_set.h iki.h iki-common.h limit.h limit-common.h memory.h memory_structure.h path.h path-common.h pipe.h print.h serialize.h serialize-common.h signal.h signal-common.h socket.h socket-common.h status.h status_array.h string.h string-common.h string_dynamic.h string_map.h string_quantity.h string_range.h string_triple.h thread.h thread-common.h type.h type_array.h utf.h utf-common.h +build_sources_headers-level_threadless account.h account-common.h capability.h capability-common.h color.h console.h console-common.h control_group.h control_group-common.h conversion.h conversion-common.h directory.h directory_type.h directory-common.h environment.h environment-common.h execute.h execute-common.h file.h file-common.h fss.h fss-common.h fss_comment.h fss_delimit.h fss_named.h fss_nest.h fss_quote.h fss_set.h iki.h iki-common.h limit.h limit-common.h memory.h memory_structure.h path.h path-common.h pipe.h print.h serialize.h serialize-common.h signal.h signal-common.h socket.h socket-common.h status.h status_array.h string.h string-common.h string_dynamic.h string_map.h string_quantity.h string_range.h string_triple.h type.h type_array.h utf.h utf-common.h build_sources_script build_sources_setting build_script yes diff --git a/build/level_2/settings b/build/level_2/settings index 59a660c..f002b57 100644 --- a/build/level_2/settings +++ b/build/level_2/settings @@ -18,7 +18,7 @@ modes_default level build_compiler gcc build_indexer ar build_language c -build_libraries -lc -lcap -lfll_1 -lfll_0 +build_libraries -lc -lcap build_libraries-level -lfll_1 -lfll_0 build_libraries-level_threadless -lfll_1 -lfll_0 build_sources_library control_group.c environment.c error.c private-error.c execute.c private-execute.c file.c private-file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c fss_status.c iki.c private-iki.c path.c program.c status.c diff --git a/build/monolithic/settings b/build/monolithic/settings index 5be10cf..df778bf 100644 --- a/build/monolithic/settings +++ b/build/monolithic/settings @@ -12,7 +12,7 @@ environment process_pre process_post -modes monolithic monolithic-threadless +modes monolithic monolithic_threadless modes_default monolithic build_compiler gcc @@ -21,11 +21,11 @@ build_language c build_libraries -lc -lcap build_libraries-monolithic build_libraries-monolithic_threadless -build_sources_library level_0/account.c level_0/private-account.c level_0/capability.c level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/private-iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/private-print.c level_0/serialize.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/control_group.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_embedded_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/private-print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/type.c level_1/private-type.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/control_group.c level_2/environment.c level_2/error.c level_2/private-error.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_embedded_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/iki.c level_2/private-iki.c level_2/path.c level_2/program.c level_2/status.c -build_sources_library-monolithic level_0/thread.c level_0/private-thread.c +build_sources_library-monolithic level_0/account.c level_0/private-account.c level_0/capability.c level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/private-iki.c level_0/limit.c level_0/private-limit.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/private-print.c level_0/serialize.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/thread.c level_0/private-thread.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/control_group.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_embedded_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/private-print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/type.c level_1/private-type.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/control_group.c level_2/environment.c level_2/error.c level_2/private-error.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_embedded_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/iki.c level_2/private-iki.c level_2/path.c level_2/program.c level_2/status.c +build_sources_library-monolithic_threadless level_0/account.c level_0/private-account.c level_0/capability.c level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/private-iki.c level_0/limit.c level_0/private-limit.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/private-print.c level_0/serialize.c level_0/private-serialize.c level_0/signal.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/control_group.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/environment.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_embedded_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/private-print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/type.c level_1/private-type.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/control_group.c level_2/environment.c level_2/error.c level_2/private-error.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/private-file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_embedded_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/iki.c level_2/private-iki.c level_2/path.c level_2/program.c level_2/status.c build_sources_program -build_sources_headers level_0/account.h level_0/account-common.h level_0/capability.h level_0/capability-common.h level_0/color.h level_0/console.h level_0/console-common.h level_0/control_group.h level_0/control_group-common.h level_0/conversion.h level_0/conversion-common.h level_0/directory.h level_0/directory_type.h level_0/directory-common.h level_0/environment.h level_0/environment-common.h level_0/execute.h level_0/execute-common.h level_0/file.h level_0/file-common.h level_0/fss.h level_0/fss-common.h level_0/fss_comment.h level_0/fss_delimit.h level_0/fss_named.h level_0/fss_nest.h level_0/fss_quote.h level_0/fss_set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory_structure.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/serialize-common.h level_0/signal.h level_0/signal-common.h level_0/socket.h level_0/socket-common.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string-common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/string_triple.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/control_group.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/execute.h level_1/execute-common.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_embedded_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/type.h level_1/utf.h level_1/utf_file.h level_2/control_group.h level_2/environment.h level_2/error.h level_2/error-common.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_embedded_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/iki.h level_2/path.h level_2/program.h level_2/status.h -build_sources_headers-monolithic level_0/thread.h level_0/thread-common.h +build_sources_headers-monolithic level_0/account.h level_0/account-common.h level_0/capability.h level_0/capability-common.h level_0/color.h level_0/console.h level_0/console-common.h level_0/control_group.h level_0/control_group-common.h level_0/conversion.h level_0/conversion-common.h level_0/directory.h level_0/directory_type.h level_0/directory-common.h level_0/environment.h level_0/environment-common.h level_0/execute.h level_0/execute-common.h level_0/file.h level_0/file-common.h level_0/fss.h level_0/fss-common.h level_0/fss_comment.h level_0/fss_delimit.h level_0/fss_named.h level_0/fss_nest.h level_0/fss_quote.h level_0/fss_set.h level_0/iki.h level_0/iki-common.h level_0/limit.h level_0/limit-common.h level_0/memory.h level_0/memory_structure.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/serialize-common.h level_0/signal.h level_0/signal-common.h level_0/socket.h level_0/socket-common.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string-common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/string_triple.h level_0/thread.h level_0/thread-common.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/control_group.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/execute.h level_1/execute-common.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_embedded_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/type.h level_1/utf.h level_1/utf_file.h level_2/control_group.h level_2/environment.h level_2/error.h level_2/error-common.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_embedded_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/iki.h level_2/path.h level_2/program.h level_2/status.h +build_sources_headers-monolithic_threadless level_0/account.h level_0/account-common.h level_0/capability.h level_0/capability-common.h level_0/color.h level_0/console.h level_0/console-common.h level_0/control_group.h level_0/control_group-common.h level_0/conversion.h level_0/conversion-common.h level_0/directory.h level_0/directory_type.h level_0/directory-common.h level_0/environment.h level_0/environment-common.h level_0/execute.h level_0/execute-common.h level_0/file.h level_0/file-common.h level_0/fss.h level_0/fss-common.h level_0/fss_comment.h level_0/fss_delimit.h level_0/fss_named.h level_0/fss_nest.h level_0/fss_quote.h level_0/fss_set.h level_0/iki.h level_0/iki-common.h level_0/limit.h level_0/limit-common.h level_0/memory.h level_0/memory_structure.h level_0/path.h level_0/path-common.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/serialize-common.h level_0/signal.h level_0/signal-common.h level_0/socket.h level_0/socket-common.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string-common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/string_triple.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/control_group.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/execute.h level_1/execute-common.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_embedded_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/type.h level_1/utf.h level_1/utf_file.h level_2/control_group.h level_2/environment.h level_2/error.h level_2/error-common.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_embedded_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/iki.h level_2/path.h level_2/program.h level_2/status.h build_sources_script build_sources_setting build_script yes diff --git a/build/scripts/bootstrap-example.sh b/build/scripts/bootstrap-example.sh index 275b122..83a9c7e 100644 --- a/build/scripts/bootstrap-example.sh +++ b/build/scripts/bootstrap-example.sh @@ -56,7 +56,7 @@ if [[ $1 == "individual" ]] ; then bash build/scripts/package.sh $verbose $color build -i if [[ $? -eq 0 ]] ; then - for i in f_type f_status f_memory f_string f_utf f_account f_capability f_color f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_path f_pipe f_print f_serialize f_signal f_socket f_thread fl_color fl_console fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_print fl_status fl_string fl_type fl_utf fl_utf_file fll_control_group fll_environment fll_error fll_execute fll_file fll_fss fll_iki fll_path fll_program fll_status ; do + for i in f_type f_status f_memory f_string f_utf f_account f_capability f_color f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_path f_pipe f_print f_serialize f_signal f_socket f_thread fl_color fl_console fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_print fl_status fl_string fl_type fl_utf fl_utf_file fll_control_group fll_environment fll_error fll_execute fll_file fll_fss fll_iki fll_path fll_program fll_status ; do echo && echo "Processing $i." && cd package/individual/$i-$2/ && diff --git a/level_0/f_control_group/c/control_group.h b/level_0/f_control_group/c/control_group.h index 100242b..f0b8e62 100644 --- a/level_0/f_control_group/c/control_group.h +++ b/level_0/f_control_group/c/control_group.h @@ -1,5 +1,5 @@ /** - * FLL - Level 1 + * FLL - Level 0 * * Project: Control Group * API Version: 0.5 diff --git a/level_0/f_execute/c/execute-common.h b/level_0/f_execute/c/execute-common.h index 71a8d00..476a607 100644 --- a/level_0/f_execute/c/execute-common.h +++ b/level_0/f_execute/c/execute-common.h @@ -19,6 +19,8 @@ extern "C" { /** * A structure representing a scheduler and its parameters for execution. * + * @todo move this into a f_scheduler project. + * * policy: the scheduler policy. * priority: the scheduler priority; */ diff --git a/level_0/f_execute/c/execute.h b/level_0/f_execute/c/execute.h index 60e6abb..942c48a 100644 --- a/level_0/f_execute/c/execute.h +++ b/level_0/f_execute/c/execute.h @@ -10,7 +10,11 @@ #ifndef _F_execute_h #define _F_execute_h +// include pre-requirements +#define _GNU_SOURCE + // libc includes +#include // fll-0 includes #include diff --git a/level_0/f_fss/c/fss.h b/level_0/f_fss/c/fss.h index 8fe185a..877b590 100644 --- a/level_0/f_fss/c/fss.h +++ b/level_0/f_fss/c/fss.h @@ -17,8 +17,8 @@ // fll-0 includes #include -#include #include +#include #include #include #include diff --git a/level_0/f_limit/c/limit-common.h b/level_0/f_limit/c/limit-common.h new file mode 100644 index 0000000..e5d631d --- /dev/null +++ b/level_0/f_limit/c/limit-common.h @@ -0,0 +1,120 @@ +/** + * FLL - Level 0 + * + * Project: Limit + * API Version: 0.5 + * Licenses: lgplv2.1 + * + * Defines common data to be used for/by limit related functionality. + * + * This is auto-included by limit.h and should not need to be explicitly included. + */ +#ifndef _F_limit_common_h +#define _F_limit_common_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * A limit value structure. + * + * rlim_cur: the soft limit. + * rlim_max: the hard limit. + */ +#ifndef _di_f_limit_value_t_ + typedef struct rlimit f_limit_value_t; + + #define f_limit_value_t_initialize { 0, 0 } + + #define f_macro_limit_value_t_clear(value) \ + value.rlim_cur = 0; \ + value.rlim_max = 0; +#endif // _di_f_limit_value_t_ + +/** + * An array of limit values. + * + * array: An array of limit values. + * size: Total amount of allocated space. + * used: Total number of allocated spaces used. + */ +#ifndef _di_f_limit_values_t_ + typedef struct { + f_limit_value_t *array; + + f_array_length_t size; + f_array_length_t used; + } f_limit_values_t; + + #define f_limit_values_t_initialize { 0, 0, 0 } + + #define f_macro_limit_values_t_clear(values) f_macro_memory_structure_t_clear(values) + + #define f_macro_limit_values_t_new(status, values, length) f_macro_memory_structure_t_new(status, values, f_limit_value_t, length) + + #define f_macro_limit_values_t_delete(status, values) f_macro_memory_structure_t_delete(status, values, f_limit_value_t) + #define f_macro_limit_values_t_destroy(status, values) f_macro_memory_structure_t_destroy(status, values, f_limit_value_t) + + #define f_macro_limit_values_t_delete_simple(values) f_macro_memory_structure_t_delete_simple(values, f_limit_value_t) + #define f_macro_limit_values_t_destroy_simple(values) f_macro_memory_structure_t_destroy_simple(values, f_limit_value_t) + + #define f_macro_limit_values_t_resize(status, values, new_length) f_macro_memory_structure_t_resize(status, values, f_limit_value_t, new_length) + #define f_macro_limit_values_t_adjust(status, values, new_length) f_macro_memory_structure_t_adjust(status, values, f_limit_value_t, new_length) +#endif // _di_f_limit_values_t_ + +/** + * A limit value structure. + * + * type: the limit resource type code. + * value: the limit value containing the soft and hard limit. + */ +#ifndef _di_f_limit_set_t_ + typedef struct { + int type; + f_limit_value_t value; + } f_limit_set_t; + + #define f_limit_set_t_initialize { 0, 0 } + + #define f_macro_limit_set_t_clear(set) \ + set.type = 0; \ + set.value = 0; +#endif // _di_f_limit_set_t_ + +/** + * An array of limit sets. + * + * array: An array of limit sets. + * size: Total amount of allocated space. + * used: Total number of allocated spaces used. + */ +#ifndef _di_f_limit_sets_t_ + typedef struct { + f_limit_set_t *array; + + f_array_length_t size; + f_array_length_t used; + } f_limit_sets_t; + + #define f_limit_sets_t_initialize { 0, 0, 0 } + + #define f_macro_limit_sets_t_clear(sets) f_macro_memory_structure_t_clear(sets) + + #define f_macro_limit_sets_t_new(status, sets, length) f_macro_memory_structure_t_new(status, sets, f_limit_set_t, length) + + #define f_macro_limit_sets_t_delete(status, sets) f_macro_memory_structure_t_delete(status, sets, f_limit_set_t) + #define f_macro_limit_sets_t_destroy(status, sets) f_macro_memory_structure_t_destroy(status, sets, f_limit_set_t) + + #define f_macro_limit_sets_t_delete_simple(sets) f_macro_memory_structure_t_delete_simple(sets, f_limit_set_t) + #define f_macro_limit_sets_t_destroy_simple(sets) f_macro_memory_structure_t_destroy_simple(sets, f_limit_set_t) + + #define f_macro_limit_sets_t_resize(status, sets, new_length) f_macro_memory_structure_t_resize(status, sets, f_limit_set_t, new_length) + #define f_macro_limit_sets_t_adjust(status, sets, new_length) f_macro_memory_structure_t_adjust(status, sets, f_limit_set_t, new_length) +#endif // _di_f_limit_sets_t_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _F_limit_common_h diff --git a/level_0/f_limit/c/limit.c b/level_0/f_limit/c/limit.c new file mode 100644 index 0000000..26247a8 --- /dev/null +++ b/level_0/f_limit/c/limit.c @@ -0,0 +1,192 @@ +#include "limit.h" +#include "private-limit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_f_limit_process_ + f_return_status f_limit_process(const pid_t id, const int type, const f_limit_value_t *value_next, f_limit_value_t *value_current) { + #ifndef _di_level_0_parameter_checking_ + if (!value_next && !value_current) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (prlimit(id, type, value_next, value_current) < 0) { + if (errno == EFAULT) return F_status_set_error(F_address_not); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == ESRCH) return F_status_set_error(F_found_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_limit_process_ + +#ifndef _di_f_limit_sets_decrease_ + f_return_status f_limit_sets_decrease(f_limit_sets_t *sets) { + #ifndef _di_level_0_parameter_checking_ + if (!sets) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (sets->size > 1) { + return private_f_limit_sets_resize(sets->size - 1, sets); + } + + return private_f_limit_sets_delete(sets); + } +#endif // _di_f_limit_sets_decrease_ + +#ifndef _di_f_limit_sets_decrease_by_ + f_return_status f_limit_sets_decrease_by(const f_array_length_t amount, f_limit_sets_t *sets) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!sets) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (sets->size - amount > 0) { + return private_f_limit_sets_resize(sets->size - amount, sets); + } + + return private_f_limit_sets_delete(sets); + } +#endif // _di_f_limit_sets_decrease_by_ + +#ifndef _di_f_limit_sets_delete_ + f_return_status f_limit_sets_delete(f_limit_sets_t *sets) { + #ifndef _di_level_0_parameter_checking_ + if (!sets) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_limit_sets_delete(sets); + } +#endif // _di_f_limit_sets_delete_ + +#ifndef _di_f_limit_sets_increase_ + f_return_status f_limit_sets_increase(f_limit_sets_t *sets) { + #ifndef _di_level_0_parameter_checking_ + if (!sets) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (sets->used + 1 > sets->size) { + f_array_length_t size = sets->used + f_memory_default_allocation_step; + + if (size > f_array_length_t_size) { + if (sets->used + 1 > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + size = f_array_length_t_size; + } + + return private_f_limit_sets_resize(size, sets); + } + + return F_none; + } +#endif // _di_f_limit_sets_increase_ + +#ifndef _di_f_limit_sets_increase_by_ + f_return_status f_limit_sets_increase_by(const f_array_length_t amount, f_limit_sets_t *sets) { + #ifndef _di_level_0_parameter_checking_ + if (!sets) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (sets->used + amount > sets->size) { + if (sets->used + amount > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + return private_f_limit_sets_resize(sets->used + amount, sets); + } + + return F_none; + } +#endif // _di_f_limit_sets_increase_by_ + +#ifndef _di_f_limit_values_decrease_ + f_return_status f_limit_values_decrease(f_limit_values_t *values) { + #ifndef _di_level_0_parameter_checking_ + if (!values) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (values->size > 1) { + return private_f_limit_values_resize(values->size - 1, values); + } + + return private_f_limit_values_delete(values); + } +#endif // _di_f_limit_values_decrease_ + +#ifndef _di_f_limit_values_decrease_by_ + f_return_status f_limit_values_decrease_by(const f_array_length_t amount, f_limit_values_t *values) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!values) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (values->size - amount > 0) { + return private_f_limit_values_resize(values->size - amount, values); + } + + return private_f_limit_values_delete(values); + } +#endif // _di_f_limit_values_decrease_by_ + +#ifndef _di_f_limit_values_delete_ + f_return_status f_limit_values_delete(f_limit_values_t *values) { + #ifndef _di_level_0_parameter_checking_ + if (!values) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_limit_values_delete(values); + } +#endif // _di_f_limit_values_delete_ + +#ifndef _di_f_limit_values_increase_ + f_return_status f_limit_values_increase(f_limit_values_t *values) { + #ifndef _di_level_0_parameter_checking_ + if (!values) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (values->used + 1 > values->size) { + f_array_length_t size = values->used + f_memory_default_allocation_step; + + if (size > f_array_length_t_size) { + if (values->used + 1 > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + size = f_array_length_t_size; + } + + return private_f_limit_values_resize(size, values); + } + + return F_none; + } +#endif // _di_f_limit_values_increase_ + +#ifndef _di_f_limit_values_increase_by_ + f_return_status f_limit_values_increase_by(const f_array_length_t amount, f_limit_values_t *values) { + #ifndef _di_level_0_parameter_checking_ + if (!values) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (values->used + amount > values->size) { + if (values->used + amount > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + return private_f_limit_values_resize(values->used + amount, values); + } + + return F_none; + } +#endif // _di_f_limit_values_increase_by_ + + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_limit/c/limit.h b/level_0/f_limit/c/limit.h new file mode 100644 index 0000000..5a17766 --- /dev/null +++ b/level_0/f_limit/c/limit.h @@ -0,0 +1,262 @@ +/** + * FLL - Level 0 + * + * Project: Limit + * API Version: 0.5 + * Licenses: lgplv2.1 + * + * Provides limit related functionality. + */ +#ifndef _F_limit_h +#define _F_limit_h + +// include pre-requirements +#define _GNU_SOURCE + +// libc includes +#include +#include + +// fll-0 includes +#include +#include +#include + +// fll-1 control includes +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get or set the resource limits for some process. + * + * Either value_next or value_current must be non-zero. + * + * @param id + * The PID to set the resources of. + * @param type + * The resource type to set limit of or get limit of. + * @param value_next + * The resource value to assign. + * If 0 is used instead of a valid value, then value_current must be non-zero and will be populated with the current resource value. + * @param value_current + * The resource value currently assigned. + * If 0, then value_next is assigning the value but the previous value will not be returned. + * If both value_next and value_current are non-zero, then this represents the value prior to the assignment of value_next. + * + * @return + * F_none on success. + * F_address_not (with error bit) if a pointer is outside of valid address space. + * F_found_not (with error bit) if no process by the given PID was found. + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if not allowed to perform this action. + * + * @see prlimit() + */ +#ifndef _di_f_limit_process_ + extern f_return_status f_limit_process(const pid_t id, const int type, const f_limit_value_t *value_next, f_limit_value_t *value_current); +#endif // _di_f_limit_process_ + +/** + * Resize the sets array to a smaller size, by 1. + * + * This will shrink the size by size - 1. + * This will not shrink the size to less than 0. + * + * @param sets + * The string array to resize. + * + * @return + * F_none on success. + * F_memory_allocation (with error bit) on memory allocation error. + * F_memory_reallocation (with error bit) on memory reallocation error. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_limit_sets_decrease_ + extern f_return_status f_limit_sets_decrease(f_limit_sets_t *sets); +#endif // _di_f_limit_sets_decrease_ + +/** + * Resize the sets array to a smaller size. + * + * This will resize making the array smaller based on (size - given length). + * If the given length is too small, then the resize will fail. + * This will not shrink the size to less than 0. + * + * @param amount + * A positive number representing how much to decrease the size by. + * @param sets + * The string array to resize. + * + * @return + * F_none on success. + * F_memory_allocation (with error bit) on memory allocation error. + * F_memory_reallocation (with error bit) on memory reallocation error. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_limit_sets_decrease_by_ + extern f_return_status f_limit_sets_decrease_by(const f_array_length_t amount, f_limit_sets_t *sets); +#endif // _di_f_limit_sets_decrease_by_ + +/** + * Delete the sets array. + * + * @param string + * The string to delete. + * + * @return + * F_none on success. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_limit_sets_delete_ + extern f_return_status f_limit_sets_delete(f_limit_sets_t *sets); +#endif // _di_f_limit_sets_delete_ + +/** + * Increase the size of the sets array, but only if necessary. + * + * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param sets + * The string array to resize. + * + * @return + * F_none on success. + * F_memory_allocation (with error bit) on memory allocation error. + * F_memory_reallocation (with error bit) on memory reallocation error. + * F_parameter (with error bit) if a parameter is invalid. + * F_array_too_large (with error bit) if the new array length is too large. + */ +#ifndef _di_f_limit_sets_increase_ + extern f_return_status f_limit_sets_increase(f_limit_sets_t *sets); +#endif // _di_f_limit_sets_increase_ + +/** + * Resize the sets array to a larger size. + * + * This will resize making the array larger based on the given length. + * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param amount + * A positive number representing how much to increase the size by. + * @param sets + * The string array to resize. + * + * @return + * F_none on success. + * F_memory_allocation (with error bit) on memory allocation error. + * F_memory_reallocation (with error bit) on memory reallocation error. + * F_parameter (with error bit) if a parameter is invalid. + * F_array_too_large (with error bit) if the new array length is too large. + */ +#ifndef _di_f_limit_sets_increase_by_ + extern f_return_status f_limit_sets_increase_by(const f_array_length_t amount, f_limit_sets_t *sets); +#endif // _di_f_limit_sets_increase_by_ + +/** + * Resize the values array to a smaller size, by 1. + * + * This will shrink the size by size - 1. + * This will not shrink the size to less than 0. + * + * @param values + * The string array to resize. + * + * @return + * F_none on success. + * F_memory_allocation (with error bit) on memory allocation error. + * F_memory_reallocation (with error bit) on memory reallocation error. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_limit_values_decrease_ + extern f_return_status f_limit_values_decrease(f_limit_values_t *values); +#endif // _di_f_limit_values_decrease_ + +/** + * Resize the values array to a smaller size. + * + * This will resize making the array smaller based on (size - given length). + * If the given length is too small, then the resize will fail. + * This will not shrink the size to less than 0. + * + * @param amount + * A positive number representing how much to decrease the size by. + * @param values + * The string array to resize. + * + * @return + * F_none on success. + * F_memory_allocation (with error bit) on memory allocation error. + * F_memory_reallocation (with error bit) on memory reallocation error. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_limit_values_decrease_by_ + extern f_return_status f_limit_values_decrease_by(const f_array_length_t amount, f_limit_values_t *values); +#endif // _di_f_limit_values_decrease_by_ + +/** + * Delete the values array. + * + * @param string + * The string to delete. + * + * @return + * F_none on success. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_limit_values_delete_ + extern f_return_status f_limit_values_delete(f_limit_values_t *values); +#endif // _di_f_limit_values_delete_ + +/** + * Increase the size of the values array, but only if necessary. + * + * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param values + * The string array to resize. + * + * @return + * F_none on success. + * F_memory_allocation (with error bit) on memory allocation error. + * F_memory_reallocation (with error bit) on memory reallocation error. + * F_parameter (with error bit) if a parameter is invalid. + * F_array_too_large (with error bit) if the new array length is too large. + */ +#ifndef _di_f_limit_values_increase_ + extern f_return_status f_limit_values_increase(f_limit_values_t *values); +#endif // _di_f_limit_values_increase_ + +/** + * Resize the values array to a larger size. + * + * This will resize making the array larger based on the given length. + * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param amount + * A positive number representing how much to increase the size by. + * @param values + * The string array to resize. + * + * @return + * F_none on success. + * F_memory_allocation (with error bit) on memory allocation error. + * F_memory_reallocation (with error bit) on memory reallocation error. + * F_parameter (with error bit) if a parameter is invalid. + * F_array_too_large (with error bit) if the new array length is too large. + */ +#ifndef _di_f_limit_values_increase_by_ + extern f_return_status f_limit_values_increase_by(const f_array_length_t amount, f_limit_values_t *values); +#endif // _di_f_limit_values_increase_by_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _F_limit_h diff --git a/level_0/f_limit/c/private-limit.c b/level_0/f_limit/c/private-limit.c new file mode 100644 index 0000000..8a48b18 --- /dev/null +++ b/level_0/f_limit/c/private-limit.c @@ -0,0 +1,50 @@ +#include "limit.h" +#include "private-limit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_di_f_limit_sets_decrease_) || !defined(_di_f_limit_sets_decrease_by_) || !defined(_di_f_limit_sets_delete_) + f_return_status private_f_limit_sets_delete(f_limit_sets_t *sets) { + f_status_t status = F_none; + + f_macro_limit_sets_t_delete(status, (*sets)); + + return status; + } +#endif // !defined(_di_f_limit_sets_decrease_) || !defined(_di_f_limit_sets_decrease_by_) || !defined(_di_f_limit_sets_delete_) + +#if !defined(_di_f_limit_sets_decrease_) || !defined(_di_f_limit_sets_decrease_by_) || !defined(_di_f_limit_sets_increase_) || !defined(_di_f_limit_sets_increase_by_) + f_return_status private_f_limit_sets_resize(const f_array_length_t length, f_limit_sets_t *sets) { + f_status_t status = F_none; + + f_macro_limit_sets_t_resize(status, (*sets), length); + + return status; + } +#endif // !defined(_di_f_limit_sets_decrease_) || !defined(_di_f_limit_sets_decrease_by_) || !defined(_di_f_limit_sets_increase_) || !defined(_di_f_limit_sets_increase_by_) + +#if !defined(_di_f_limit_values_decrease_) || !defined(_di_f_limit_values_decrease_by_) || !defined(_di_f_limit_values_delete_) + f_return_status private_f_limit_values_delete(f_limit_values_t *values) { + f_status_t status = F_none; + + f_macro_limit_values_t_delete(status, (*values)); + + return status; + } +#endif // !defined(_di_f_limit_values_decrease_) || !defined(_di_f_limit_values_decrease_by_) || !defined(_di_f_limit_values_delete_) + +#if !defined(_di_f_limit_values_decrease_) || !defined(_di_f_limit_values_decrease_by_) || !defined(_di_f_limit_values_increase_) || !defined(_di_f_limit_values_increase_by_) + f_return_status private_f_limit_values_resize(const f_array_length_t length, f_limit_values_t *values) { + f_status_t status = F_none; + + f_macro_limit_values_t_resize(status, (*values), length); + + return status; + } +#endif // !defined(_di_f_limit_values_decrease_) || !defined(_di_f_limit_values_decrease_by_) || !defined(_di_f_limit_values_increase_) || !defined(_di_f_limit_values_increase_by_) + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_limit/c/private-limit.h b/level_0/f_limit/c/private-limit.h new file mode 100644 index 0000000..b60b7a5 --- /dev/null +++ b/level_0/f_limit/c/private-limit.h @@ -0,0 +1,116 @@ +/** + * FLL - Level 0 + * + * Project: Limit + * API Version: 0.5 + * Licenses: lgplv2.1 + * + * These are provided for internal reduction in redundant code. + * These should not be exposed/used outside of this project. + */ +#ifndef _PRIVATE_F_limit_h +#define _PRIVATE_F_limit_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Private implementation of f_limit_sets_delete(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param sets + * The sets to delete. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_macro_limit_sets_t_delete(). + * + * @see f_macro_limit_sets_t_delete() + * @see f_limit_sets_decrease() + * @see f_limit_sets_decrease_by() + * @see f_limit_sets_delete() + */ +#if !defined(_di_f_limit_sets_decrease_) || !defined(_di_f_limit_sets_decrease_by_) || !defined(_di_f_limit_sets_delete_) + extern f_return_status private_f_limit_sets_delete(f_limit_sets_t *sets) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_limit_sets_decrease_) || !defined(_di_f_limit_sets_decrease_by_) || !defined(_di_f_limit_sets_delete_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param sets + * The sets to resize. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_macro_limit_sets_t_resize(). + * + * @see f_macro_limit_sets_t_resize() + * @see f_limit_sets_decrease() + * @see f_limit_sets_decrease_by() + * @see f_limit_sets_increase() + * @see f_limit_sets_increase_by() + */ +#if !defined(_di_f_limit_sets_decrease_) || !defined(_di_f_limit_sets_decrease_by_) || !defined(_di_f_limit_sets_increase_) || !defined(_di_f_limit_sets_increase_by_) + extern f_return_status private_f_limit_sets_resize(const f_array_length_t length, f_limit_sets_t *sets) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_limit_sets_decrease_) || !defined(_di_f_limit_sets_decrease_by_) || !defined(_di_f_limit_sets_increase_) || !defined(_di_f_limit_sets_increase_by_) + +/** + * Private implementation of f_limit_values_delete(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param values + * The values to delete. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_macro_limit_values_t_delete(). + * + * @see f_macro_limit_values_t_delete() + * @see f_limit_values_decrease() + * @see f_limit_values_decrease_by() + * @see f_limit_values_delete() + */ +#if !defined(_di_f_limit_values_decrease_) || !defined(_di_f_limit_values_decrease_by_) || !defined(_di_f_limit_values_delete_) + extern f_return_status private_f_limit_values_delete(f_limit_values_t *values) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_limit_values_decrease_) || !defined(_di_f_limit_values_decrease_by_) || !defined(_di_f_limit_values_delete_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param values + * The values to resize. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_macro_limit_values_t_resize(). + * + * @see f_macro_limit_values_t_resize() + * @see f_limit_values_decrease() + * @see f_limit_values_decrease_by() + * @see f_limit_values_increase() + * @see f_limit_values_increase_by() + */ +#if !defined(_di_f_limit_values_decrease_) || !defined(_di_f_limit_values_decrease_by_) || !defined(_di_f_limit_values_increase_) || !defined(_di_f_limit_values_increase_by_) + extern f_return_status private_f_limit_values_resize(const f_array_length_t length, f_limit_values_t *values) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_limit_values_decrease_) || !defined(_di_f_limit_values_decrease_by_) || !defined(_di_f_limit_values_increase_) || !defined(_di_f_limit_values_increase_by_) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PRIVATE_F_limit_h diff --git a/level_0/f_limit/data/build/defines b/level_0/f_limit/data/build/defines new file mode 100644 index 0000000..4f13080 --- /dev/null +++ b/level_0/f_limit/data/build/defines @@ -0,0 +1 @@ +# fss-0000 diff --git a/level_0/f_limit/data/build/dependencies b/level_0/f_limit/data/build/dependencies new file mode 100644 index 0000000..66dca29 --- /dev/null +++ b/level_0/f_limit/data/build/dependencies @@ -0,0 +1,5 @@ +# fss-0000 + +f_type +f_status +f_memory diff --git a/level_0/f_limit/data/build/settings b/level_0/f_limit/data/build/settings new file mode 100644 index 0000000..5e95afa --- /dev/null +++ b/level_0/f_limit/data/build/settings @@ -0,0 +1,55 @@ +# fss-0001 + +project_name f_limit + +version_major 0 +version_minor 5 +version_micro 3 +version_target major + +environment + +process_pre +process_post + +modes individual +modes_default individual + +build_compiler gcc +build_indexer ar +build_language c +build_libraries -lc +build_libraries-individual -lf_memory +build_sources_library limit.c private-limit.c +build_sources_program +build_sources_headers limit.h limit-common.h +build_sources_script +build_sources_setting +build_script yes +build_shared yes +build_static no + +path_headers level_0 +path_headers_preserve no +path_library_script script +path_library_shared shared +path_library_static static +path_program_script script +path_program_shared shared +path_program_static static +path_sources +path_standard yes + +search_exclusive yes +search_shared yes +search_static yes + +defines_all +defines_static +defines_shared + +flags_all -z now -g -fdiagnostics-color=always +flags_shared +flags_static +flags_library -fPIC +flags_program -fPIE diff --git a/level_0/f_status/c/status.h b/level_0/f_status/c/status.h index 8d17fa5..8ec171f 100644 --- a/level_0/f_status/c/status.h +++ b/level_0/f_status/c/status.h @@ -204,6 +204,8 @@ extern "C" { F_interrupt_not, F_known, F_known_not, + F_limit, + F_limit_not, F_link, F_link_not, F_lock, @@ -234,6 +236,8 @@ extern "C" { F_pipe_not, F_port, F_port_not, + F_processor, + F_processor_not, F_prohibited, F_prohibited_not, F_range, diff --git a/level_0/f_string/c/string-common.h b/level_0/f_string/c/string-common.h index 4c6c9aa..eb61ade 100644 --- a/level_0/f_string/c/string-common.h +++ b/level_0/f_string/c/string-common.h @@ -30,35 +30,42 @@ extern "C" { */ #ifndef _di_f_string_has_eol_ #define f_string_eol "\n" + #define f_string_eol_length 1 #endif // _di_f_string_has_eol_ #ifndef _di_f_string_has_placeholder_ #define f_string_placeholder "\0" + #define f_string_placeholder_length 1 #endif // _di_f_string_has_placeholder_ +#ifndef _di_f_string_has_space_ + #define f_string_space " " + #define f_string_space_length 1 +#endif // _di_f_string_has_space_ + #ifndef _di_string_format_pointers_ - #define string_format_string "%s" - #define string_format_character "%c" - #define string_format_wide_string "%ls" - #define string_format_wide_character "%lc" - #define string_format_integer "%i" - #define string_format_unsigned "%u" - #define string_format_double "%d" - #define string_format_float "%f" - #define string_format_short_integer "%hi" - #define string_format_short_unsigned "%hu" - #define string_format_long_integer "%li" - #define string_format_long_unsigned "%lu" - #define string_format_long_double "%ld" - #define string_format_long_long_integer "%lli" - #define string_format_long_long_unsigned "%llu" + #define f_string_format_string "%s" + #define f_string_format_character "%c" + #define f_string_format_wide_string "%ls" + #define f_string_format_wide_character "%lc" + #define f_string_format_integer "%i" + #define f_string_format_unsigned "%u" + #define f_string_format_double "%d" + #define f_string_format_float "%f" + #define f_string_format_short_integer "%hi" + #define f_string_format_short_unsigned "%hu" + #define f_string_format_long_integer "%li" + #define f_string_format_long_unsigned "%lu" + #define f_string_format_long_double "%ld" + #define f_string_format_long_long_integer "%lli" + #define f_string_format_long_long_unsigned "%llu" #endif // _di_string_format_pointers_ -#ifndef _di_f_array_t_length_printf_ +#ifndef _di_f_array_length_printf_ #define f_array_length_printf string_format_integer #define f_array_length_short_printf string_format_short_integer #define f_array_length_long_printf string_format_long_integer -#endif // _di_f_array_t_length_printf_ +#endif // _di_f_array_length_printf_ /** * Define the basic string type. diff --git a/level_0/f_string/c/string.h b/level_0/f_string/c/string.h index 5034235..7d2f9f0 100644 --- a/level_0/f_string/c/string.h +++ b/level_0/f_string/c/string.h @@ -45,6 +45,10 @@ extern "C" { const static f_string_t f_string_placeholder_s = f_string_placeholder; #endif // _di_f_string_has_placeholder_ +#ifndef _di_f_string_has_space_ + const static f_string_t f_string_space_s = f_string_space; +#endif // _di_f_string_has_space_ + #ifndef _di_f_string_static_empty_s_ const static f_string_static_t f_string_static_empty_s = f_macro_string_static_t_initialize(f_string_empty_s, 0); #endif // _di_f_string_static_empty_s_ diff --git a/level_0/f_type/c/type_array.h b/level_0/f_type/c/type_array.h index 8b178ba..ccb663d 100644 --- a/level_0/f_type/c/type_array.h +++ b/level_0/f_type/c/type_array.h @@ -27,7 +27,7 @@ extern "C" { * size: Total amount of allocated space. * used: Total number of allocated spaces used. */ -#ifndef _di_f_array_t_lengths_t_ +#ifndef _di_f_array_lengths_t_ typedef struct { f_array_length_t *array; @@ -49,7 +49,7 @@ extern "C" { #define f_macro_array_lengths_t_resize(status, lengths, new_length) f_macro_memory_structure_t_resize(status, lengths, f_array_length_t, new_length) #define f_macro_array_lengths_t_adjust(status, lengths, new_length) f_macro_memory_structure_t_adjust(status, lengths, f_array_length_t, new_length) -#endif // _di_f_array_t_lengths_t_ +#endif // _di_f_array_lengths_t_ /** * An array of an array of array lengths. @@ -58,7 +58,7 @@ extern "C" { * size: total amount of allocated space. * used: total number of allocated spaces used. */ -#ifndef _di_f_array_t_lengthss_t_ +#ifndef _di_f_array_lengthss_t_ typedef struct { f_array_lengths_t *array; @@ -80,7 +80,7 @@ extern "C" { #define f_macro_array_lengthss_t_resize(status, lengths, new_length) f_macro_memory_structures_t_resize(status, lengths, f_array_length_t, f_array_lengths_t, new_length, f_array_length_t) #define f_macro_array_lengthss_t_adjust(status, lengths, new_length) f_macro_memory_structures_t_adjust(status, lengths, f_array_length_t, f_array_lengths_t, new_length, f_array_length_t) -#endif // _di_f_array_t_lengthss_t_ +#endif // _di_f_array_lengthss_t_ /** * An array of f_cell_t. diff --git a/level_1/fl_execute/c/execute-common.h b/level_1/fl_execute/c/execute-common.h index c876d11..ae8b43d 100644 --- a/level_1/fl_execute/c/execute-common.h +++ b/level_1/fl_execute/c/execute-common.h @@ -66,8 +66,10 @@ extern "C" { * nice: the niceness value to assign the child process to, set to 0 to not use. * id_user: the id of the user to assign the child process to, set to 0 to not use. * id_group: the id of the group to assign the child process to, set to 0 to not use. + * affinity: the cpu affinity to assign the child process to, set to 0 to not use (this is an array of CPU ids, starting from 0). * capability: all of the capabilities to assign the child process to, set to 0 to not use (f_capability_t is a pointer). * control_group: an array of cgroups (control groups) to assign the child PID to, set to 0 to not use. + * limits: the resource limits to assign the child process to, set to 0 to not use. * id_groups: the ids of each supplemental group to assign the child process to, set to 0 to not use. * scheduler: the scheduler to assign the child process to, set to 0 to not use. */ @@ -77,23 +79,27 @@ extern "C" { uid_t *id_user; gid_t *id_group; + f_int32s_t *affinity; f_capability_t capability; f_control_group_t *control_group; f_int32s_t *id_groups; + f_limit_sets_t *limits; f_execute_scheduler_t *scheduler; } fl_execute_as_t; - #define fl_execute_as_t_initialize { 0, 0, 0, 0, 0, 0, 0 } + #define fl_execute_as_t_initialize { 0, 0, 0, 0, 0, 0, 0, 0, 0 } - #define fl_macro_execute_as_t_initialize(nice, id_user, id_group, capability, control_group, id_groups, scheduler) { nice, id_user, id_group, capability, control_group, id_groups, scheduler } + #define fl_macro_execute_as_t_initialize(nice, id_user, id_group, affinity, capability, control_group, id_groups, limits, scheduler) { nice, id_user, id_group, affinity, capability, control_group, id_groups, limits, scheduler } #define fl_execute_as_t_clear(as) \ as.nice = 0; \ as.id_user = 0; \ as.id_group = 0; \ + as.affinity = 0; \ as.capability = 0; \ as.control_group = 0; \ as.id_groups = 0; \ + as.limits = 0; \ as.scheduler = 0; #endif // _di_fl_execute_as_t_ diff --git a/level_1/fl_execute/c/execute.h b/level_1/fl_execute/c/execute.h index 9f03005..f4a98cb 100644 --- a/level_1/fl_execute/c/execute.h +++ b/level_1/fl_execute/c/execute.h @@ -23,10 +23,11 @@ // fll-0 includes #include +#include #include #include +#include #include -#include // fll-1 execute includes #include diff --git a/level_1/fl_execute/data/build/dependencies b/level_1/fl_execute/data/build/dependencies index 7e33434..2747470 100644 --- a/level_1/fl_execute/data/build/dependencies +++ b/level_1/fl_execute/data/build/dependencies @@ -4,5 +4,6 @@ f_type f_status f_string f_capability +f_limit f_signal f_execute diff --git a/level_1/fl_execute/data/build/settings b/level_1/fl_execute/data/build/settings index 3e48aed..9b4c26d 100644 --- a/level_1/fl_execute/data/build/settings +++ b/level_1/fl_execute/data/build/settings @@ -19,7 +19,7 @@ build_compiler gcc build_indexer ar build_language c build_libraries -lc -lcap -build_libraries-individual -lf_capability -lf_memory -lf_signal +build_libraries-individual -lf_capability -lf_limit -lf_memory -lf_signal build_sources_library build_sources_program build_sources_headers execute.h execute-common.h diff --git a/level_1/fl_status/c/status.c b/level_1/fl_status/c/status.c index 1a5aa85..d500c72 100644 --- a/level_1/fl_status/c/status.c +++ b/level_1/fl_status/c/status.c @@ -389,11 +389,11 @@ extern "C" { case F_interrupt_not: *string = FL_status_string_interrupt_not; break; - case F_valid: - *string = FL_status_string_valid; + case F_limit: + *string = FL_status_string_limit; break; - case F_valid_not: - *string = FL_status_string_valid_not; + case F_limit_not: + *string = FL_status_string_limit_not; break; case F_link: *string = FL_status_string_link; @@ -485,6 +485,12 @@ extern "C" { case F_port_not: *string = FL_status_string_port_not; break; + case F_processor: + *string = FL_status_string_processor; + break; + case F_processor_not: + *string = FL_status_string_processor_not; + break; case F_prohibited: *string = FL_status_string_prohibited; break; @@ -620,6 +626,12 @@ extern "C" { case F_utf_not: *string = FL_status_string_utf_not; break; + case F_valid: + *string = FL_status_string_valid; + break; + case F_valid_not: + *string = FL_status_string_valid_not; + break; case F_value: *string = FL_status_string_value; break; diff --git a/level_1/fl_status/c/status.h b/level_1/fl_status/c/status.h index 8fe136d..bf6dec7 100644 --- a/level_1/fl_status/c/status.h +++ b/level_1/fl_status/c/status.h @@ -223,6 +223,8 @@ extern "C" { #define FL_status_string_interrupt_not "F_interrupt_not" #define FL_status_string_known "F_known" #define FL_status_string_known_not "F_known_not" + #define FL_status_string_limit "F_limit" + #define FL_status_string_limit_not "F_limit_not" #define FL_status_string_link "F_link" #define FL_status_string_link_not "F_link_not" #define FL_status_string_lock "F_lock" @@ -253,6 +255,8 @@ extern "C" { #define FL_status_string_pipe_not "F_pipe_not" #define FL_status_string_port "F_port" #define FL_status_string_port_not "F_port_not" + #define FL_status_string_processor "F_processor" + #define FL_status_string_processor_not "F_processor_not" #define FL_status_string_prohibited "F_prohibited" #define FL_status_string_prohibited_not "F_prohibited_not" #define FL_status_string_range "F_range" @@ -370,6 +374,8 @@ extern "C" { #define FL_status_string_interrupt_not_length 15 #define FL_status_string_known_length 7 #define FL_status_string_known_not_length 11 + #define FL_status_string_limit_length 7 + #define FL_status_string_limit_not_length 11 #define FL_status_string_link_length 6 #define FL_status_string_link_not_length 10 #define FL_status_string_lock_length 6 @@ -400,6 +406,8 @@ extern "C" { #define FL_status_string_pipe_not_length 10 #define FL_status_string_port_length 6 #define FL_status_string_port_not_length 10 + #define FL_status_string_processor_length 11 + #define FL_status_string_processor_not_length 15 #define FL_status_string_prohibited_length 12 #define FL_status_string_prohibited_not_length 16 #define FL_status_string_range_length 7 diff --git a/level_2/fll_execute/c/execute.h b/level_2/fll_execute/c/execute.h index d6ae81f..f3d752c 100644 --- a/level_2/fll_execute/c/execute.h +++ b/level_2/fll_execute/c/execute.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -399,7 +400,7 @@ extern "C" { * This returns F_capability, F_group, and F_user only by the child process and must be treated the same as F_child for the purposes of understanding what the current process is. * These are essentialy F_child with explicit error codes that are returned instead of performing the desired execution. * - * This returns F_control_group and F_schedule only by the parent process and represents that the child process could not be executed. + * This returns F_control_group, F_limit, F_processor, and F_schedule only by the parent process and represents that the child process could not be executed. * * @param program * The name or path of the program. @@ -438,14 +439,17 @@ extern "C" { * F_failure (with error bit) on execution failure. * F_fork (with error bit) on fork failure. * F_group (with error bit) on failure to set GID in the child (only the child process returns this). + * F_limit (with error bit) on failure to set a resource limit in the child (only the parent process returns this). * F_nice (with error bit) on failure to set process niceness in the child (only the child process returns this). * F_pipe (with error bit) on pipe failure. + * F_processor (with error bit) on failure to set a processor (cpu) affinity in the child (only the parent process returns this). * F_schedule (with error bit) on failure to set scheduler in the child (only the parent process returns this). * F_user (with error bit) on failure to set UID in the child (only the child process returns this). * * Errors (with error bit) from: f_capability_process_set(). * Errors (with error bit) from: f_environment_get(). * Errors (with error bit) from: f_file_exists(). + * Errors (with error bit) from: f_limit_process(). * Errors (with error bit) from: f_macro_string_dynamics_t_delete(). * Errors (with error bit) from: f_signal_mask(). * Errors (with error bit) from: f_thread_signal_mask(). @@ -465,6 +469,7 @@ extern "C" { * @see memcpy() * @see nice() * @see pipe() + * @see sched_setaffinity() * @see sched_setscheduler() * @see setgid() * @see setgroups() @@ -475,6 +480,7 @@ extern "C" { * @see f_capability_process_set() * @see f_environment_get() * @see f_file_exists() + * @see f_limit_process() * @see f_signal_mask() * @see f_thread_signal_mask() * @see fl_control_group_apply() diff --git a/level_2/fll_execute/c/private-execute.c b/level_2/fll_execute/c/private-execute.c index 9f88548..b863576 100644 --- a/level_2/fll_execute/c/private-execute.c +++ b/level_2/fll_execute/c/private-execute.c @@ -190,6 +190,42 @@ extern "C" { #if !defined(_di_fll_execute_program_) f_return_status private_fll_execute_as_parent(const fl_execute_as_t as, const pid_t id_child, fl_execute_parameter_t * const parameter, char *result) { + if (as.affinity && as.affinity->used) { + cpu_set_t *set = CPU_ALLOC(as.affinity->used); + + if (set == 0) { + result[0] = '1'; + + return F_status_set_error(F_processor); + } + + size_t size = CPU_ALLOC_SIZE(as.affinity->used); + + CPU_ZERO_S(size, set); + + for (f_array_length_t i = 0; i < as.affinity->used; ++i) { + CPU_SET_S(as.affinity->array[i], size, set); + } // for + + const int response = sched_setaffinity(id_child, size, set); + + CPU_FREE(set); + + if (response == -1) { + result[0] = '1'; + + return F_status_set_error(F_processor); + } + } + + if (as.control_group) { + if (F_status_is_error(fl_control_group_apply(*as.control_group, id_child))) { + result[0] = '1'; + + return F_status_set_error(F_control_group); + } + } + if (as.scheduler) { struct sched_param parameter_schedule; parameter_schedule.sched_priority = as.scheduler->priority; @@ -203,12 +239,15 @@ extern "C" { } } - if (as.control_group) { - if (F_status_is_error(fl_control_group_apply(*as.control_group, id_child))) { - result[0] = '1'; + if (as.limits) { + for (f_array_length_t i = 0; i < as.limits->used; ++i) { - return F_status_set_error(F_control_group); - } + if (F_status_is_error(f_limit_process(id_child, as.limits->array[i].type, &as.limits->array[i].value, 0))) { + result[0] = '1'; + + return F_status_set_error(F_limit); + } + } // for } return F_none; diff --git a/level_2/fll_execute/c/private-execute.h b/level_2/fll_execute/c/private-execute.h index 3fc9b21..c1581e5 100644 --- a/level_2/fll_execute/c/private-execute.h +++ b/level_2/fll_execute/c/private-execute.h @@ -109,12 +109,12 @@ extern "C" { * F_capability (with error bit) on failure to set capabilities. * F_group (with error bit) on failure to set GID. * F_nice (with error bit) on failure to set process niceness. - * F_schedule (with error bit) on failure to set scheduler. * F_user (with error bit) on failure to set UID. * * @see exit() * @see getpid() * @see nice() + * @see sched_setaffinity() * @see sched_setscheduler() * @see setgid() * @see setgroups() @@ -146,21 +146,22 @@ extern "C" { * * @return * F_none on success. - * F_capability (with error bit) on failure to set capabilities. - * F_group (with error bit) on failure to set GID. - * F_nice (with error bit) on failure to set process niceness. + * F_control_group (with error bit) on failure to set control group. + * F_limit (with error bit) on failure to set a resource limit. + * F_processor (with error bit) on failure to set processor (cpu) affinity. * F_schedule (with error bit) on failure to set scheduler. - * F_user (with error bit) on failure to set UID. * * @see exit() * @see getpid() * @see nice() + * @see sched_setaffinity() * @see sched_setscheduler() * @see setgid() * @see setgroups() * @see setuid() * * @see f_capability_process_set() + * @see f_limit_process() * @see fll_execute_program() */ #if !defined(_di_fll_execute_program_) @@ -203,13 +204,15 @@ extern "C" { * F_none on success. * F_child on success but this is the child thread. * F_capability (with error bit) on failure to set capabilities in the child (only the child process returns this). - * F_control_group (with error bit) on failure to set capabilities in the child (only the parent process returns this). + * F_control_group (with error bit) on failure to set control group in the child (only the parent process returns this). * F_child (with error bit) on any failure without an explicit failure code (like F_group) before calling execute but this is the child thread. * F_failure (with error bit) on execution failure. * F_fork (with error bit) on fork failure. * F_group (with error bit) on failure to set GID in the child (only the child process returns this). + * F_limit (with error bit) on failure to set a resource limit in the child (only the parent process returns this). * F_nice (with error bit) on failure to set process niceness in the child (only the child process returns this). * F_pipe (with error bit) on pipe failure. + * F_processor (with error bit) on failure to set a processor (cpu) affinity in the child (only the parent process returns this). * F_schedule (with error bit) on failure to set scheduler in the child (only the parent process returns this). * F_user (with error bit) on failure to set UID in the child (only the child process returns this). * @@ -223,6 +226,7 @@ extern "C" { * @see waitpid() * * @see f_environment_set_dynamic() + * @see f_limit_process() * @see f_signal_mask() * @see f_thread_signal_mask() * @see fl_control_group_apply() @@ -268,13 +272,15 @@ extern "C" { * F_none on success. * F_child on success but this is the child thread. * F_capability (with error bit) on failure to set capabilities in the child (only the child process returns this). - * F_control_group (with error bit) on failure to set capabilities in the child (only the parent process returns this). + * F_control_group (with error bit) on failure to set control group in the child (only the parent process returns this). * F_child (with error bit) on any failure without an explicit failure code (like F_group) before calling execute but this is the child thread. * F_failure (with error bit) on execution failure. * F_fork (with error bit) on fork failure. * F_group (with error bit) on failure to set GID in the child (only the child process returns this). + * F_limit (with error bit) on failure to set a resource limit in the child (only the parent process returns this). * F_nice (with error bit) on failure to set process niceness in the child (only the child process returns this). * F_pipe (with error bit) on pipe failure. + * F_processor (with error bit) on failure to set a processor (cpu) affinity in the child (only the parent process returns this). * F_schedule (with error bit) on failure to set scheduler in the child (only the parent process returns this). * F_user (with error bit) on failure to set UID in the child (only the child process returns this). * @@ -288,6 +294,7 @@ extern "C" { * @see waitpid() * * @see f_environment_set_dynamic() + * @see f_limit_process() * @see f_signal_mask() * @see f_thread_signal_mask() * @see fll_execute_program() diff --git a/level_2/fll_execute/data/build/dependencies b/level_2/fll_execute/data/build/dependencies index 4e06e33..f87fce0 100644 --- a/level_2/fll_execute/data/build/dependencies +++ b/level_2/fll_execute/data/build/dependencies @@ -9,6 +9,7 @@ f_capability f_environment f_execute f_file +f_limit f_path f_signal f_thread diff --git a/level_2/fll_execute/data/build/settings b/level_2/fll_execute/data/build/settings index c95b57d..1620208 100644 --- a/level_2/fll_execute/data/build/settings +++ b/level_2/fll_execute/data/build/settings @@ -19,8 +19,8 @@ build_compiler gcc build_indexer ar build_language c build_libraries -lc -lcap -build_libraries-individual -lfl_control_group -lfl_environment -lfl_string -lf_account -lf_capability -lf_environment -lf_file -lf_memory -lf_path -lf_signal -lf_thread -lf_utf -build_libraries-individual_threadless -lfl_control_group -lfl_environment -lfl_string -lf_account -lf_capability -lf_environment -lf_file -lf_memory -lf_path -lf_signal -lf_utf +build_libraries-individual -lfl_control_group -lfl_environment -lfl_string -lf_account -lf_capability -lf_environment -lf_file -lf_limit -lf_memory -lf_path -lf_signal -lf_thread -lf_utf +build_libraries-individual_threadless -lfl_control_group -lfl_environment -lfl_string -lf_account -lf_capability -lf_environment -lf_file -lf_limit -lf_memory -lf_path -lf_signal -lf_utf build_sources_library execute.c private-execute.c build_sources_program build_sources_headers execute.h diff --git a/level_2/fll_program/c/program.c b/level_2/fll_program/c/program.c index 08201fc..1339263 100644 --- a/level_2/fll_program/c/program.c +++ b/level_2/fll_program/c/program.c @@ -68,14 +68,14 @@ extern "C" { fprintf(file.stream, "%c ", f_string_eol_s[0]); fl_color_print(file.stream, context.set.standout, name); - fprintf(file.stream, " "); + fprintf(file.stream, f_string_space_s); fl_color_print(file.stream, context.set.notable, "["); fprintf(file.stream, " options "); fl_color_print(file.stream, context.set.notable, "]"); if (parameters[0] != '\0') { - fprintf(file.stream, " "); + fprintf(file.stream, f_string_space_s); fl_color_print(file.stream, context.set.notable, "["); fprintf(file.stream, " %s ", parameters); diff --git a/level_2/fll_status/c/status.c b/level_2/fll_status/c/status.c index b7dfa55..894b814 100644 --- a/level_2/fll_status/c/status.c +++ b/level_2/fll_status/c/status.c @@ -661,6 +661,16 @@ extern "C" { return F_none; } + if (fl_string_compare(string, FL_status_string_limit, length, FL_status_string_limit_length) == F_equal_to) { + *code = F_limit; + return F_none; + } + + if (fl_string_compare(string, FL_status_string_limit_not, length, FL_status_string_limit_not_length) == F_equal_to) { + *code = F_limit_not; + return F_none; + } + if (fl_string_compare(string, FL_status_string_link, length, FL_status_string_link_length) == F_equal_to) { *code = F_link; return F_none; @@ -811,6 +821,16 @@ extern "C" { return F_none; } + if (fl_string_compare(string, FL_status_string_processor, length, FL_status_string_processor_length) == F_equal_to) { + *code = F_processor; + return F_none; + } + + if (fl_string_compare(string, FL_status_string_processor_not, length, FL_status_string_processor_not_length) == F_equal_to) { + *code = F_processor_not; + return F_none; + } + if (fl_string_compare(string, FL_status_string_prohibited, length, FL_status_string_prohibited_length) == F_equal_to) { *code = F_prohibited; return F_none; diff --git a/level_3/byte_dump/c/private-byte_dump.c b/level_3/byte_dump/c/private-byte_dump.c index eb86b57..9da1f47 100644 --- a/level_3/byte_dump/c/private-byte_dump.c +++ b/level_3/byte_dump/c/private-byte_dump.c @@ -181,19 +181,19 @@ extern "C" { if (cell.column < data.width) { if (data.mode == byte_dump_mode_hexidecimal && cell.column % 8 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.mode == byte_dump_mode_duodecimal && cell.column % 6 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.mode == byte_dump_mode_octal && cell.column % 6 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.mode == byte_dump_mode_binary && cell.column % 4 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.mode == byte_dump_mode_decimal && cell.column % 6 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } } } // while @@ -284,19 +284,19 @@ extern "C" { if (cell->column < data.width) { if (data.mode == byte_dump_mode_hexidecimal && cell->column % 8 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.mode == byte_dump_mode_duodecimal && cell->column % 6 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.mode == byte_dump_mode_octal && cell->column % 6 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.mode == byte_dump_mode_binary && cell->column % 4 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.mode == byte_dump_mode_decimal && cell->column % 6 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } } } @@ -415,19 +415,19 @@ extern "C" { } } else if (data.mode == byte_dump_mode_hexidecimal && cell->column % 8 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.mode == byte_dump_mode_duodecimal && cell->column % 6 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.mode == byte_dump_mode_octal && cell->column % 6 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.mode == byte_dump_mode_binary && cell->column % 4 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.mode == byte_dump_mode_decimal && cell->column % 6 == 0) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } return reset; @@ -452,7 +452,7 @@ extern "C" { } // while } else { - const char *placeholder = " "; + const char *placeholder = f_string_space_s; if (data.parameters[byte_dump_parameter_placeholder].result == f_console_result_found) { placeholder = byte_dump_character_placeholder; @@ -491,7 +491,7 @@ extern "C" { } else { for (; j < previous->bytes && j < data.width; j++) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } // for } } @@ -619,7 +619,7 @@ extern "C" { } } else if (data.presentation == byte_dump_presentation_simple) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (data.presentation == byte_dump_presentation_classic) { fprintf(data.output.stream, "."); @@ -641,7 +641,7 @@ extern "C" { fl_color_print(data.output.stream, data.context.set.warning, "%s", byte_dump_character_placeholder); } else { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } } else if (f_utf_character_is_control(characters.string[i]) == F_true) { @@ -650,37 +650,37 @@ extern "C" { fl_color_print(data.output.stream, data.context.set.warning, "."); } else { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } } else if (width_utf == 2 && characters.string[i] == 0xd89d0000) { // U+061C - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 3 && characters.string[i] >= 0xefbfb000 && characters.string[i] <= 0xefbfbc00) { // Use space to represent Specials codes. // 0xefbfbd00 is excluded because it is printable (and is the "Replacement Character" code). - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 3 && characters.string[i] >= 0xe290a700 && characters.string[i] <= 0xe290bf00) { // Use space to represent Control Pictues codes that are not currently defined but are reserved. - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 3 && characters.string[i] >= 0xee808000 && characters.string[i] <= 0xefa3bf00) { // Use space to represent Private Use Area codes. - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 4 && characters.string[i] >= 0xf09c80a0 && characters.string[i] <= 0xf09c80bd) { // Use space to represent Vaiation Selectors Supplement codes. - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 4 && characters.string[i] >= 0xf3b08080 && characters.string[i] <= 0xf3bfbfbf) { // Use space to represent Supplemental Private Use Area-A codes. - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 4 && characters.string[i] >= 0xf4808080 && characters.string[i] <= 0xf48fbfbf) { // Use space to represent Supplemental Private Use Area-B codes. - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 1) { // print invalid placeholder for invalid UTF-8 widths. @@ -713,34 +713,34 @@ extern "C" { // print a space for combining characters to combine into, thereby allowing it to be safely and readably displayed. if (width_utf == 2 && characters.string[i] >= 0xdea60000 && characters.string[i] <= 0xdeb00000) { // Thana combining codes: U+07A6 to U+07B0. - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 2 && characters.string[i] >= 0xcc800000 && characters.string[i] <= 0xcdaf0000) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 3 && characters.string[i] >= 0xe1aab000 && characters.string[i] <= 0xe1abbf00) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 3 && characters.string[i] >= 0xe1b78000 && characters.string[i] <= 0xe1b7bf00) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 3 && characters.string[i] >= 0xe2839000 && characters.string[i] <= 0xe283bf00) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 2 && characters.string[i] >= 0xd8900000 && characters.string[i] <= 0xd89a0000) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 2 && characters.string[i] >= 0xd98b0000 && characters.string[i] <= 0xd99f0000) { // Arabic, U+064B to U+065F. - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 2 && characters.string[i] >= 0xdb960000 && characters.string[i] <= 0xdb9c0000) { // Arabic, U+06D6 to U+06DC. - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } else if (width_utf == 2 && characters.string[i] >= 0xd6910000 && characters.string[i] <= 0xd6bd0000) { // Hebrew, U+0591 to U+05BD. - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } } else { @@ -761,7 +761,7 @@ extern "C" { } } else { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } j++; @@ -779,7 +779,7 @@ extern "C" { } } else { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } j++; @@ -797,7 +797,7 @@ extern "C" { } } else { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } j++; @@ -823,7 +823,7 @@ extern "C" { } else { for (; j < data.width; j++) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); } // for } diff --git a/level_3/controller/c/controller.c b/level_3/controller/c/controller.c index 30d38e7..d76c482 100644 --- a/level_3/controller/c/controller.c +++ b/level_3/controller/c/controller.c @@ -154,7 +154,7 @@ extern "C" { entry_name.size = entry_name.used; } else { - entry_name.string = controller_string_default; + entry_name.string = controller_string_default_s; entry_name.used = controller_string_default_length; entry_name.size = entry_name.used; } diff --git a/level_3/controller/c/private-common.h b/level_3/controller/c/private-common.h index 8ded89f..e215e52 100644 --- a/level_3/controller/c/private-common.h +++ b/level_3/controller/c/private-common.h @@ -15,6 +15,8 @@ extern "C" { #ifndef _di_controller_string_ #define controller_string_action "action" #define controller_string_actions "actions" + #define controller_string_affinity "affinity" + #define controller_string_as "as" #define controller_string_asynchronous "asynchronous" #define controller_string_bash "bash" #define controller_string_batch "batch" @@ -24,6 +26,9 @@ extern "C" { #define controller_string_consider "consider" #define controller_string_control "control" #define controller_string_control_group "control_group" + #define controller_string_cpu "cpu" + #define controller_string_core "core" + #define controller_string_data "data" #define controller_string_deadline "deadline" #define controller_string_default "default" #define controller_string_define "define" @@ -35,25 +40,33 @@ extern "C" { #define controller_string_failsafe "failsafe" #define controller_string_fifo "fifo" #define controller_string_freeze "freeze" + #define controller_string_fsize "fsize" #define controller_string_group "group" #define controller_string_groups "groups" #define controller_string_how "how" #define controller_string_idle "idle" #define controller_string_item "item" #define controller_string_kill "kill" + #define controller_string_limit "limit" + #define controller_string_locks "locks" #define controller_string_main "main" + #define controller_string_memlock "memlock" #define controller_string_method "method" + #define controller_string_msgqueue "msgqueue" #define controller_string_name "name" #define controller_string_need "need" #define controller_string_new "new" #define controller_string_nice "nice" #define controller_string_no "no" + #define controller_string_nofile "nofile" + #define controller_string_nproc "nproc" #define controller_string_optional "optional" #define controller_string_other "other" #define controller_string_parameter "parameter" #define controller_string_path "path" #define controller_string_pause "pause" #define controller_string_pid "pid" + #define controller_string_processor "processor" #define controller_string_program "program" #define controller_string_ready "ready" #define controller_string_reload "reload" @@ -62,12 +75,17 @@ extern "C" { #define controller_string_restart "restart" #define controller_string_resume "resume" #define controller_string_round_robin "round_robin" + #define controller_string_rss "rss" + #define controller_string_rtprio "rtprio" + #define controller_string_rttime "rttime" #define controller_string_rule "rule" #define controller_string_rules "rules" #define controller_string_scheduler "scheduler" #define controller_string_script "script" #define controller_string_service "service" #define controller_string_setting "setting" + #define controller_string_sigpending "sigpending" + #define controller_string_stack "stack" #define controller_string_start "start" #define controller_string_stop "stop" #define controller_string_succeed "succeed" @@ -84,6 +102,8 @@ extern "C" { #define controller_string_action_length 6 #define controller_string_actions_length 7 + #define controller_string_affinity_length 8 + #define controller_string_as_length 2 #define controller_string_asynchronous_length 12 #define controller_string_bash_length 4 #define controller_string_batch_length 5 @@ -93,6 +113,9 @@ extern "C" { #define controller_string_consider_length 8 #define controller_string_control_length 7 #define controller_string_control_group_length 13 + #define controller_string_core_length 4 + #define controller_string_cpu_length 3 + #define controller_string_data_length 4 #define controller_string_deadline_length 8 #define controller_string_define_length 6 #define controller_string_default_length 7 @@ -104,24 +127,32 @@ extern "C" { #define controller_string_failsafe_length 8 #define controller_string_fifo_length 4 #define controller_string_freeze_length 6 + #define controller_string_fsize_length 5 #define controller_string_group_length 5 #define controller_string_how_length 3 #define controller_string_idle_length 4 #define controller_string_item_length 4 #define controller_string_kill_length 4 + #define controller_string_limit_length 5 + #define controller_string_locks_length 5 #define controller_string_main_length 4 + #define controller_string_memlock_length 7 #define controller_string_method_length 6 + #define controller_string_msgqueue_length 8 #define controller_string_name_length 4 #define controller_string_need_length 4 #define controller_string_new_length 3 #define controller_string_nice_length 4 #define controller_string_no_length 2 + #define controller_string_nofile_length 6 + #define controller_string_nproc_length 5 #define controller_string_optional_length 8 #define controller_string_other_length 5 #define controller_string_parameter_length 9 #define controller_string_path_length 4 #define controller_string_pause_length 5 #define controller_string_pid_length 3 + #define controller_string_processor_length 9 #define controller_string_program_length 7 #define controller_string_ready_length 5 #define controller_string_reload_length 6 @@ -130,12 +161,17 @@ extern "C" { #define controller_string_restart_length 7 #define controller_string_resume_length 6 #define controller_string_round_robin_length 11 + #define controller_string_rss_length 3 + #define controller_string_rtprio_length 6 + #define controller_string_rttime_length 6 #define controller_string_rule_length 4 #define controller_string_rules_length 5 #define controller_string_scheduler_length 9 #define controller_string_script_length 6 #define controller_string_service_length 7 #define controller_string_setting_length 7 + #define controller_string_sigpending_length 10 + #define controller_string_stack_length 5 #define controller_string_start_length 5 #define controller_string_stop_length 4 #define controller_string_succeed_length 7 @@ -149,8 +185,116 @@ extern "C" { #define controller_string_want_length 4 #define controller_string_wish_length 4 #define controller_string_yes_length 3 + + const static f_string_t controller_string_action_s = controller_string_action; + const static f_string_t controller_string_actions_s = controller_string_actions; + const static f_string_t controller_string_affinity_s = controller_string_affinity; + const static f_string_t controller_string_as_s = controller_string_as; + const static f_string_t controller_string_asynchronous_s = controller_string_asynchronous; + const static f_string_t controller_string_bash_s = controller_string_bash; + const static f_string_t controller_string_batch_s = controller_string_batch; + const static f_string_t controller_string_capability_s = controller_string_capability; + const static f_string_t controller_string_create_s = controller_string_create; + const static f_string_t controller_string_command_s = controller_string_command; + const static f_string_t controller_string_consider_s = controller_string_consider; + const static f_string_t controller_string_control_s = controller_string_control; + const static f_string_t controller_string_control_group_s = controller_string_control_group; + const static f_string_t controller_string_cpu_s = controller_string_cpu; + const static f_string_t controller_string_core_s = controller_string_core; + const static f_string_t controller_string_data_s = controller_string_data; + const static f_string_t controller_string_deadline_s = controller_string_deadline; + const static f_string_t controller_string_default_s = controller_string_default; + const static f_string_t controller_string_define_s = controller_string_define; + const static f_string_t controller_string_entry_s = controller_string_entry; + const static f_string_t controller_string_entries_s = controller_string_entries; + const static f_string_t controller_string_environment_s = controller_string_environment; + const static f_string_t controller_string_existing_s = controller_string_existing; + const static f_string_t controller_string_fail_s = controller_string_fail; + const static f_string_t controller_string_failsafe_s = controller_string_failsafe; + const static f_string_t controller_string_fifo_s = controller_string_fifo; + const static f_string_t controller_string_freeze_s = controller_string_freeze; + const static f_string_t controller_string_fsize_s = controller_string_fsize; + const static f_string_t controller_string_group_s = controller_string_group; + const static f_string_t controller_string_groups_s = controller_string_groups; + const static f_string_t controller_string_how_s = controller_string_how; + const static f_string_t controller_string_idle_s = controller_string_idle; + const static f_string_t controller_string_item_s = controller_string_item; + const static f_string_t controller_string_kill_s = controller_string_kill; + const static f_string_t controller_string_limit_s = controller_string_limit; + const static f_string_t controller_string_locks_s = controller_string_locks; + const static f_string_t controller_string_main_s = controller_string_main; + const static f_string_t controller_string_memlock_s = controller_string_memlock; + const static f_string_t controller_string_method_s = controller_string_method; + const static f_string_t controller_string_msgqueue_s = controller_string_msgqueue; + const static f_string_t controller_string_name_s = controller_string_name; + const static f_string_t controller_string_need_s = controller_string_need; + const static f_string_t controller_string_new_s = controller_string_new; + const static f_string_t controller_string_nice_s = controller_string_nice; + const static f_string_t controller_string_no_s = controller_string_no; + const static f_string_t controller_string_nofile_s = controller_string_nofile; + const static f_string_t controller_string_nproc_s = controller_string_nproc; + const static f_string_t controller_string_optional_s = controller_string_optional; + const static f_string_t controller_string_other_s = controller_string_other; + const static f_string_t controller_string_parameter_s = controller_string_parameter; + const static f_string_t controller_string_path_s = controller_string_path; + const static f_string_t controller_string_pause_s = controller_string_pause; + const static f_string_t controller_string_pid_s = controller_string_pid; + const static f_string_t controller_string_processor_s = controller_string_processor; + const static f_string_t controller_string_program_s = controller_string_program; + const static f_string_t controller_string_ready_s = controller_string_ready; + const static f_string_t controller_string_reload_s = controller_string_reload; + const static f_string_t controller_string_require_s = controller_string_require; + const static f_string_t controller_string_required_s = controller_string_required; + const static f_string_t controller_string_restart_s = controller_string_restart; + const static f_string_t controller_string_resume_s = controller_string_resume; + const static f_string_t controller_string_round_robin_s = controller_string_round_robin; + const static f_string_t controller_string_rss_s = controller_string_rss; + const static f_string_t controller_string_rtprio_s = controller_string_rtprio; + const static f_string_t controller_string_rttime_s = controller_string_rttime; + const static f_string_t controller_string_rule_s = controller_string_rule; + const static f_string_t controller_string_rules_s = controller_string_rules; + const static f_string_t controller_string_scheduler_s = controller_string_scheduler; + const static f_string_t controller_string_script_s = controller_string_script; + const static f_string_t controller_string_service_s = controller_string_service; + const static f_string_t controller_string_setting_s = controller_string_setting; + const static f_string_t controller_string_sigpending_s = controller_string_sigpending; + const static f_string_t controller_string_stack_s = controller_string_stack; + const static f_string_t controller_string_start_s = controller_string_start; + const static f_string_t controller_string_stop_s = controller_string_stop; + const static f_string_t controller_string_succeed_s = controller_string_succeed; + const static f_string_t controller_string_synchronous_s = controller_string_synchronous; + const static f_string_t controller_string_thaw_s = controller_string_thaw; + const static f_string_t controller_string_timeout_s = controller_string_timeout; + const static f_string_t controller_string_type_s = controller_string_type; + const static f_string_t controller_string_use_s = controller_string_use; + const static f_string_t controller_string_user_s = controller_string_user; + const static f_string_t controller_string_wait_s = controller_string_wait; + const static f_string_t controller_string_want_s = controller_string_want; + const static f_string_t controller_string_wish_s = controller_string_wish; + const static f_string_t controller_string_yes_s = controller_string_yes; #endif // _di_controller_string_ +#ifndef _di_controller_resource_limit_t_ + enum { + controller_resource_limit_type_as = RLIMIT_AS, + controller_resource_limit_type_core = RLIMIT_CORE, + controller_resource_limit_type_cpu = RLIMIT_CPU, + controller_resource_limit_type_data = RLIMIT_DATA, + controller_resource_limit_type_fsize = RLIMIT_FSIZE, + controller_resource_limit_type_locks = RLIMIT_LOCKS, + controller_resource_limit_type_memlock = RLIMIT_MEMLOCK, + controller_resource_limit_type_msgqueue = RLIMIT_MSGQUEUE, + controller_resource_limit_type_nice = RLIMIT_NICE, + controller_resource_limit_type_nofile = RLIMIT_NOFILE, + controller_resource_limit_type_nproc = RLIMIT_NPROC, + controller_resource_limit_type_rss = RLIMIT_RSS, + controller_resource_limit_type_rtprio = RLIMIT_RTPRIO, + controller_resource_limit_type_rttime = RLIMIT_RTTIME, + controller_resource_limit_type_sigpending = RLIMIT_SIGPENDING, + controller_resource_limit_type_stack = RLIMIT_STACK, + }; +#endif // _di_controller_resource_limit_t_ + #ifndef _di_controller_rule_action_t_ #define controller_rule_action_method_string_extended "FSS-0001 (Extended)" #define controller_rule_action_method_string_extended_list "FSS-0003 (Extended List)" @@ -279,11 +423,13 @@ extern "C" { #ifndef _di_controller_rule_t_ enum { - controller_rule_setting_type_capability = 1, + controller_rule_setting_type_affinity = 1, + controller_rule_setting_type_capability, controller_rule_setting_type_control_group, controller_rule_setting_type_define, controller_rule_setting_type_environment, controller_rule_setting_type_group, + controller_rule_setting_type_limit, controller_rule_setting_type_name, controller_rule_setting_type_need, controller_rule_setting_type_nice, @@ -337,9 +483,11 @@ extern "C" { f_string_dynamics_t want; f_string_dynamics_t wish; + f_int32s_t affinity; f_capability_t capability; f_control_group_t control_group; f_int32s_t groups; + f_limit_sets_t limits; f_execute_scheduler_t scheduler; controller_rule_items_t items; @@ -367,9 +515,11 @@ extern "C" { f_string_dynamics_t_initialize, \ f_string_dynamics_t_initialize, \ f_string_dynamics_t_initialize, \ + f_int32s_t_initialize, \ f_capability_t_initialize, \ f_control_group_t_initialize, \ f_int32s_t_initialize, \ + f_limit_sets_t_initialize, \ f_execute_scheduler_t_initialize, \ controller_rule_items_initialize, \ } @@ -385,9 +535,11 @@ extern "C" { fl_string_dynamics_delete(&rule.need); \ fl_string_dynamics_delete(&rule.want); \ fl_string_dynamics_delete(&rule.wish); \ + fl_type_int32s_delete(&rule.affinity); \ f_capability_delete(&rule.capability); \ fl_control_group_delete(&rule.control_group); \ fl_type_int32s_delete(&rule.groups); \ + f_limit_sets_delete(&rule.limits); \ controller_macro_rule_items_t_delete_simple(rule.items) #endif // _di_controller_rule_t_ diff --git a/level_3/controller/c/private-controller.c b/level_3/controller/c/private-controller.c index 8111999..7aee64a 100644 --- a/level_3/controller/c/private-controller.c +++ b/level_3/controller/c/private-controller.c @@ -406,7 +406,7 @@ extern "C" { if (data.warning.verbosity == f_console_verbosity_debug) { fprintf(data.warning.to.stream, "%c", f_string_eol_s[0]); fprintf(data.warning.to.stream, "%s%sMultiple '", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : f_string_empty_s); - fprintf(data.warning.to.stream, "%s%s%s%s", data.warning.context.after->string, data.warning.notable.before->string, controller_string_ready, data.warning.notable.after->string); + fprintf(data.warning.to.stream, "%s%s%s%s", data.warning.context.after->string, data.warning.notable.before->string, controller_string_ready_s, data.warning.notable.after->string); fprintf(data.warning.to.stream, "%s' entry item actions detected; only the first will be used.%s%c", data.warning.context.before->string, data.warning.context.after->string, f_string_eol_s[0]); controller_entry_error_print(data.warning, *cache); @@ -419,7 +419,7 @@ extern "C" { else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_item) { error_has = F_false; - if (fl_string_dynamic_compare_string(controller_string_main, actions->array[cache->ats.array[at_j]].parameters.array[0], controller_string_main_length) == F_equal_to) { + if (fl_string_dynamic_compare_string(controller_string_main_s, actions->array[cache->ats.array[at_j]].parameters.array[0], controller_string_main_length) == F_equal_to) { continue; } @@ -610,7 +610,7 @@ extern "C" { if (simulate) { fprintf(data->output.stream, "%c", f_string_eol_s[0]); fprintf(data->output.stream, "Processing entry item rule '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_main, data->context.set.title.after->string); + fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_main_s, data->context.set.title.after->string); fprintf(data->output.stream, "'.%c", f_string_eol_s[0]); } @@ -642,7 +642,7 @@ extern "C" { fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, cache->name_action.string, data->context.set.title.after->string); if (actions->array[cache->ats.array[at_j]].parameters.used) { - fprintf(data->output.stream, " "); + fprintf(data->output.stream, f_string_space_s); fprintf(data->output.stream, "%s", data->context.set.notable.before->string); controller_entry_action_parameters_print(data->output.stream, actions->array[cache->ats.array[at_j]]); fprintf(data->output.stream, "%s", data->context.set.notable.after->string); @@ -658,7 +658,7 @@ extern "C" { fprintf(data->error.to.stream, "%s%s%s", data->error.context.after->string, data->error.notable.before->string, cache->name_action.string); if (actions->array[cache->ats.array[at_j]].parameters.used) { - fprintf(data->error.to.stream, " "); + fprintf(data->error.to.stream, f_string_space_s); controller_entry_action_parameters_print(data->error.to.stream, actions->array[cache->ats.array[at_j]]); } @@ -679,7 +679,7 @@ extern "C" { fprintf(data->warning.to.stream, "%s%s%s", data->warning.context.after->string, data->warning.notable.before->string, cache->name_action.string); if (actions->array[cache->ats.array[at_j]].parameters.used) { - fprintf(data->warning.to.stream, " "); + fprintf(data->warning.to.stream, f_string_space_s); controller_entry_action_parameters_print(data->warning.to.stream, actions->array[cache->ats.array[at_j]]); } @@ -699,7 +699,7 @@ extern "C" { fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, cache->name_action.string, data->context.set.title.after->string); if (actions->array[cache->ats.array[at_j]].parameters.used) { - fprintf(data->output.stream, " "); + fprintf(data->output.stream, f_string_space_s); fprintf(data->output.stream, "%s", data->context.set.notable.before->string); controller_entry_action_parameters_print(data->output.stream, actions->array[cache->ats.array[at_j]]); fprintf(data->output.stream, "%s", data->context.set.notable.after->string); @@ -713,7 +713,7 @@ extern "C" { fprintf(data->warning.to.stream, "%s%s", data->warning.notable.before->string, cache->name_action.string); if (actions->array[cache->ats.array[at_j]].parameters.used) { - fprintf(data->warning.to.stream, " "); + fprintf(data->warning.to.stream, f_string_space_s); controller_entry_action_parameters_print(data->warning.to.stream, actions->array[cache->ats.array[at_j]]); } @@ -735,7 +735,7 @@ extern "C" { if (simulate) { fprintf(data->output.stream, "%c", f_string_eol_s[0]); fprintf(data->output.stream, "Processing entry item action '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_ready, data->context.set.title.after->string); + fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_ready_s, data->context.set.title.after->string); fprintf(data->output.stream, "'.%c", f_string_eol_s[0]); } else { @@ -748,7 +748,7 @@ extern "C" { else if (simulate) { fprintf(data->output.stream, "%c", f_string_eol_s[0]); fprintf(data->output.stream, "Ignoring entry item action '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_ready, data->context.set.title.after->string); + fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_ready_s, data->context.set.title.after->string); fprintf(data->output.stream, "', state already is ready.%c", f_string_eol_s[0]); } } @@ -963,18 +963,18 @@ extern "C" { f_string_t code = ""; if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_kill) { - code = controller_string_kill; + code = controller_string_kill_s; } else if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_start) { - code = controller_string_start; + code = controller_string_start_s; } else if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_stop) { - code = controller_string_stop; + code = controller_string_stop_s; } fprintf(data->output.stream, "%c", f_string_eol_s[0]); fprintf(data->output.stream, "Processing entry item action '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_timeout, data->context.set.title.after->string); + fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_timeout_s, data->context.set.title.after->string); fprintf(data->output.stream, "' setting '"); fprintf(data->output.stream, "%s%s%s", data->context.set.important.before->string, code, data->context.set.important.after->string); fprintf(data->output.stream, "' to '"); @@ -1015,7 +1015,7 @@ extern "C" { if (simulate) { fprintf(data->output.stream, "%c", f_string_eol_s[0]); fprintf(data->output.stream, "Processing entry item action '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_failsafe, data->context.set.title.after->string); + fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_failsafe_s, data->context.set.title.after->string); fprintf(data->output.stream, "' setting value to '"); fprintf(data->output.stream, "%s%s%s", data->context.set.important.before->string, setting->entry.items.array[setting->failsafe_rule_id].name.string, data->context.set.important.after->string); fprintf(data->output.stream, "'.%c", f_string_eol_s[0]); diff --git a/level_3/controller/c/private-entry.c b/level_3/controller/c/private-entry.c index 25af69d..9709376 100644 --- a/level_3/controller/c/private-entry.c +++ b/level_3/controller/c/private-entry.c @@ -20,7 +20,7 @@ extern "C" { if (index == action.parameters.used) break; - fprintf(stream, " "); + fprintf(stream, f_string_space_s); } // for } #endif // _di_controller_entry_action_parameters_print_ @@ -32,32 +32,32 @@ extern "C" { switch (type) { case controller_entry_action_type_consider: - buffer.string = controller_string_consider; + buffer.string = controller_string_consider_s; buffer.used = controller_string_consider_length; break; case controller_entry_action_type_failsafe: - buffer.string = controller_string_failsafe; + buffer.string = controller_string_failsafe_s; buffer.used = controller_string_failsafe_length; break; case controller_entry_action_type_item: - buffer.string = controller_string_item; + buffer.string = controller_string_item_s; buffer.used = controller_string_item_length; break; case controller_entry_action_type_ready: - buffer.string = controller_string_ready; + buffer.string = controller_string_ready_s; buffer.used = controller_string_ready_length; break; case controller_entry_action_type_rule: - buffer.string = controller_string_rule; + buffer.string = controller_string_rule_s; buffer.used = controller_string_rule_length; break; case controller_entry_action_type_timeout: - buffer.string = controller_string_timeout; + buffer.string = controller_string_timeout_s; buffer.used = controller_string_timeout_length; break; } @@ -179,22 +179,22 @@ extern "C" { break; } - if (fl_string_dynamic_compare_string(controller_string_consider, cache->name_action, controller_string_consider_length) == F_equal_to) { + if (fl_string_dynamic_compare_string(controller_string_consider_s, cache->name_action, controller_string_consider_length) == F_equal_to) { actions->array[actions->used].type = controller_entry_action_type_consider; } - else if (fl_string_dynamic_compare_string(controller_string_failsafe, cache->name_action, controller_string_failsafe_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_failsafe_s, cache->name_action, controller_string_failsafe_length) == F_equal_to) { actions->array[actions->used].type = controller_entry_action_type_failsafe; } - else if (fl_string_dynamic_compare_string(controller_string_item, cache->name_action, controller_string_item_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_item_s, cache->name_action, controller_string_item_length) == F_equal_to) { actions->array[actions->used].type = controller_entry_action_type_item; } - else if (fl_string_dynamic_compare_string(controller_string_ready, cache->name_action, controller_string_ready_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_ready_s, cache->name_action, controller_string_ready_length) == F_equal_to) { actions->array[actions->used].type = controller_entry_action_type_ready; } - else if (fl_string_dynamic_compare_string(controller_string_rule, cache->name_action, controller_string_rule_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_rule_s, cache->name_action, controller_string_rule_length) == F_equal_to) { actions->array[actions->used].type = controller_entry_action_type_rule; } - else if (fl_string_dynamic_compare_string(controller_string_timeout, cache->name_action, controller_string_timeout_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_timeout_s, cache->name_action, controller_string_timeout_length) == F_equal_to) { actions->array[actions->used].type = controller_entry_action_type_timeout; } else { @@ -413,13 +413,13 @@ extern "C" { for (j = 2; j < action->parameters.used; ++j) { - if (fl_string_dynamic_compare_string(controller_string_asynchronous, action->parameters.array[j], controller_string_asynchronous_length) == F_equal_to) { + if (fl_string_dynamic_compare_string(controller_string_asynchronous_s, action->parameters.array[j], controller_string_asynchronous_length) == F_equal_to) { action->code |= controller_entry_rule_code_asynchronous; } - else if (fl_string_dynamic_compare_string(controller_string_require, action->parameters.array[j], controller_string_require_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_require_s, action->parameters.array[j], controller_string_require_length) == F_equal_to) { action->code |= controller_entry_rule_code_require; } - else if (fl_string_dynamic_compare_string(controller_string_wait, action->parameters.array[j], controller_string_wait_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_wait_s, action->parameters.array[j], controller_string_wait_length) == F_equal_to) { action->code |= controller_entry_rule_code_wait; } else { @@ -434,11 +434,11 @@ extern "C" { if (data.error.verbosity != f_console_verbosity_quiet) { fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); fprintf(data.error.to.stream, "%s%sThe entry item action third parameter (and beyond) must be one of '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_asynchronous, data.error.notable.after->string); + fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_asynchronous_s, data.error.notable.after->string); fprintf(data.error.to.stream, "%s', '", data.error.context.before->string); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_require, data.error.notable.after->string); + fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_require_s, data.error.notable.after->string); fprintf(data.error.to.stream, "%s', or '", data.error.context.before->string); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_wait, data.error.notable.after->string); + fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_wait_s, data.error.notable.after->string); fprintf(data.error.to.stream, "%s' but instead has '", data.error.context.before->string); fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, action->parameters.array[j].string, data.error.notable.after->string); fprintf(data.error.to.stream, "%s'.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); @@ -447,7 +447,7 @@ extern "C" { } // for } else if (action->type == controller_entry_action_type_failsafe || action->type == controller_entry_action_type_item) { - if (fl_string_dynamic_compare_string(controller_string_main, action->parameters.array[0], controller_string_main_length) == F_equal_to) { + if (fl_string_dynamic_compare_string(controller_string_main_s, action->parameters.array[0], controller_string_main_length) == F_equal_to) { action->status = F_status_set_error(F_supported_not); if (F_status_is_error_not(status_action)) { @@ -457,20 +457,20 @@ extern "C" { if (data.error.verbosity != f_console_verbosity_quiet) { fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); fprintf(data.error.to.stream, "%s%sThe entry item action may not specify the reserved item '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_main, data.error.notable.after->string); + fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_main_s, data.error.notable.after->string); fprintf(data.error.to.stream, "%s'.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); } } } else if (action->type == controller_entry_action_type_timeout) { - if (fl_string_dynamic_compare_string(controller_string_kill, action->parameters.array[0], controller_string_kill_length) == F_equal_to) { + if (fl_string_dynamic_compare_string(controller_string_kill_s, action->parameters.array[0], controller_string_kill_length) == F_equal_to) { action->code = controller_entry_timeout_code_kill; } - else if (fl_string_dynamic_compare_string(controller_string_start, action->parameters.array[0], controller_string_start_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_start_s, action->parameters.array[0], controller_string_start_length) == F_equal_to) { action->code = controller_entry_timeout_code_start; } - else if (fl_string_dynamic_compare_string(controller_string_stop, action->parameters.array[0], controller_string_stop_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_stop_s, action->parameters.array[0], controller_string_stop_length) == F_equal_to) { action->code = controller_entry_timeout_code_stop; } else { @@ -483,11 +483,11 @@ extern "C" { if (data.error.verbosity != f_console_verbosity_quiet) { fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); fprintf(data.error.to.stream, "%s%sThe entry item action must have one of '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_kill, data.error.notable.after->string); + fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_kill_s, data.error.notable.after->string); fprintf(data.error.to.stream, "%s', '", data.error.context.before->string); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_start, data.error.notable.after->string); + fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_start_s, data.error.notable.after->string); fprintf(data.error.to.stream, "%s', or '", data.error.context.before->string); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_stop, data.error.notable.after->string); + fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_stop_s, data.error.notable.after->string); fprintf(data.error.to.stream, "%s' but instead has '", data.error.context.before->string); fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, action->parameters.array[0].string, data.error.notable.after->string); fprintf(data.error.to.stream, "%s'.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); @@ -634,7 +634,7 @@ extern "C" { cache->name_action.used = 0; cache->name_item.used = 0; - status = controller_file_load(data, setting, controller_string_entries, entry_name, controller_string_entry, controller_string_entries_length, controller_string_entry_length, cache); + status = controller_file_load(data, setting, controller_string_entries_s, entry_name, controller_string_entry_s, controller_string_entries_length, controller_string_entry_length, cache); if (F_status_is_error_not(status)) { if (cache->buffer_file.used) { @@ -749,7 +749,7 @@ extern "C" { range = &cache->content_items.array[i].array[0]; - if (fl_string_dynamic_compare_string(controller_string_main, cache->name_item, controller_string_main_length) == F_equal_to) { + if (fl_string_dynamic_compare_string(controller_string_main_s, cache->name_item, controller_string_main_length) == F_equal_to) { code |= 0x1; at = 0; @@ -798,7 +798,7 @@ extern "C" { if (data.error.verbosity != f_console_verbosity_quiet) { fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); fprintf(data.error.to.stream, "%s%sThe required entry item '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_main, data.error.notable.after->string); + fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_main_s, data.error.notable.after->string); fprintf(data.error.to.stream, "%s' was not found.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); } diff --git a/level_3/controller/c/private-rule.c b/level_3/controller/c/private-rule.c index 2d295ac..67b7935 100644 --- a/level_3/controller/c/private-rule.c +++ b/level_3/controller/c/private-rule.c @@ -106,47 +106,47 @@ extern "C" { switch (type) { case controller_rule_action_type_create: - buffer.string = controller_string_create; + buffer.string = controller_string_create_s; buffer.used = controller_string_create_length; break; case controller_rule_action_type_group: - buffer.string = controller_string_group; + buffer.string = controller_string_group_s; buffer.used = controller_string_group_length; break; case controller_rule_action_type_kill: - buffer.string = controller_string_kill; + buffer.string = controller_string_kill_s; buffer.used = controller_string_kill_length; break; case controller_rule_action_type_restart: - buffer.string = controller_string_restart; + buffer.string = controller_string_restart_s; buffer.used = controller_string_restart_length; break; case controller_rule_action_type_reload: - buffer.string = controller_string_reload; + buffer.string = controller_string_reload_s; buffer.used = controller_string_reload_length; break; case controller_rule_action_type_start: - buffer.string = controller_string_start; + buffer.string = controller_string_start_s; buffer.used = controller_string_start_length; break; case controller_rule_action_type_stop: - buffer.string = controller_string_stop; + buffer.string = controller_string_stop_s; buffer.used = controller_string_stop_length; break; case controller_rule_action_type_use: - buffer.string = controller_string_use; + buffer.string = controller_string_use_s; buffer.used = controller_string_use_length; break; case controller_rule_action_type_user: - buffer.string = controller_string_user; + buffer.string = controller_string_user_s; buffer.used = controller_string_user_length; break; } @@ -218,6 +218,8 @@ extern "C" { else { actions->array[actions->used].type = type; actions->array[actions->used].line = cache->line_action; + actions->array[actions->used].parameters.used = 0; + actions->array[actions->used].status = F_known_not; status = fl_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_action.array[0], &actions->array[actions->used].parameters.array[0]); @@ -315,6 +317,41 @@ extern "C" { if (F_status_is_error(status)) { fll_error_print(data.error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true); } + else if (item->type == controller_rule_item_type_script) { + status = fl_string_dynamics_increase(&actions->array[actions->used].parameters); + + if (F_status_is_error(status)) { + fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamics_increase", F_true); + } + else { + + // "script" types use the entire content as a single string piped to the script, so merge all arguments together. + actions->array[actions->used].type = type; + actions->array[actions->used].line = cache->line_action; + actions->array[actions->used].parameters.used = 0; + actions->array[actions->used].status = F_known_not; + + for (f_array_length_t i = 0; i < cache->content_action.used; ++i) { + + status = fl_string_dynamic_partial_mash_nulless(f_string_space_s, f_string_space_length, cache->buffer_item, cache->content_action.array[i], &actions->array[actions->used].parameters.array[0]); + if (F_status_is_error(status)) break; + } // for + + if (F_status_is_error_not(status)) { + status = fl_string_dynamic_terminate_after(&actions->array[actions->used].parameters.array[0]); + + if (F_status_is_error(status)) { + fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_terminate_after", F_true); + } + else { + actions->array[actions->used].parameters.used = 1; + actions->used++; + } + } + } + + return status; + } else { status = f_fss_count_lines(cache->buffer_item, range->start, &actions->array[actions->used].line); @@ -400,12 +437,26 @@ extern "C" { if (output.verbosity != f_console_verbosity_quiet) { fprintf(output.to.stream, "%c", f_string_eol_s[0]); - fprintf(output.to.stream, "%s%sThe %s '", output.context.before->string, output.prefix ? output.prefix : f_string_empty_s, script_is ? controller_string_script : controller_string_program); + fprintf(output.to.stream, "%s%sThe %s '", output.context.before->string, output.prefix ? output.prefix : f_string_empty_s, script_is ? controller_string_script_s : controller_string_program_s); fprintf(output.to.stream, "%s%s%s%s", output.context.after->string, output.notable.before->string, name ? name : f_string_empty_s, output.notable.after->string); - if (status == F_control_group || status == F_schedule) { + if (status == F_control_group || status == F_limit || status == F_processor || status == F_schedule) { fprintf(output.to.stream, "%s' failed due to a failure to setup the '", output.context.before->string); - fprintf(output.to.stream, "%s%s%s%s", output.context.after->string, output.notable.before->string, status == F_control_group ? controller_string_control_group : controller_string_scheduler, output.notable.after->string); + + fprintf(output.to.stream, "%s%s", output.context.after->string, output.notable.before->string); + if (status == F_control_group) { + fprintf(output.to.stream, "%s", controller_string_control_group_s); + } + else if (status == F_limit) { + fprintf(output.to.stream, "%s", controller_string_limit_s); + } + else if (status == F_processor) { + fprintf(output.to.stream, "%s", controller_string_processor_s); + } + else if (status == F_schedule) { + fprintf(output.to.stream, "%s", controller_string_scheduler_s); + } + fprintf(output.to.stream, "%s", output.notable.after->string); fprintf(output.to.stream, "%s'.%s%c", output.context.before->string, output.context.after->string, f_string_eol_s[0]); } else if (code) { @@ -425,7 +476,7 @@ extern "C" { if (output.verbosity != f_console_verbosity_quiet) { fprintf(output.to.stream, "%c", f_string_eol_s[0]); - fprintf(output.to.stream, "%s%sThe %s '", output.context.before->string, output.prefix ? output.prefix : f_string_empty_s, script_is ? controller_string_script : controller_string_program); + fprintf(output.to.stream, "%s%sThe %s '", output.context.before->string, output.prefix ? output.prefix : f_string_empty_s, script_is ? controller_string_script_s : controller_string_program_s); fprintf(output.to.stream, "%s%s%s%s", output.context.after->string, output.notable.before->string, name ? name : f_string_empty_s, output.notable.after->string); fprintf(output.to.stream, "%s' could not be executed because it was not found.%s%c", output.context.before->string, output.context.after->string, f_string_eol_s[0]); } @@ -468,30 +519,14 @@ extern "C" { fl_execute_parameter_t parameter = fl_macro_execute_parameter_t_initialize(0, &environment, &signals, 0); fl_execute_as_t as = fl_execute_as_t_initialize; - if (rule->has & controller_rule_has_nice) { - as.nice = &rule->nice; - } - - if (rule->has & controller_rule_has_user) { - as.id_user = &rule->user; - } - - if (rule->has & controller_rule_has_group) { - as.id_group = &rule->group; - - if (rule->groups.used) { - as.id_groups = &rule->groups; - } + if (rule->affinity.used) { + as.affinity = &rule->affinity; } if (rule->capability) { as.capability = rule->capability; } - if (rule->has & controller_rule_has_scheduler) { - as.scheduler = &rule->scheduler; - } - if (rule->has & controller_rule_has_control_group) { as.control_group = &rule->control_group; @@ -508,6 +543,30 @@ extern "C" { } } + if (rule->has & controller_rule_has_group) { + as.id_group = &rule->group; + + if (rule->groups.used) { + as.id_groups = &rule->groups; + } + } + + if (rule->limits.used) { + as.limits = &rule->limits; + } + + if (rule->has & controller_rule_has_scheduler) { + as.scheduler = &rule->scheduler; + } + + if (rule->has & controller_rule_has_nice) { + as.nice = &rule->nice; + } + + if (rule->has & controller_rule_has_user) { + as.id_user = &rule->user; + } + status = fll_environment_load_names(rule->environment, &environment); if (F_status_is_error(status)) { @@ -655,7 +714,7 @@ extern "C" { fprintf(data->output.stream, "' with the arguments: '%s", data->context.title.string); for (f_array_length_t i = program ? 0 : 1; i < arguments.used; ++i) { - fprintf(data->output.stream, "%s%s", (program && i || !program && i > 1) ? " " : "", arguments.array[i].string); + fprintf(data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string); } // for fprintf(data->output.stream, "%s'.%c", data->context.reset.string, f_string_eol_s[0]); @@ -698,7 +757,7 @@ extern "C" { if (F_status_is_error(status)) { status = F_status_set_fine(status); - if (status == F_control_group || status == F_failure || status == F_schedule) { + if (status == F_control_group || status == F_failure || status == F_limit || status == F_processor || status == F_schedule) { controller_rule_error_print_execute(data->error, type == controller_rule_item_type_script, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, result, status); } else if (status == F_file_found_not) { @@ -736,7 +795,7 @@ extern "C" { fprintf(data->output.stream, "' with the arguments: '%s", data->context.title.string); for (f_array_length_t i = program ? 0 : 1; i < arguments.used; ++i) { - fprintf(data->output.stream, "%s%s", (program && i || !program && i > 1) ? " " : "", arguments.array[i].string); + fprintf(data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string); } // for fprintf(data->output.stream, "%s'.%c", data->context.reset.string, f_string_eol_s[0]); @@ -779,7 +838,7 @@ extern "C" { if (F_status_is_error(status)) { status = F_status_set_fine(status); - if (status == F_control_group || status == F_failure || status == F_schedule) { + if (status == F_control_group || status == F_failure || status == F_limit || status == F_processor || status == F_schedule) { controller_rule_error_print_execute(data->error, type == controller_rule_item_type_script, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, result, status); } else if (status == F_file_found_not) { @@ -915,37 +974,37 @@ extern "C" { break; } - if (fl_string_dynamic_compare_string(controller_string_create, cache->name_action, controller_string_create_length) == F_equal_to) { + if (fl_string_dynamic_compare_string(controller_string_create_s, cache->name_action, controller_string_create_length) == F_equal_to) { type = controller_rule_action_type_create; } - else if (fl_string_dynamic_compare_string(controller_string_group, cache->name_action, controller_string_group_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_group_s, cache->name_action, controller_string_group_length) == F_equal_to) { type = controller_rule_action_type_group; } - else if (fl_string_dynamic_compare_string(controller_string_kill, cache->name_action, controller_string_kill_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_kill_s, cache->name_action, controller_string_kill_length) == F_equal_to) { type = controller_rule_action_type_kill; } - else if (fl_string_dynamic_compare_string(controller_string_pause, cache->name_action, controller_string_pause_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_pause_s, cache->name_action, controller_string_pause_length) == F_equal_to) { type = controller_rule_action_type_pause; } - else if (fl_string_dynamic_compare_string(controller_string_restart, cache->name_action, controller_string_restart_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_restart_s, cache->name_action, controller_string_restart_length) == F_equal_to) { type = controller_rule_action_type_restart; } - else if (fl_string_dynamic_compare_string(controller_string_resume, cache->name_action, controller_string_resume_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_resume_s, cache->name_action, controller_string_resume_length) == F_equal_to) { type = controller_rule_action_type_resume; } - else if (fl_string_dynamic_compare_string(controller_string_reload, cache->name_action, controller_string_reload_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_reload_s, cache->name_action, controller_string_reload_length) == F_equal_to) { type = controller_rule_action_type_reload; } - else if (fl_string_dynamic_compare_string(controller_string_start, cache->name_action, controller_string_start_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_start_s, cache->name_action, controller_string_start_length) == F_equal_to) { type = controller_rule_action_type_start; } - else if (fl_string_dynamic_compare_string(controller_string_stop, cache->name_action, controller_string_stop_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_stop_s, cache->name_action, controller_string_stop_length) == F_equal_to) { type = controller_rule_action_type_stop; } - else if (fl_string_dynamic_compare_string(controller_string_use, cache->name_action, controller_string_use_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_use_s, cache->name_action, controller_string_use_length) == F_equal_to) { type = controller_rule_action_type_use; } - else if (fl_string_dynamic_compare_string(controller_string_user, cache->name_action, controller_string_user_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_user_s, cache->name_action, controller_string_user_length) == F_equal_to) { type = controller_rule_action_type_user; } else { @@ -1005,22 +1064,22 @@ extern "C" { switch (type) { case controller_rule_item_type_command: - buffer.string = controller_string_command; + buffer.string = controller_string_command_s; buffer.used = controller_string_command_length; break; case controller_rule_item_type_script: - buffer.string = controller_string_script; + buffer.string = controller_string_script_s; buffer.used = controller_string_script_length; break; case controller_rule_item_type_service: - buffer.string = controller_string_service; + buffer.string = controller_string_service_s; buffer.used = controller_string_service_length; break; case controller_rule_item_type_setting: - buffer.string = controller_string_setting; + buffer.string = controller_string_setting_s; buffer.used = controller_string_setting_length; break; } @@ -1052,6 +1111,99 @@ extern "C" { } #endif // _di_controller_rule_items_increase_by_ +#ifndef _di_controller_rule_setting_limit_type_name_ + f_string_static_t controller_rule_setting_limit_type_name(const uint8_t type) { + + f_string_static_t buffer = f_string_static_t_initialize; + + switch (type) { + case controller_resource_limit_type_as: + buffer.string = controller_string_as_s; + buffer.used = controller_string_as_length; + break; + + case controller_resource_limit_type_core: + buffer.string = controller_string_core_s; + buffer.used = controller_string_core_length; + break; + + case controller_resource_limit_type_cpu: + buffer.string = controller_string_cpu_s; + buffer.used = controller_string_cpu_length; + break; + + case controller_resource_limit_type_data: + buffer.string = controller_string_data_s; + buffer.used = controller_string_data_length; + break; + + case controller_resource_limit_type_fsize: + buffer.string = controller_string_fsize_s; + buffer.used = controller_string_fsize_length; + break; + + case controller_resource_limit_type_locks: + buffer.string = controller_string_locks_s; + buffer.used = controller_string_locks_length; + break; + + case controller_resource_limit_type_memlock: + buffer.string = controller_string_memlock_s; + buffer.used = controller_string_memlock_length; + break; + + case controller_resource_limit_type_msgqueue: + buffer.string = controller_string_msgqueue_s; + buffer.used = controller_string_msgqueue_length; + break; + + case controller_resource_limit_type_nice: + buffer.string = controller_string_nice_s; + buffer.used = controller_string_nice_length; + break; + + case controller_resource_limit_type_nofile: + buffer.string = controller_string_nofile_s; + buffer.used = controller_string_nofile_length; + break; + + case controller_resource_limit_type_nproc: + buffer.string = controller_string_nproc_s; + buffer.used = controller_string_nproc_length; + break; + + case controller_resource_limit_type_rss: + buffer.string = controller_string_rss_s; + buffer.used = controller_string_rss_length; + break; + + case controller_resource_limit_type_rtprio: + buffer.string = controller_string_rtprio_s; + buffer.used = controller_string_rtprio_length; + break; + + case controller_resource_limit_type_rttime: + buffer.string = controller_string_rttime_s; + buffer.used = controller_string_rttime_length; + break; + + case controller_resource_limit_type_sigpending: + buffer.string = controller_string_sigpending_s; + buffer.used = controller_string_sigpending_length; + break; + + case controller_resource_limit_type_stack: + buffer.string = controller_string_stack_s; + buffer.used = controller_string_stack_length; + break; + } + + buffer.size = buffer.used; + + return buffer; + } +#endif // _di_controller_rule_setting_limit_type_name_ + #ifndef _di_controller_rule_path_ f_return_status controller_rule_path(const controller_data_t data, const controller_setting_t setting, const f_string_static_t path_directory, const f_string_static_t path_name, f_string_dynamic_t *path) { f_status_t status = F_none; @@ -1067,7 +1219,7 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = fl_string_append(controller_string_rules, controller_string_rules_length, path); + status = fl_string_append(controller_string_rules_s, controller_string_rules_length, path); } if (F_status_is_error_not(status)) { @@ -1087,11 +1239,11 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = fl_string_append(f_path_extension_separator, f_path_extension_separator_length, path); + status = fl_string_append(f_path_extension_separator_s, f_path_extension_separator_length, path); } if (F_status_is_error_not(status)) { - status = fl_string_append(controller_string_rule, controller_string_rule_length, path); + status = fl_string_append(controller_string_rule_s, controller_string_rule_length, path); } if (F_status_is_error(status)) { @@ -1190,7 +1342,7 @@ extern "C" { cache->name_item.used = 0; cache->name_file.used = 0; - status = fl_string_append(controller_string_rules, controller_string_rules_length, &cache->name_file); + status = fl_string_append(controller_string_rules_s, controller_string_rules_length, &cache->name_file); if (F_status_is_error_not(status)) { status = fl_string_append(f_path_separator_s, f_path_separator_length, &cache->name_file); @@ -1215,7 +1367,7 @@ extern "C" { status = fl_string_append(f_path_extension_separator, f_path_extension_separator_length, &cache->name_file); if (F_status_is_error_not(status)) { - status = fl_string_append(controller_string_rule, controller_string_rule_length, &cache->name_file); + status = fl_string_append(controller_string_rule_s, controller_string_rule_length, &cache->name_file); } if (F_status_is_error(status)) { @@ -1459,37 +1611,42 @@ extern "C" { rule->nice = 0; f_macro_time_spec_t_clear(rule->timestamp); - f_macro_control_group_t_clear(rule->control_group); rule->id.used = 0; rule->name.used = 0; rule->path.used = 0; - rule->scheduler.policy = 0; - rule->scheduler.priority = 0; rule->script.used = 0; - for (f_array_length_t i = 0; i < rule->control_group.groups.used; ++i) { - rule->control_group.groups.array[i].used = 0; - } // for - - rule->control_group.as_new = F_false; - rule->control_group.path.used = 0; - rule->control_group.groups.used = 0; - rule->define.used = 0; rule->parameter.used = 0; - if (rule->capability) { - f_capability_delete(&rule->capability); - } - - rule->capability = 0; rule->environment.used = 0; rule->need.used = 0; rule->want.used = 0; rule->wish.used = 0; + rule->affinity.used = 0; + + if (rule->capability) { + f_capability_delete(&rule->capability); + rule->capability = 0; + } + + for (f_array_length_t i = 0; i < rule->control_group.groups.size; ++i) { + rule->control_group.groups.array[i].used = 0; + } // for + + rule->control_group.as_new = F_false; + rule->control_group.path.used = 0; + rule->control_group.groups.used = 0; + + f_macro_control_group_t_clear(rule->control_group); + rule->groups.used = 0; + rule->limits.used = 0; + + rule->scheduler.policy = 0; + rule->scheduler.priority = 0; rule->items.used = 0; @@ -1529,7 +1686,7 @@ extern "C" { fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_terminate_after", F_true); } else { - status = controller_file_load(data, setting, controller_string_rules, rule->id, controller_string_rule, controller_string_rules_length, controller_string_rule_length, cache); + status = controller_file_load(data, setting, controller_string_rules_s, rule->id, controller_string_rule_s, controller_string_rules_length, controller_string_rule_length, cache); } } @@ -1608,16 +1765,16 @@ extern "C" { break; } - if (fl_string_dynamic_compare_string(controller_string_setting, cache->name_item, controller_string_setting_length) == F_equal_to) { + if (fl_string_dynamic_compare_string(controller_string_setting_s, cache->name_item, controller_string_setting_length) == F_equal_to) { rule->items.array[rule->items.used].type = 0; } - else if (fl_string_dynamic_compare_string(controller_string_command, cache->name_item, controller_string_command_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_command_s, cache->name_item, controller_string_command_length) == F_equal_to) { rule->items.array[rule->items.used].type = controller_rule_item_type_command; } - else if (fl_string_dynamic_compare_string(controller_string_script, cache->name_item, controller_string_script_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_script_s, cache->name_item, controller_string_script_length) == F_equal_to) { rule->items.array[rule->items.used].type = controller_rule_item_type_script; } - else if (fl_string_dynamic_compare_string(controller_string_service, cache->name_item, controller_string_service_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_service_s, cache->name_item, controller_string_service_length) == F_equal_to) { rule->items.array[rule->items.used].type = controller_rule_item_type_service; } else { @@ -1706,10 +1863,23 @@ extern "C" { f_array_length_t j = 0; uint8_t type = 0; + // save the current name item and line number to restore on return. + const f_array_length_t line_item = cache->line_item; + const f_array_length_t length_name_item = cache->name_item.used; + + char name_item[length_name_item]; + name_item[length_name_item] = 0; + + memcpy(name_item, cache->name_item.string, length_name_item); + for (; i < cache->content_actions.used; ++i, type = 0) { + // name_action is used to store all setting values for a single setting. + cache->name_action.used = 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->object_actions.array[i], &cache->name_item); if (F_status_is_error(status)) { @@ -1725,70 +1895,90 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + status_return = status; + break; } if (F_status_is_error_not(status_return)) { status_return = status; } + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); continue; } - if (fl_string_dynamic_compare_string(controller_string_capability, cache->name_item, controller_string_capability_length) == F_equal_to) { + if (fl_string_dynamic_compare_string(controller_string_affinity_s, cache->name_item, controller_string_affinity_length) == F_equal_to) { + type = controller_rule_setting_type_affinity; + } + else if (fl_string_dynamic_compare_string(controller_string_capability_s, cache->name_item, controller_string_capability_length) == F_equal_to) { type = controller_rule_setting_type_capability; } - else if (fl_string_dynamic_compare_string(controller_string_control_group, cache->name_item, controller_string_control_group_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_control_group_s, cache->name_item, controller_string_control_group_length) == F_equal_to) { type = controller_rule_setting_type_control_group; } - else if (fl_string_dynamic_compare_string(controller_string_define, cache->name_item, controller_string_define_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_define_s, cache->name_item, controller_string_define_length) == F_equal_to) { type = controller_rule_setting_type_define; } - else if (fl_string_dynamic_compare_string(controller_string_environment, cache->name_item, controller_string_environment_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_environment_s, cache->name_item, controller_string_environment_length) == F_equal_to) { type = controller_rule_setting_type_environment; } - else if (fl_string_dynamic_compare_string(controller_string_group, cache->name_item, controller_string_group_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_group_s, cache->name_item, controller_string_group_length) == F_equal_to) { type = controller_rule_setting_type_group; } - else if (fl_string_dynamic_compare_string(controller_string_name, cache->name_item, controller_string_name_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_limit_s, cache->name_item, controller_string_limit_length) == F_equal_to) { + type = controller_rule_setting_type_limit; + } + else if (fl_string_dynamic_compare_string(controller_string_name_s, cache->name_item, controller_string_name_length) == F_equal_to) { type = controller_rule_setting_type_name; } - else if (fl_string_dynamic_compare_string(controller_string_need, cache->name_item, controller_string_need_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_need_s, cache->name_item, controller_string_need_length) == F_equal_to) { type = controller_rule_setting_type_need; } - else if (fl_string_dynamic_compare_string(controller_string_nice, cache->name_item, controller_string_nice_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_nice_s, cache->name_item, controller_string_nice_length) == F_equal_to) { type = controller_rule_setting_type_nice; } - else if (fl_string_dynamic_compare_string(controller_string_parameter, cache->name_item, controller_string_parameter_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_parameter_s, cache->name_item, controller_string_parameter_length) == F_equal_to) { type = controller_rule_setting_type_parameter; } - else if (fl_string_dynamic_compare_string(controller_string_path, cache->name_item, controller_string_path_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_path_s, cache->name_item, controller_string_path_length) == F_equal_to) { type = controller_rule_setting_type_path; } - else if (fl_string_dynamic_compare_string(controller_string_scheduler, cache->name_item, controller_string_scheduler_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_scheduler_s, cache->name_item, controller_string_scheduler_length) == F_equal_to) { type = controller_rule_setting_type_scheduler; } - else if (fl_string_dynamic_compare_string(controller_string_script, cache->name_item, controller_string_script_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_script_s, cache->name_item, controller_string_script_length) == F_equal_to) { type = controller_rule_setting_type_script; } - else if (fl_string_dynamic_compare_string(controller_string_user, cache->name_item, controller_string_user_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_user_s, cache->name_item, controller_string_user_length) == F_equal_to) { type = controller_rule_setting_type_user; } - else if (fl_string_dynamic_compare_string(controller_string_want, cache->name_item, controller_string_want_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_want_s, cache->name_item, controller_string_want_length) == F_equal_to) { type = controller_rule_setting_type_want; } - else if (fl_string_dynamic_compare_string(controller_string_wish, cache->name_item, controller_string_wish_length) == F_equal_to) { + else if (fl_string_dynamic_compare_string(controller_string_wish_s, cache->name_item, controller_string_wish_length) == F_equal_to) { type = controller_rule_setting_type_wish; } else { if (data.warning.verbosity == f_console_verbosity_debug) { + fprintf(data.warning.to.stream, "%c", f_string_eol_s[0]); fprintf(data.warning.to.stream, "%s%sUnknown rule setting '", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : f_string_empty_s); fprintf(data.warning.to.stream, "%s%s", data.warning.context.after->string, data.warning.notable.before->string); f_print_dynamic(data.warning.to.stream, cache->name_item); fprintf(data.warning.to.stream, "%s", data.warning.notable.after->string); fprintf(data.warning.to.stream, "%s'.%s%c", data.warning.context.before->string, data.warning.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.warning, *cache, F_false); } @@ -1800,15 +1990,18 @@ extern "C" { fprintf(data.warning.to.stream, "%c", f_string_eol_s[0]); fprintf(data.warning.to.stream, "%s%sEmpty rule setting.%s%c", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : f_string_empty_s, data.warning.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + 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->content_actions.array[i].array[0].start; range2.stop = cache->content_actions.array[i].array[cache->content_actions.array[i].used - 1].stop; @@ -1826,27 +2019,42 @@ extern "C" { } if (F_status_is_error(status)) { + + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + status_return = status; + break; } if (F_status_is_error_not(status_return)) { status_return = status; } - controller_rule_error_print(data.error, *cache, F_false); continue; } - if (type == controller_rule_setting_type_define || type == controller_rule_setting_type_parameter) { + if (type == controller_rule_setting_type_affinity) { + // @todo use sched_getaffinity() to get the available cpus and do not add an invalid cpu to the affinity array. - if (cache->content_actions.array[i].used != 2) { + if (!cache->content_actions.array[i].used) { if (data.error.verbosity != f_console_verbosity_quiet) { + + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + fprintf(data.error.to.stream, "%c", f_string_eol_s[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 : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + fprintf(data.error.to.stream, "%s%sRule setting requires one or more Content.%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); controller_rule_error_print(data.error, *cache, F_false); } @@ -1858,72 +2066,204 @@ extern "C" { continue; } - if (type == controller_rule_setting_type_define) { - setting_maps = &rule->define; - } - else if (type == controller_rule_setting_type_parameter) { - setting_maps = &rule->parameter; - } + rule->affinity.used = 0; - status = fl_string_maps_increase(setting_maps); + f_number_signed_t number = 0; - if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fl_string_maps_increase", F_true); + for (j = 0; j < cache->content_actions.array[i].used; ++j, number = 0) { - if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + // @todo this needs to be in a function such as f_int32s_increase(). + if (rule->affinity.used + 1 > rule->affinity.size) { + f_array_length_t size = rule->affinity.used + f_memory_default_allocation_step; + + if (size > f_array_length_t_size) { + if (rule->affinity.used + 1 > f_array_length_t_size) { + status = F_status_set_error(F_array_too_large); + } + else { + size = f_array_length_t_size; + } + } + + if (F_status_is_error_not(status)) { + f_macro_int32s_t_resize(status, rule->affinity, size); + } } - if (F_status_is_error_not(status_return)) { - status_return = status; + if (F_status_is_error(status)) { + fll_error_print(data.error, F_status_set_fine(status), "f_macro_int32s_t_resize", F_true); + break; } - controller_rule_error_print(data.error, *cache, F_false); - continue; - } + status = fl_conversion_string_to_number_signed(cache->buffer_item.string, &number, cache->content_actions.array[i].array[j]); - setting_maps->array[setting_maps->used].name.used = 0; - setting_maps->array[setting_maps->used].value.used = 0; + if (F_status_is_error(status)) { + status = F_status_set_fine(status); - status = fl_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[0], &setting_maps->array[setting_maps->used].name); + if (status == F_data_not || status == F_number || status == F_number_overflow || status == F_number_underflow) { - if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append_nulless", F_true); + if (data.error.verbosity != f_console_verbosity_quiet) { + if (status == F_number_overflow || status == F_number_underflow) { + fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); + fprintf(data.error.to.stream, "%s%sRule setting has an unsupported number '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); + fprintf(data.error.to.stream, "%s%s", data.error.context.after->string, data.error.notable.before->string); + f_print_dynamic_partial(data.error.to.stream, cache->buffer_item, cache->content_actions.array[i].array[j]); + fprintf(data.error.to.stream, "%s%s', the number is too large for this system.%s%c", data.error.notable.after->string, data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + } + else { + fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); + fprintf(data.error.to.stream, "%s%sRule setting has an invalid number '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); + fprintf(data.error.to.stream, "%s%s", data.error.context.after->string, data.error.notable.before->string); + f_print_dynamic_partial(data.error.to.stream, cache->buffer_item, cache->content_actions.array[i].array[j]); + fprintf(data.error.to.stream, "%s%s', only whole numbers are allowed for an affinity value.%s%c", data.error.notable.after->string, data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + } - if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; - } + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); - if (F_status_is_error_not(status_return)) { - status_return = status; - } + cache->line_action = ++cache->line_item; - controller_rule_error_print(data.error, *cache, F_false); - continue; - } + controller_rule_error_print(data.error, *cache, F_false); + } - status = fl_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[1], &setting_maps->array[setting_maps->used].value); + status = F_status_set_error(F_valid_not); - if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append_nulless", F_true); - } - else { - status = fl_string_dynamic_terminate_after(&setting_maps->array[setting_maps->used].value); + if (F_status_is_error_not(status_return)) { + status_return = status; + } + } + else { + fll_error_print(data.error, status, "fl_conversion_string_to_number_signed", F_true); - if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_terminate_after", F_true); - } - } + status = F_status_set_error(status); - if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; - } + if (F_status_is_error_not(status_return)) { + status_return = status; + } + } + + continue; + } + + rule->affinity.array[rule->affinity.used++] = number; + } // for + + continue; + } + + if (type == controller_rule_setting_type_define || type == controller_rule_setting_type_parameter) { + + if (cache->content_actions.array[i].used != 2) { + + if (data.error.verbosity != f_console_verbosity_quiet) { + + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + + fprintf(data.error.to.stream, "%c", f_string_eol_s[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 : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + + controller_rule_error_print(data.error, *cache, F_false); + } + + if (F_status_is_error_not(status_return)) { + status_return = F_status_set_error(F_valid_not); + } + + continue; + } + + if (type == controller_rule_setting_type_define) { + setting_maps = &rule->define; + } + else if (type == controller_rule_setting_type_parameter) { + setting_maps = &rule->parameter; + } + + status = fl_string_maps_increase(setting_maps); + + if (F_status_is_error(status)) { + fll_error_print(data.error, F_status_set_fine(status), "fl_string_maps_increase", F_true); + + if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { + status_return = status; + break; + } + + if (F_status_is_error_not(status_return)) { + status_return = status; + } + + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + + controller_rule_error_print(data.error, *cache, F_false); + continue; + } + + setting_maps->array[setting_maps->used].name.used = 0; + setting_maps->array[setting_maps->used].value.used = 0; + + status = fl_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[0], &setting_maps->array[setting_maps->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); + + if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { + status_return = status; + break; + } + + if (F_status_is_error_not(status_return)) { + status_return = status; + } + + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + + controller_rule_error_print(data.error, *cache, F_false); + continue; + } + + status = fl_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[1], &setting_maps->array[setting_maps->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); + } + else { + status = fl_string_dynamic_terminate_after(&setting_maps->array[setting_maps->used].value); + + if (F_status_is_error(status)) { + fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_terminate_after", F_true); + } + } + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { + status_return = status; + break; + } if (F_status_is_error_not(status_return)) { status_return = status; } + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); continue; } @@ -1940,6 +2280,12 @@ extern "C" { fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); fprintf(data.error.to.stream, "%s%sRule setting requires two or more Content.%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -1950,10 +2296,10 @@ extern "C" { continue; } - if (fl_string_dynamic_partial_compare_string(controller_string_existing, cache->buffer_item, controller_string_existing_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + if (fl_string_dynamic_partial_compare_string(controller_string_existing_s, cache->buffer_item, controller_string_existing_length, cache->content_actions.array[i].array[0]) == F_equal_to) { rule->control_group.as_new = F_false; } - else if (fl_string_dynamic_partial_compare_string(controller_string_new, cache->buffer_item, controller_string_new_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + else if (fl_string_dynamic_partial_compare_string(controller_string_new_s, cache->buffer_item, controller_string_new_length, cache->content_actions.array[i].array[0]) == F_equal_to) { rule->control_group.as_new = F_true; } else { @@ -1964,6 +2310,12 @@ extern "C" { f_print_dynamic_partial(data.error.to.stream, cache->buffer_item, cache->content_actions.array[i].array[0]); fprintf(data.error.to.stream, "%s%s'.%s%c", data.error.notable.after->string, data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -2013,7 +2365,8 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + status_return = status; + break; } rule->control_group.path.used = 0; @@ -2022,6 +2375,12 @@ extern "C" { status_return = status; } + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); continue; } @@ -2031,6 +2390,223 @@ extern "C" { continue; } + if (type == controller_rule_setting_type_limit) { + + if (cache->content_actions.array[i].used != 3) { + + if (data.error.verbosity != f_console_verbosity_quiet) { + fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); + fprintf(data.error.to.stream, "%s%sRule setting requires three Content.%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + + controller_rule_error_print(data.error, *cache, F_false); + } + + if (F_status_is_error_not(status_return)) { + status_return = F_status_set_error(F_valid_not); + } + + continue; + } + + if (fl_string_dynamic_partial_compare_string(controller_string_as_s, cache->buffer_item, controller_string_as_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_as; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_core_s, cache->buffer_item, controller_string_core_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_core; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_cpu_s, cache->buffer_item, controller_string_cpu_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_cpu; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_data_s, cache->buffer_item, controller_string_data_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_data; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_fsize_s, cache->buffer_item, controller_string_fsize_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_fsize; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_locks_s, cache->buffer_item, controller_string_locks_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_locks; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_memlock_s, cache->buffer_item, controller_string_memlock_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_memlock; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_msgqueue_s, cache->buffer_item, controller_string_msgqueue_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_msgqueue; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_nice_s, cache->buffer_item, controller_string_nice_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_nice; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_nofile_s, cache->buffer_item, controller_string_nofile_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_nofile; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_nproc_s, cache->buffer_item, controller_string_nproc_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_nproc; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_rss_s, cache->buffer_item, controller_string_rss_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_rss; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_rtprio_s, cache->buffer_item, controller_string_rtprio_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_rtprio; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_rttime_s, cache->buffer_item, controller_string_rttime_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_rttime; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_sigpending_s, cache->buffer_item, controller_string_sigpending_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_sigpending; + } + else if (fl_string_dynamic_partial_compare_string(controller_string_stack_s, cache->buffer_item, controller_string_stack_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + type = controller_resource_limit_type_stack; + } + else { + if (data.error.verbosity == f_console_verbosity_debug) { + fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); + fprintf(data.error.to.stream, "%s%sUnknown resource limit type '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); + fprintf(data.error.to.stream, "%s%s", data.error.context.after->string, data.error.notable.before->string); + f_print_dynamic(data.error.to.stream, cache->name_action); + fprintf(data.error.to.stream, "%s", data.error.notable.after->string); + fprintf(data.error.to.stream, "%s'.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + + controller_rule_error_print(data.error, *cache, F_true); + } + + if (F_status_is_error_not(status_return)) { + status_return = F_status_set_error(F_valid_not); + } + + continue; + } + + for (j = 0; j < rule->limits.used; ++j) { + + if (type == rule->limits.array[j].type) { + if (data.error.verbosity != f_console_verbosity_quiet) { + fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); + fprintf(data.error.to.stream, "%s%sThe resource limit type is already specified.%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + fprintf(data.error.to.stream, "%s%s", data.error.context.after->string, data.error.notable.before->string); + + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + + controller_rule_error_print(data.error, *cache, F_false); + } + + status = F_status_set_error(F_valid_not); + + if (F_status_is_error_not(status_return)) { + status_return = status; + } + } + } // for + + if (F_status_is_error(status)) continue; + + status = f_limit_sets_increase(&rule->limits); + + if (F_status_is_error(status)) { + fll_error_print(data.error, F_status_set_fine(status), "f_limit_sets_increase", F_true); + + if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { + status_return = status; + break; + } + + if (F_status_is_error_not(status_return)) { + status_return = status; + } + + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + + controller_rule_error_print(data.error, *cache, F_false); + continue; + } + + f_number_signed_t number = 0; + + for (j = 1; j < 3; ++j, number = 0) { + status = fl_conversion_string_to_number_signed(cache->buffer_item.string, &number, cache->content_actions.array[i].array[j]); + + if (F_status_is_error(status)) { + status = F_status_set_fine(status); + + if (status == F_data_not || status == F_number || status == F_number_overflow || status == F_number_underflow) { + + if (data.error.verbosity != f_console_verbosity_quiet) { + if (status == F_number_overflow || status == F_number_underflow) { + fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); + fprintf(data.error.to.stream, "%s%sRule setting has an unsupported number '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); + fprintf(data.error.to.stream, "%s%s", data.error.context.after->string, data.error.notable.before->string); + f_print_dynamic_partial(data.error.to.stream, cache->buffer_item, cache->content_actions.array[i].array[j]); + fprintf(data.error.to.stream, "%s%s', the number is too large for this system.%s%c", data.error.notable.after->string, data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + } + else { + fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); + fprintf(data.error.to.stream, "%s%sRule setting has an invalid number '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); + fprintf(data.error.to.stream, "%s%s", data.error.context.after->string, data.error.notable.before->string); + f_print_dynamic_partial(data.error.to.stream, cache->buffer_item, cache->content_actions.array[i].array[j]); + fprintf(data.error.to.stream, "%s%s', only whole numbers are allowed for a resource limit value.%s%c", data.error.notable.after->string, data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + } + + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + + controller_rule_error_print(data.error, *cache, F_false); + } + + status = F_status_set_error(F_valid_not); + + if (F_status_is_error_not(status_return)) { + status_return = status; + } + } + else { + fll_error_print(data.error, status, "fl_conversion_string_to_number_signed", F_true); + + status = F_status_set_error(status); + + if (F_status_is_error_not(status_return)) { + status_return = status; + } + } + + break; + } + + if (j == 1) { + rule->limits.array[rule->limits.used].value.rlim_cur = number; + } + else { + rule->limits.array[rule->limits.used].value.rlim_max = number; + } + } // for + + if (F_status_is_error(status)) continue; + + rule->limits.array[rule->limits.used++].type = type; + + continue; + } + if (type == controller_rule_setting_type_name || type == controller_rule_setting_type_path || type == controller_rule_setting_type_script) { if (type == controller_rule_setting_type_name) { setting_value = &rule->name; @@ -2048,6 +2624,12 @@ extern "C" { fprintf(data.error.to.stream, "%c", f_string_eol_s[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 : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -2066,13 +2648,20 @@ extern "C" { setting_value->used = 0; if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + status_return = status; + break; } if (F_status_is_error_not(status_return)) { status_return = status; } + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); continue; } @@ -2091,6 +2680,12 @@ extern "C" { fprintf(data.error.to.stream, "%s", data.error.notable.after->string); fprintf(data.error.to.stream, "%s', there must be at least 1 graph character.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -2110,6 +2705,12 @@ extern "C" { setting_value->used = 0; + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); continue; } @@ -2131,7 +2732,8 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + status_return = status; + break; } if (F_status_is_error_not(status_return)) { @@ -2140,6 +2742,12 @@ extern "C" { setting_value->used = 0; + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); continue; } @@ -2156,6 +2764,12 @@ extern "C" { fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); fprintf(data.error.to.stream, "%s%sRule setting requires either one or two Content.%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -2166,27 +2780,27 @@ extern "C" { continue; } - if (fl_string_dynamic_partial_compare_string(controller_string_batch, cache->buffer_item, controller_string_batch_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + if (fl_string_dynamic_partial_compare_string(controller_string_batch_s, cache->buffer_item, controller_string_batch_length, cache->content_actions.array[i].array[0]) == F_equal_to) { rule->scheduler.policy = SCHED_BATCH; rule->scheduler.priority = 0; } - else if (fl_string_dynamic_partial_compare_string(controller_string_deadline, cache->buffer_item, controller_string_deadline_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + else if (fl_string_dynamic_partial_compare_string(controller_string_deadline_s, cache->buffer_item, controller_string_deadline_length, cache->content_actions.array[i].array[0]) == F_equal_to) { rule->scheduler.policy = SCHED_DEADLINE; rule->scheduler.priority = 49; } - else if (fl_string_dynamic_partial_compare_string(controller_string_fifo, cache->buffer_item, controller_string_fifo_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + else if (fl_string_dynamic_partial_compare_string(controller_string_fifo_s, cache->buffer_item, controller_string_fifo_length, cache->content_actions.array[i].array[0]) == F_equal_to) { rule->scheduler.policy = SCHED_FIFO; rule->scheduler.priority = 49; } - else if (fl_string_dynamic_partial_compare_string(controller_string_idle, cache->buffer_item, controller_string_idle_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + else if (fl_string_dynamic_partial_compare_string(controller_string_idle_s, cache->buffer_item, controller_string_idle_length, cache->content_actions.array[i].array[0]) == F_equal_to) { rule->scheduler.policy = SCHED_IDLE; rule->scheduler.priority = 0; } - else if (fl_string_dynamic_partial_compare_string(controller_string_other, cache->buffer_item, controller_string_other_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + else if (fl_string_dynamic_partial_compare_string(controller_string_other_s, cache->buffer_item, controller_string_other_length, cache->content_actions.array[i].array[0]) == F_equal_to) { rule->scheduler.policy = SCHED_OTHER; rule->scheduler.priority = 0; } - else if (fl_string_dynamic_partial_compare_string(controller_string_round_robin, cache->buffer_item, controller_string_round_robin_length, cache->content_actions.array[i].array[0]) == F_equal_to) { + else if (fl_string_dynamic_partial_compare_string(controller_string_round_robin_s, cache->buffer_item, controller_string_round_robin_length, cache->content_actions.array[i].array[0]) == F_equal_to) { rule->scheduler.policy = SCHED_RR; rule->scheduler.priority = 49; } @@ -2198,6 +2812,12 @@ extern "C" { f_print_dynamic_partial(data.error.to.stream, cache->buffer_item, cache->content_actions.array[i].array[0]); fprintf(data.error.to.stream, "%s%s'.%s%c", data.error.notable.after->string, data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -2241,6 +2861,12 @@ extern "C" { fprintf(data.error.to.stream, " allowed for the designated scheduler.%s%c", data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -2251,6 +2877,10 @@ extern "C" { else { fll_error_print(data.error, status, "fl_conversion_string_to_number_signed", F_true); status = F_status_set_error(status); + + if (F_status_is_error_not(status_return)) { + status_return = status; + } } continue; @@ -2272,6 +2902,12 @@ extern "C" { fprintf(data.error.to.stream, "%c", f_string_eol_s[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 : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -2290,10 +2926,17 @@ extern "C" { if (F_status_is_error(status)) { fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append_nulless", F_true); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + status_return = status; + break; } if (F_status_is_error_not(status_return)) { @@ -2306,10 +2949,17 @@ extern "C" { if (F_status_is_error(status)) { fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_terminate_after", F_true); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + status_return = status; + break; } if (F_status_is_error_not(status_return)) { @@ -2323,15 +2973,29 @@ extern "C" { if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { fll_error_print(data.error, F_status_set_fine(status), "f_capability_from_text", F_true); + + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); - return status; + status_return = status; + break; } if (data.error.verbosity != f_console_verbosity_quiet) { fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); fprintf(data.error.to.stream, "%s%sRule setting failed to process the capabilities.%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -2350,7 +3014,7 @@ extern "C" { if (F_status_is_error(status) || number < -20 || number > 19) { status = F_status_set_fine(status); - if (number < -20 || number > 19 || status == F_data_not || status == F_number || status == F_number_overflow) { + if (number < -20 || number > 19 || status == F_data_not || status == F_number || status == F_number_overflow || status == F_number_underflow) { if (data.error.verbosity != f_console_verbosity_quiet) { fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); @@ -2363,6 +3027,12 @@ extern "C" { fprintf(data.error.to.stream, "%s%s19%s", data.error.context.after->string, data.error.notable.before->string, data.error.notable.after->string); fprintf(data.error.to.stream, "%s are allowed.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -2373,6 +3043,10 @@ extern "C" { else { fll_error_print(data.error, status, "fl_conversion_string_to_number_signed", F_true); status = F_status_set_error(status); + + if (F_status_is_error_not(status_return)) { + status_return = status; + } } } else { @@ -2422,6 +3096,12 @@ extern "C" { fll_error_print(data.error, status, "f_account_id_user_by_name", F_true); } + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); if (F_status_is_error_not(status_return)) { @@ -2443,6 +3123,12 @@ extern "C" { fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); fprintf(data.error.to.stream, "%s%sRule setting requires one or more Content.%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -2465,13 +3151,20 @@ extern "C" { fll_error_print(data.error, F_status_set_fine(status), "fl_type_int32s_increase", F_true); if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + status_return = status; + break; } if (F_status_is_error_not(status_return)) { status_return = status; } + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); continue; } @@ -2515,6 +3208,12 @@ extern "C" { fll_error_print(data.error, status, "f_account_id_group_by_name", F_true); } + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); if (F_status_is_error_not(status_return)) { @@ -2546,13 +3245,20 @@ extern "C" { fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamics_increase", F_true); if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + status_return = status; + break; } if (F_status_is_error_not(status_return)) { status_return = status; } + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); continue; } @@ -2576,13 +3282,20 @@ extern "C" { setting_values->array[setting_values->used].used = 0; if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + status_return = status; + break; } if (F_status_is_error_not(status_return)) { status_return = status; } + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); continue; } @@ -2598,6 +3311,12 @@ extern "C" { fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, setting_values->array[setting_values->used].string, data.error.notable.after->string); fprintf(data.error.to.stream, "%s'.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -2617,6 +3336,12 @@ extern "C" { setting_values->array[setting_values->used].used = 0; + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); continue; } @@ -2633,6 +3358,12 @@ extern "C" { fprintf(data.error.to.stream, "%c", f_string_eol_s[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 : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); } @@ -2659,13 +3390,20 @@ extern "C" { fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamics_increase_by", F_true); if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + status_return = status; + break; } if (F_status_is_error_not(status_return)) { status_return = status; } + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); continue; } @@ -2676,13 +3414,20 @@ extern "C" { setting_values->array[setting_values->used].used = 0; if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_memory_allocation || F_status_set_fine(status) == F_memory_reallocation) { - return status; + status_return = status; + break; } if (F_status_is_error_not(status_return)) { status_return = status; } + // get the current line number within the settings item. + cache->line_item = line_item; + f_fss_count_lines(cache->buffer_item, cache->object_actions.array[i].start, &cache->line_item); + + cache->line_action = ++cache->line_item; + controller_rule_error_print(data.error, *cache, F_false); continue; } @@ -2731,6 +3476,14 @@ extern "C" { setting_values->used++; } // for + // resore the current name item and line number, which there should already be enough allocated space for. + memcpy(cache->name_item.string, name_item, length_name_item); + + cache->name_item.string[length_name_item] = 0; + cache->name_item.used = length_name_item; + + cache->line_item = line_item; + return status_return; } #endif // _di_controller_rule_setting_read_ @@ -2787,21 +3540,21 @@ extern "C" { fprintf(data.output.stream, "' has no '"); fprintf(data.output.stream, "%s%s%s", data.context.set.important.before->string, controller_rule_action_type_name(action).string, data.context.set.important.after->string); fprintf(data.output.stream, "' action to execute and would '"); - fprintf(data.output.stream, "%s%s%s", data.context.set.important.before->string, options & controller_rule_option_require ? controller_string_fail : controller_string_succeed, data.context.set.important.after->string); + fprintf(data.output.stream, "%s%s%s", data.context.set.important.before->string, options & controller_rule_option_require ? controller_string_fail_s : controller_string_succeed_s, data.context.set.important.after->string); fprintf(data.output.stream, "' because it is '"); - fprintf(data.output.stream, "%s%s%s", data.context.set.important.before->string, options & controller_rule_option_require ? controller_string_required : controller_string_optional, data.context.set.important.after->string); + fprintf(data.output.stream, "%s%s%s", data.context.set.important.before->string, options & controller_rule_option_require ? controller_string_required_s : controller_string_optional_s, data.context.set.important.after->string); fprintf(data.output.stream, "'.%c", f_string_eol_s[0]); } } fprintf(data.output.stream, "%c", f_string_eol_s[0]); fprintf(data.output.stream, "Rule %s%s%s {%c", data.context.set.title.before->string, rule->id.used ? rule->id.string : f_string_empty_s, data.context.set.title.after->string, f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_name, data.context.set.important.after->string, rule->name.used ? rule->name.string : f_string_empty_s, f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_how, data.context.set.important.after->string, options & controller_rule_option_asynchronous ? controller_string_asynchronous : controller_string_synchronous, f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_wait, data.context.set.important.after->string, options & controller_rule_option_wait ? controller_string_yes : controller_string_no, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_name_s, data.context.set.important.after->string, rule->name.used ? rule->name.string : f_string_empty_s, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_how_s, data.context.set.important.after->string, options & controller_rule_option_asynchronous ? controller_string_asynchronous : controller_string_synchronous_s, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_wait_s, data.context.set.important.after->string, options & controller_rule_option_wait ? controller_string_yes : controller_string_no_s, f_string_eol_s[0]); if (f_capability_supported()) { - fprintf(data.output.stream, " %s%s%s ", data.context.set.important.before->string, controller_string_capability, data.context.set.important.after->string); + fprintf(data.output.stream, " %s%s%s ", data.context.set.important.before->string, controller_string_capability_s, data.context.set.important.after->string); if (rule->capability) { cache->buffer_other.used = 0; @@ -2814,92 +3567,96 @@ extern "C" { fprintf(data.output.stream, "%c", f_string_eol_s[0]); } else { - fprintf(data.output.stream, " %s%s%s ", data.context.set.important.before->string, controller_string_capability, data.context.set.important.after->string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s ", data.context.set.important.before->string, controller_string_capability_s, data.context.set.important.after->string, f_string_eol_s[0]); fprintf(data.output.stream, "%s(unsupported)%s%c", data.context.set.warning.before->string, data.context.set.warning.after->string, f_string_eol_s[0]); } - fprintf(data.output.stream, " %s%s%s", data.context.set.important.before->string, controller_string_control_group, data.context.set.important.after->string); + fprintf(data.output.stream, " %s%s%s", data.context.set.important.before->string, controller_string_control_group_s, data.context.set.important.after->string); if (rule->has & controller_rule_has_control_group) { - fprintf(data.output.stream, " %s", rule->control_group.as_new ? controller_string_new : controller_string_existing); + fprintf(data.output.stream, " %s", rule->control_group.as_new ? controller_string_new_s : controller_string_existing_s); for (i = 0; i < rule->control_group.groups.used; ++i) { if (rule->control_group.groups.array[i].used) { - fprintf(data.output.stream, " "); + fprintf(data.output.stream, f_string_space_s); f_print_dynamic(data.output.stream, rule->control_group.groups.array[i]); } } // for } fprintf(data.output.stream, "%c", f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s", data.context.set.important.before->string, controller_string_scheduler, data.context.set.important.after->string); + fprintf(data.output.stream, " %s%s%s", data.context.set.important.before->string, controller_string_nice_s, data.context.set.important.after->string); + if (rule->has & controller_rule_has_nice) { + fprintf(data.output.stream, " %i", rule->nice); + } + fprintf(data.output.stream, "%c", f_string_eol_s[0]); + + fprintf(data.output.stream, " %s%s%s", data.context.set.important.before->string, controller_string_scheduler_s, data.context.set.important.after->string); if (rule->has & controller_rule_has_scheduler) { f_string_t policy = ""; if (rule->scheduler.policy == SCHED_BATCH) { - policy = controller_string_batch; + policy = controller_string_batch_s; } else if (rule->scheduler.policy == SCHED_DEADLINE) { - policy = controller_string_deadline; + policy = controller_string_deadline_s; } else if (rule->scheduler.policy == SCHED_FIFO) { - policy = controller_string_fifo; + policy = controller_string_fifo_s; } else if (rule->scheduler.policy == SCHED_IDLE) { - policy = controller_string_idle; + policy = controller_string_idle_s; } else if (rule->scheduler.policy == SCHED_OTHER) { - policy = controller_string_other; + policy = controller_string_other_s; } else if (rule->scheduler.policy == SCHED_RR) { - policy = controller_string_round_robin; + policy = controller_string_round_robin_s; } fprintf(data.output.stream, " %s %i", policy, rule->scheduler.priority); } fprintf(data.output.stream, "%c", f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_script, data.context.set.important.after->string, rule->script.used ? rule->script.string : f_string_empty_s, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_script_s, data.context.set.important.after->string, rule->script.used ? rule->script.string : f_string_empty_s, f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s", data.context.set.important.before->string, controller_string_nice, data.context.set.important.after->string); - if (rule->has & controller_rule_has_nice) { - fprintf(data.output.stream, " %i", rule->nice); - } - fprintf(data.output.stream, "%c", f_string_eol_s[0]); - - fprintf(data.output.stream, " %s%s%s", data.context.set.important.before->string, controller_string_user, data.context.set.important.after->string); + fprintf(data.output.stream, " %s%s%s", data.context.set.important.before->string, controller_string_user_s, data.context.set.important.after->string); if (rule->has & controller_rule_has_user) { fprintf(data.output.stream, " %i", rule->user); } fprintf(data.output.stream, "%c", f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_define, data.context.set.important.after->string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_affinity_s, data.context.set.important.after->string, f_string_eol_s[0]); + + for (i = 0; i < rule->affinity.used; ++i) { + fprintf(data.output.stream, " %i%c", rule->affinity.array[i], f_string_eol_s[0]); + } // for - if (rule->define.used) { - for (i = 0; i < rule->define.used; ++i) { + fprintf(data.output.stream, " }%c", f_string_eol_s[0]); - if (rule->define.array[i].name.used && rule->define.array[i].value.used) { - fprintf(data.output.stream, " %s %s=%s %s%c", rule->define.array[i].name.string, data.context.set.important.before->string, data.context.set.important.after->string, rule->define.array[i].value.string, f_string_eol_s[0]); - } - } // for - } + fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_define_s, data.context.set.important.after->string, f_string_eol_s[0]); + + for (i = 0; i < rule->define.used; ++i) { + + if (rule->define.array[i].name.used && rule->define.array[i].value.used) { + fprintf(data.output.stream, " %s %s=%s %s%c", rule->define.array[i].name.string, data.context.set.important.before->string, data.context.set.important.after->string, rule->define.array[i].value.string, f_string_eol_s[0]); + } + } // for fprintf(data.output.stream, " }%c", f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_environment, data.context.set.important.after->string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_environment_s, data.context.set.important.after->string, f_string_eol_s[0]); - if (rule->environment.used) { - for (i = 0; i < rule->environment.used; ++i) { + for (i = 0; i < rule->environment.used; ++i) { - if (rule->environment.array[i].used) { - fprintf(data.output.stream, " %s%c", rule->environment.array[i].string, f_string_eol_s[0]); - } - } // for - } + if (rule->environment.array[i].used) { + fprintf(data.output.stream, " %s%c", rule->environment.array[i].string, f_string_eol_s[0]); + } + } // for fprintf(data.output.stream, " }%c", f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_group, data.context.set.important.after->string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_group_s, data.context.set.important.after->string, f_string_eol_s[0]); if (rule->has & controller_rule_has_group) { fprintf(data.output.stream, " %i%c", rule->group, f_string_eol_s[0]); @@ -2911,55 +3668,56 @@ extern "C" { fprintf(data.output.stream, " }%c", f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_need, data.context.set.important.after->string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_limit_s, data.context.set.important.after->string, f_string_eol_s[0]); - if (rule->need.used) { - for (i = 0; i < rule->need.used; ++i) { + for (i = 0; i < rule->limits.used; ++i) { - if (rule->need.array[i].used) { - fprintf(data.output.stream, " %s%c", rule->need.array[i].string, f_string_eol_s[0]); - } - } // for - } + fprintf(data.output.stream, " %s %s=%s %llu %llu%c", controller_rule_setting_limit_type_name(rule->limits.array[i].type).string, data.context.set.important.before->string, data.context.set.important.after->string, rule->limits.array[i].value.rlim_cur, rule->limits.array[i].value.rlim_max, f_string_eol_s[0]); + } // for fprintf(data.output.stream, " }%c", f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_parameter, data.context.set.important.after->string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_need_s, data.context.set.important.after->string, f_string_eol_s[0]); - if (rule->parameter.used) { - for (i = 0; i < rule->parameter.used; ++i) { + for (i = 0; i < rule->need.used; ++i) { - if (rule->parameter.array[i].name.used && rule->parameter.array[i].value.used) { - fprintf(data.output.stream, " %s %s=%s %s%c", rule->parameter.array[i].name.string, data.context.set.important.before->string, data.context.set.important.after->string, rule->parameter.array[i].value.string, f_string_eol_s[0]); - } - } // for - } + if (rule->need.array[i].used) { + fprintf(data.output.stream, " %s%c", rule->need.array[i].string, f_string_eol_s[0]); + } + } // for fprintf(data.output.stream, " }%c", f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_want, data.context.set.important.after->string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_parameter_s, data.context.set.important.after->string, f_string_eol_s[0]); - if (rule->want.used) { - for (i = 0; i < rule->want.used; ++i) { + for (i = 0; i < rule->parameter.used; ++i) { - if (rule->want.array[i].used) { - fprintf(data.output.stream, " %s%c", rule->want.array[i].string, f_string_eol_s[0]); - } - } // for - } + if (rule->parameter.array[i].name.used && rule->parameter.array[i].value.used) { + fprintf(data.output.stream, " %s %s=%s %s%c", rule->parameter.array[i].name.string, data.context.set.important.before->string, data.context.set.important.after->string, rule->parameter.array[i].value.string, f_string_eol_s[0]); + } + } // for fprintf(data.output.stream, " }%c", f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_wish, data.context.set.important.after->string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_want_s, data.context.set.important.after->string, f_string_eol_s[0]); - if (rule->wish.used) { - for (i = 0; i < rule->wish.used; ++i) { + for (i = 0; i < rule->want.used; ++i) { - if (rule->wish.array[i].used) { - fprintf(data.output.stream, " %s%c", rule->wish.array[i].string, f_string_eol_s[0]); - } - } // for - } + if (rule->want.array[i].used) { + fprintf(data.output.stream, " %s%c", rule->want.array[i].string, f_string_eol_s[0]); + } + } // for + + fprintf(data.output.stream, " }%c", f_string_eol_s[0]); + + fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_wish_s, data.context.set.important.after->string, f_string_eol_s[0]); + + for (i = 0; i < rule->wish.used; ++i) { + + if (rule->wish.array[i].used) { + fprintf(data.output.stream, " %s%c", rule->wish.array[i].string, f_string_eol_s[0]); + } + } // for fprintf(data.output.stream, " }%c", f_string_eol_s[0]); @@ -2975,20 +3733,20 @@ extern "C" { item = &rule->items.array[i]; - fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_item, data.context.set.important.after->string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_item_s, data.context.set.important.after->string, f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_type, data.context.set.important.after->string, controller_rule_item_type_name(item->type).string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_type_s, data.context.set.important.after->string, controller_rule_item_type_name(item->type).string, f_string_eol_s[0]); for (j = 0; j < item->actions.used; ++j) { action = &item->actions.array[j]; - fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_action, data.context.set.important.after->string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_action_s, data.context.set.important.after->string, f_string_eol_s[0]); - fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_type, data.context.set.important.after->string, controller_rule_action_type_name(action->type).string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_type_s, data.context.set.important.after->string, controller_rule_action_type_name(action->type).string, f_string_eol_s[0]); if (item->type == controller_rule_item_type_script) { - fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_parameter, data.context.set.important.after->string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s {%c", data.context.set.important.before->string, controller_string_parameter_s, data.context.set.important.after->string, f_string_eol_s[0]); parameter = &action->parameters.array[0]; @@ -3003,13 +3761,15 @@ extern "C" { fprintf(data.output.stream, " "); } } // for + + fprintf(data.output.stream, "%c", f_string_eol_s[0]); } fprintf(data.output.stream, " }%c", f_string_eol_s[0]); } else { for (k = 0; k < action->parameters.used; ++k) { - fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_parameter, data.context.set.important.after->string, action->parameters.array[k].string, f_string_eol_s[0]); + fprintf(data.output.stream, " %s%s%s %s%c", data.context.set.important.before->string, controller_string_parameter_s, data.context.set.important.after->string, action->parameters.array[k].string, f_string_eol_s[0]); } // for } diff --git a/level_3/controller/c/private-rule.h b/level_3/controller/c/private-rule.h index b795fbf..0b10f1e 100644 --- a/level_3/controller/c/private-rule.h +++ b/level_3/controller/c/private-rule.h @@ -448,6 +448,20 @@ extern "C" { #endif // _di_controller_rule_items_increase_by_ /** + * Get a string representing the rule setting limit type. + * + * @param type + * The rule setting limit type code. + * + * @return + * The string with used > 0 on success. + * The string with used == 0 if no match was found. + */ +#ifndef _di_controller_rule_setting_limit_type_name_ + extern f_string_static_t controller_rule_setting_limit_type_name(const uint8_t type) f_gcc_attribute_visibility_internal; +#endif // di_controller_rule_setting_limit_type_name_ + +/** * Construct a canonical rule file path from the given path directory and name. * * @param data diff --git a/level_3/controller/data/build/settings b/level_3/controller/data/build/settings index 230d232..9cecadf 100644 --- a/level_3/controller/data/build/settings +++ b/level_3/controller/data/build/settings @@ -19,7 +19,7 @@ build_compiler gcc build_indexer ar build_language c build_libraries -pthread -lc -lcap -build_libraries-individual -lfll_control_group -lfll_environment -lfll_error -lfll_execute -lfll_fss -lfll_path -lfll_program -lfll_status -lfl_color -lfl_console -lfl_control_group -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_iki -lfl_status -lfl_string -lfl_type -lf_account -lf_capability -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_iki -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_thread -lf_utf +build_libraries-individual -lfll_control_group -lfll_environment -lfll_error -lfll_execute -lfll_fss -lfll_path -lfll_program -lfll_status -lfl_color -lfl_console -lfl_control_group -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_iki -lfl_status -lfl_string -lfl_type -lf_account -lf_capability -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_iki -lf_limit -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_thread -lf_utf build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll build_sources_library controller.c private-control.c private-controller.c private-entry.c private-rule.c diff --git a/level_3/controller/data/settings/example/rules/command/multiple.rule b/level_3/controller/data/settings/example/rules/command/multiple.rule index 88efe7c..cb55d79 100644 --- a/level_3/controller/data/settings/example/rules/command/multiple.rule +++ b/level_3/controller/data/settings/example/rules/command/multiple.rule @@ -9,23 +9,49 @@ setting: #user kevin #group list 8 root + limit nofile 5000 10000 + limit nproc 1000 2000 + limit nice 1 2 + + affinity 0 + need script require_me script: start { echo + echo "Current ulimit is" + ulimit -a + sleep 5 + + echo echo "Current cgroup for self (PPID $PPID, PID $$) is: '$(cat /proc/self/cgroup)'" - sleep 20 + sleep 5 } command: start { id - sleep 20 + sleep 5 } +script: + start echo + command: start whoami +script: + start echo + +command: + start sleep 5 + command: start date -u + +script: + start echo + +script: + start sleep 5 diff --git a/level_3/controller/documents/rule.txt b/level_3/controller/documents/rule.txt index 537c63d..f51adad 100644 --- a/level_3/controller/documents/rule.txt +++ b/level_3/controller/documents/rule.txt @@ -9,15 +9,17 @@ Rule Documentation: Multiple outer most list Objects may be specified and they are executed as provided, in a top-down manner. The "settings" Rule Type has the following FSS-0001 (Extended) Content\: + "affinity": Define one ore more processors to restrict this rule by with each number representing a specific processor by its id (starting at 0). "capability": Define a set of capabilities in which to use, using the capability "text" format (such as "= cap_chown+ep"). "control_group": Define a control group (cgroup) in which everything within this rule executes under. - "define": Define a custom environment variable with a given variable, and automatically expose it to processes executed within this rule. + "define": Define a custom environment variable with a given variable, and automatically expose it to processes executed within this rule. @todo make sure this is implemented. "environment": A set of environment variables to expose to the processes executed within this rule (PATH is always exposed). "group": A set of group names or IDs to execute as with the first group being the primary group and all remaining being supplementary groups. + "limit": Define a resource limit to use (multiple limits may be specified, but only once for each type). "name": A name used to represent this rule, which is printed to the user, screen, logs, etc... "need": A single rule required to be executed (must exist and must succeed) before this rule starts. "nice": A single niceness value to run all processes executed within this rule as (-20 gets to be greediest in CPU usage and 19 being the nicest in CPU usage). - "parameter": A statically defined IKI name and its associated value for use in this rule file. + "parameter": A statically defined IKI name and its associated value for use in this rule file. @todo make sure this is implemented and make sure to perform iki substitutions (with "define" being a reserved iki parameter name for environment variable usage, such as define:"PATH"). "path": A single Content used to set a custom PATH environment variable value. "script": An executable name of a script, such as "bash", to use for the "script" Rule Type (which likely defaults to "bash" if not specified). "scheduler": A valid name of a scheduler to use followed by an optional priority number. @@ -34,6 +36,11 @@ Rule Documentation: In the case of "group" and "user", only users and groups that the user the controller program is being run as may be used. + In the case of "limit", first parameter must be one of the following: as, core, cpu, data, fsize, locks, memlock, msgqueue, nice, nofile, nproc, rss, rtprio, rttime, sigpending, and stack. + The second parameter repesents the soft limit. + The third parameter represents the hard limit. + This may be specified multiply times, but only once for each type. + In the case of "want" and "wish", if the desired rule is either not found or is otherwise disabled, then this will not fail or otherwise block the wanting or wishing rule. In the case of "path", when specified, the PATH environment variable is automatically added to the "environment" setting. diff --git a/level_3/controller/specifications/rule.txt b/level_3/controller/specifications/rule.txt index afd0b9e..4713a38 100644 --- a/level_3/controller/specifications/rule.txt +++ b/level_3/controller/specifications/rule.txt @@ -28,11 +28,13 @@ Rule Specification: The other Rule Types are processed top-down. The "settings" Rule Type has the following FSS-0001 (Extended)\: + "affinity": One or more Content, each must be a 0 or greater whole number. "capability": One Content representing capabilities. "control_group": Two or more Content, the first Content being either "existing" or "new" and the remaining representing a valid control group (cgroup) name, must have at least 1 graph character (non-whitespace printing character) (leading and trailing whitespace are trimmed off). "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). "group": One or more Content representing group names or group ids. + "limit": Three Content, with the first representing a valid resource type and the second and third being a valid resource limit number (positive whole number or 0). "name": One Content, must have at least 1 graph character (non-whitespace printing character) (leading and trailing whitespace are trimmed off). "need": Two Content, the first being a partial path and the second being a rule file name without extension (such as "boot" "modules"). "nice": One Content, must be a valid number for process "niceness" (Any whole number inclusively between -20 to 19). diff --git a/level_3/fake/c/private-build.c b/level_3/fake/c/private-build.c index 98e8304..dc82ed7 100644 --- a/level_3/fake/c/private-build.c +++ b/level_3/fake/c/private-build.c @@ -526,7 +526,7 @@ extern "C" { if (data.define.used) { for (f_array_length_t i = 0; i < data.define.used; i++) { - *status = fl_string_dynamic_mash(" ", 1, data.define.array[i], &defines); + *status = fl_string_dynamic_mash(f_string_space_s, 1, data.define.array[i], &defines); if (F_status_is_error(*status)) { break; diff --git a/level_3/fake/c/private-make.c b/level_3/fake/c/private-make.c index 606956b..85f02b7 100644 --- a/level_3/fake/c/private-make.c +++ b/level_3/fake/c/private-make.c @@ -588,7 +588,7 @@ extern "C" { if (F_status_is_error_not(*status) && j + 1 < settings.contents.array[i].used) { function_name = "fl_string_append_assure"; - *status = fl_string_append_assure(" ", 1, &data_make->setting_make.parameter.array[0].value.array[0]); + *status = fl_string_append_assure(f_string_space_s, 1, &data_make->setting_make.parameter.array[0].value.array[0]); } if (F_status_is_error(*status)) { @@ -702,7 +702,7 @@ extern "C" { for (f_array_length_t j = 0; j < define.array[i].value.used; j++) { - *status = fl_string_dynamic_mash(" ", 1, define.array[i].value.array[j], &combined); + *status = fl_string_dynamic_mash(f_string_space_s, 1, define.array[i].value.array[j], &combined); if (F_status_is_error(*status)) { fll_error_print(data.error, F_status_set_fine(*status), "fl_string_dynamic_mash_nulless", F_true); @@ -1370,7 +1370,7 @@ extern "C" { for (l = 0; l < reserved_value[k]->used; l++) { if (l > 0) { - *status = fl_string_append(" ", 1, &arguments->array[arguments->used]); + *status = fl_string_append(f_string_space_s, 1, &arguments->array[arguments->used]); if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "fl_string_append", F_true); @@ -1411,7 +1411,7 @@ extern "C" { for (l = 0; l < parameter->array[k].value.used; l++) { if (l > 0) { - *status = fl_string_append(" ", 1, &arguments->array[arguments->used]); + *status = fl_string_append(f_string_space_s, 1, &arguments->array[arguments->used]); if (F_status_is_error(*status)) { fll_error_print(data_make->error, F_status_set_fine(*status), "fl_string_append", F_true); @@ -1781,7 +1781,7 @@ extern "C" { for (f_array_length_t j = 0; j < dynamics_value[i].used; j++) { - status = fl_string_dynamic_mash(" ", 1, dynamics_value[i].array[j], &value); + status = fl_string_dynamic_mash(f_string_space_s, 1, dynamics_value[i].array[j], &value); if (F_status_is_error(status)) { break; @@ -3597,7 +3597,7 @@ extern "C" { f_print_dynamic(data->output.stream, arguments.array[i]); if (i + 1 < arguments.used) { - fprintf(data->output.stream, " "); + fprintf(data->output.stream, f_string_space_s); } } // for diff --git a/level_3/fake/data/build/settings b/level_3/fake/data/build/settings index 314af23..3e9eb16 100644 --- a/level_3/fake/data/build/settings +++ b/level_3/fake/data/build/settings @@ -19,7 +19,7 @@ build_compiler gcc build_indexer ar build_language c build_libraries -lc -lcap -build_libraries-individual -lfll_environment -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_path -lfll_program -lfl_color -lfl_console -lfl_control_group -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_iki -lfl_status -lfl_string -lfl_utf -lf_account -lf_capability -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_iki -lf_memory -lf_path -lf_print -lf_signal -lf_utf +build_libraries-individual -lfll_environment -lfll_error -lfll_execute -lfll_file -lfll_fss -lfll_path -lfll_program -lfl_color -lfl_console -lfl_control_group -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_iki -lfl_status -lfl_string -lfl_utf -lf_account -lf_capability -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_iki -lf_limit -lf_memory -lf_path -lf_print -lf_signal -lf_thread -lf_utf build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll build_sources_library fake.c private-fake.c private-clean.c private-build.c private-make.c private-print.c private-skeleton.c diff --git a/level_3/firewall/data/build/settings b/level_3/firewall/data/build/settings index ba3ae4e..f34619c 100644 --- a/level_3/firewall/data/build/settings +++ b/level_3/firewall/data/build/settings @@ -19,7 +19,7 @@ build_compiler gcc build_indexer ar build_language c build_libraries -lc -lcap -build_libraries-individual -lfll_error -lfll_execute -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_control_group -lfl_conversion -lfl_environment -lfl_fss -lfl_status -lfl_string -lf_account -lf_capability -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf +build_libraries-individual -lfll_error -lfll_execute -lfll_fss -lfll_program -lfl_color -lfl_console -lfl_control_group -lfl_conversion -lfl_environment -lfl_fss -lfl_status -lfl_string -lf_account -lf_capability -lf_console -lf_conversion -lf_directory -lf_environment -lf_file -lf_fss -lf_limit -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_thread -lf_utf build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll build_sources_library firewall.c private-firewall.c diff --git a/level_3/iki_read/c/iki_read.c b/level_3/iki_read/c/iki_read.c index 70f02a5..832c4f5 100644 --- a/level_3/iki_read/c/iki_read.c +++ b/level_3/iki_read/c/iki_read.c @@ -55,11 +55,11 @@ extern "C" { fl_color_print(output.stream, context.set.notable, "<"); fprintf(output.stream, "%s", iki_read_substitution_vocabulary); fl_color_print(output.stream, context.set.notable, ">"); - fprintf(output.stream, " "); + fprintf(output.stream, f_string_space_s); fl_color_print(output.stream, context.set.notable, "<"); fprintf(output.stream, "%s", iki_read_substitution_replace); fl_color_print(output.stream, context.set.notable, ">"); - fprintf(output.stream, " "); + fprintf(output.stream, f_string_space_s); fl_color_print(output.stream, context.set.notable, "<"); fprintf(output.stream, "%s", iki_read_substitution_with); fl_color_print(output.stream, context.set.notable, ">"); -- 1.8.3.1