]> Kevux Git Server - fll/commitdiff
Progress: controller program and other minor tweaks.
authorKevin Day <thekevinday@gmail.com>
Mon, 4 Jan 2021 03:20:05 +0000 (21:20 -0600)
committerKevin Day <thekevinday@gmail.com>
Mon, 4 Jan 2021 03:23:32 +0000 (21:23 -0600)
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 " ".

49 files changed:
build/level_0/settings
build/level_2/settings
build/monolithic/settings
build/scripts/bootstrap-example.sh
level_0/f_control_group/c/control_group.h
level_0/f_execute/c/execute-common.h
level_0/f_execute/c/execute.h
level_0/f_fss/c/fss.h
level_0/f_limit/c/limit-common.h [new file with mode: 0644]
level_0/f_limit/c/limit.c [new file with mode: 0644]
level_0/f_limit/c/limit.h [new file with mode: 0644]
level_0/f_limit/c/private-limit.c [new file with mode: 0644]
level_0/f_limit/c/private-limit.h [new file with mode: 0644]
level_0/f_limit/data/build/defines [new file with mode: 0644]
level_0/f_limit/data/build/dependencies [new file with mode: 0644]
level_0/f_limit/data/build/settings [new file with mode: 0644]
level_0/f_status/c/status.h
level_0/f_string/c/string-common.h
level_0/f_string/c/string.h
level_0/f_type/c/type_array.h
level_1/fl_execute/c/execute-common.h
level_1/fl_execute/c/execute.h
level_1/fl_execute/data/build/dependencies
level_1/fl_execute/data/build/settings
level_1/fl_status/c/status.c
level_1/fl_status/c/status.h
level_2/fll_execute/c/execute.h
level_2/fll_execute/c/private-execute.c
level_2/fll_execute/c/private-execute.h
level_2/fll_execute/data/build/dependencies
level_2/fll_execute/data/build/settings
level_2/fll_program/c/program.c
level_2/fll_status/c/status.c
level_3/byte_dump/c/private-byte_dump.c
level_3/controller/c/controller.c
level_3/controller/c/private-common.h
level_3/controller/c/private-controller.c
level_3/controller/c/private-entry.c
level_3/controller/c/private-rule.c
level_3/controller/c/private-rule.h
level_3/controller/data/build/settings
level_3/controller/data/settings/example/rules/command/multiple.rule
level_3/controller/documents/rule.txt
level_3/controller/specifications/rule.txt
level_3/fake/c/private-build.c
level_3/fake/c/private-make.c
level_3/fake/data/build/settings
level_3/firewall/data/build/settings
level_3/iki_read/c/iki_read.c

index 68b9c743739302b346faa7053fd20121d4507c20..7952ea05f070e878e857503414b912cfd0e813d9 100644 (file)
@@ -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
index 59a660c33032dfce076468526cb5713e56bb5c2e..f002b57d5602f2396eb6fd923ffaf53830c8be4a 100644 (file)
@@ -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
index 5be10cfd412cbe940a6ee1dea48339260ae84474..df778bf965f5268e482149866f410e96da7e9f0c 100644 (file)
@@ -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
index 275b122699ff39c209d491aa0b7a8eb531712249..83a9c7ef6668ae9eaa175eb728df7ca24347859d 100644 (file)
@@ -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/ &&
index 100242b8603877a4e660b3e3cbed15f0f138b4e4..f0b8e62923e192d15366d9204621e61dde5c5d7f 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * FLL - Level 1
+ * FLL - Level 0
  *
  * Project: Control Group
  * API Version: 0.5
index 71a8d006700d3460b36706c537bdf1f4bf600ef3..476a60727e9aa1ef9081d9b734386adf60d25d92 100644 (file)
@@ -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;
  */
index 60e6abb0a4776d018e896848e97e11154243b28b..942c48ac96b17067c4bdfc61e3fd33f605b4e964 100644 (file)
 #ifndef _F_execute_h
 #define _F_execute_h
 
+// include pre-requirements
+#define _GNU_SOURCE
+
 // libc includes
+#include <sched.h>
 
 // fll-0 includes
 #include <level_0/type.h>
index 8fe185a68a5ad88456f93512f323aa0461311a85..877b590dc3e9cbb53c77e806f643e677fabc66a8 100644 (file)
@@ -17,8 +17,8 @@
 
 // fll-0 includes
 #include <level_0/type.h>
-#include <level_0/status.h>
 #include <level_0/type_array.h>
+#include <level_0/status.h>
 #include <level_0/memory.h>
 #include <level_0/string.h>
 #include <level_0/utf.h>
diff --git a/level_0/f_limit/c/limit-common.h b/level_0/f_limit/c/limit-common.h
new file mode 100644 (file)
index 0000000..e5d631d
--- /dev/null
@@ -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 (file)
index 0000000..26247a8
--- /dev/null
@@ -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 (file)
index 0000000..5a17766
--- /dev/null
@@ -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 <sys/time.h>
+#include <sys/resource.h>
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+#include <level_0/memory.h>
+
+// fll-1 control includes
+#include <level_0/limit-common.h>
+
+#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 (file)
index 0000000..8a48b18
--- /dev/null
@@ -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 (file)
index 0000000..b60b7a5
--- /dev/null
@@ -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 (file)
index 0000000..4f13080
--- /dev/null
@@ -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 (file)
index 0000000..66dca29
--- /dev/null
@@ -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 (file)
index 0000000..5e95afa
--- /dev/null
@@ -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
index 8d17fa5a178f39410ca020e86b531c0ae293a4f6..8ec171f8da4593919916a6376c62c5a62271db82 100644 (file)
@@ -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,
index 4c6c9aa699e1b2f4d8637f6e5788c41489e4b332..eb61adef00dde06f1811cd1f168c782ff1a849a9 100644 (file)
@@ -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.
index 50342358a180b45e3562c35455f39285cfbd1adf..7d2f9f05fc6411a2c5e79a96a3072e911245470b 100644 (file)
@@ -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_
index 8b178bafefa72d0e3ccf46b6ec6c1d13fcf61cec..ccb663d796b235c3533d9daddf5f2a7861f29d39 100644 (file)
@@ -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.
index c876d1172927bc7e8578915ca5da3c17dda11b01..ae8b43dd9e776ffc576c0b3a6001f6e13e544219 100644 (file)
@@ -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_
 
index 9f030053c93c21f1f0cc16a093357969a83fac5a..f4a98cbf38ff670fce2e23275497c9a7f9bd873b 100644 (file)
 
 // fll-0 includes
 #include <level_0/type.h>
+#include <level_0/type_array.h>
 #include <level_0/status.h>
 #include <level_0/execute.h>
+#include <level_0/limit.h>
 #include <level_0/signal.h>
-#include <level_0/type_array.h>
 
 // fll-1 execute includes
 #include <level_1/execute-common.h>
index 7e334341da744fd587dc9530f09cd7bcf1dc0930..2747470e616d123de576babbf5231ed0b934027a 100644 (file)
@@ -4,5 +4,6 @@ f_type
 f_status
 f_string
 f_capability
+f_limit
 f_signal
 f_execute
index 3e48aed2834a40e6d774a5bacfbe4f9e44959021..9b4c26d2c6a701faed26554a97a8baff77b07147 100644 (file)
@@ -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
index 1a5aa85c98e21af73462b6efc4cb582c2f5cbe9c..d500c725c8bd3fe495a68438feea2c5051c3eec1 100644 (file)
@@ -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;
index 8fe136d3edeb882c9826ec55f022ff9d1e1e41e7..bf6dec7c56e0a21b6d60afe57e5b58852740c096 100644 (file)
@@ -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
index d6ae81f0bd1aab7f19716e9d253d2219461f6d95..f3d752c2a29352177f24f0d2f8b0c8c23cb9444e 100644 (file)
@@ -37,6 +37,7 @@
 #include <level_0/environment.h>
 #include <level_0/execute.h>
 #include <level_0/file.h>
+#include <level_0/limit.h>
 #include <level_0/path.h>
 #include <level_0/signal.h>
 
@@ -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()
index 9f885484eeda165cb235152df8a40c3850c662de..b8635769a19b5074f1b8476fc926b660bda14d0d 100644 (file)
@@ -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;
index 3fc9b2181d23b941013a2a01a32a545ae8836543..c1581e5e46a92178b1e6832b50f78cfcdf0e910c 100644 (file)
@@ -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()
index 4e06e339aa4b28f48150cbfd57c69252d51bbdee..f87fce0b69a96df5f13df386212a38ad3e481007 100644 (file)
@@ -9,6 +9,7 @@ f_capability
 f_environment
 f_execute
 f_file
+f_limit
 f_path
 f_signal
 f_thread
index c95b57d67079b18774bc475ef4bdfa1e58679d09..162020808a8731e2fdfd6b42c2c2c5e715851969 100644 (file)
@@ -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
index 08201fc9522e38b0e6c4ede5a2bdb9f92faa7186..1339263c011e4dcfc0ef16fd98686e8febea9ef6 100644 (file)
@@ -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);
index b7dfa55f0082be80bd6496efbe1407a606c10721..894b814c680e28642d91a3c00fe5d14094c6269a 100644 (file)
@@ -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;
index eb86b57cda08b7a044c0b6067b28c3da552ca44f..9da1f477c7d5f7e7c58702ad15266278302f996f 100644 (file)
@@ -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
     }
 
index 30d38e79d11368cf9a6bfd83f27530815fade8fa..d76c482ccca1f515f361ee6e76d76a5e3640044d 100644 (file)
@@ -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;
     }
index 8ded89fd2dee5e80af9d742408550b473e971ddc..e215e52f977f92ad8b280b4ebc8a5d6b1942cb2b 100644 (file)
@@ -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_
 
index 8111999e253e08128d4b4efc4ca8f43bffda17d6..7aee64a749b40ef73f55f2cab47073c36e324395 100644 (file)
@@ -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]);
index 25af69d32f98e5745a688c08b0d2d40949ec48f8..9709376d01c10c3352862aa786e8862e0315b801 100644 (file)
@@ -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]);
             }
 
index 2d295acc8383bb9115e26a11ad290d31f56fa982..67b7935bcba4bf55570b7633d950572890fbe5f2 100644 (file)
@@ -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
           }
 
index b795fbf722fb3b8ef17fe6cd2e917c96eb28fbdf..0b10f1ec01d2697d133e2cf08c7dfd5219c63283 100644 (file)
@@ -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
index 230d232ffa768f0965a749cefb15ae571bd514c0..9cecadf1ee227f733550cac550e913dee7611c7c 100644 (file)
@@ -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
index 88efe7cf8eae96eb6d846a901b112aeabe648b0d..cb55d79c540f5c526af57d6ab149140f5acf0a82 100644 (file)
@@ -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
index 537c63d919f7c43c107e6d79f4c0142c343144b7..f51adad9207abb8d8449070c85a5df980951f140 100644 (file)
@@ -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.
index afd0b9e7df0a5d596b0aa7051eea25fa2b659d14..4713a3858247cd503c6fd36a6ba7c1afd2a9e0f4 100644 (file)
@@ -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).
index 98e83040cd09081254a56a9139392661720df6b4..dc82ed79873e122263f6851880a08135eb4761c2 100644 (file)
@@ -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;
index 606956bd3087fc95e0db0cee529d2a998b614518..85f02b7a9c46861c1554b0166b1704c04e23e085 100644 (file)
@@ -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
 
index 314af23f71dea34b4d7fa30400693e37d9597172..3e9eb161ae7f6157ff4fd94d73c63b4dfde423c6 100644 (file)
@@ -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
index ba3ae4e00ab0ad9b7fc3fafbdf406683e70bdc9b..f34619c1823180321bb7165f0822d57a472e41d5 100644 (file)
@@ -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
index 70f02a5e75c4848349ec6ec5ae935e982edce81b..832c4f5a9a8debae6505c1a36e2a5b4c034c1325 100644 (file)
@@ -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, ">");