]> Kevux Git Server - fll/commitdiff
Progress: control program, adding numerous FLL projects as needed.
authorKevin Day <thekevinday@gmail.com>
Wed, 30 Dec 2020 21:13:29 +0000 (15:13 -0600)
committerKevin Day <thekevinday@gmail.com>
Wed, 30 Dec 2020 21:46:40 +0000 (15:46 -0600)
This focuses primarily on getting control groups working.
There are also some f_account changes, but nothing in the control program used the f_account changes.

82 files changed:
build/level_0/settings
build/level_1/settings
build/level_2/settings
build/monolithic/settings
build/scripts/bootstrap-example.sh
level_0/f_account/c/account-common.h
level_0/f_account/c/account.c
level_0/f_account/c/account.h
level_0/f_account/c/private-account.c [new file with mode: 0644]
level_0/f_account/c/private-account.h [new file with mode: 0644]
level_0/f_account/data/build/settings
level_0/f_capability/c/capability-common.h
level_0/f_control_group/c/control_group-common.h [new file with mode: 0644]
level_0/f_control_group/c/control_group.h [new file with mode: 0644]
level_0/f_control_group/data/build/defines [new file with mode: 0644]
level_0/f_control_group/data/build/dependencies [new file with mode: 0644]
level_0/f_control_group/data/build/settings [new file with mode: 0644]
level_0/f_file/c/file-common.h
level_0/f_status/c/status.h
level_0/f_string/c/string_dynamic.h
level_0/f_string/c/string_map.h
level_1/fl_control_group/c/control_group.c [new file with mode: 0644]
level_1/fl_control_group/c/control_group.h [new file with mode: 0644]
level_1/fl_control_group/data/build/defines [new file with mode: 0644]
level_1/fl_control_group/data/build/dependencies [new file with mode: 0644]
level_1/fl_control_group/data/build/settings [new file with mode: 0644]
level_1/fl_directory/c/directory.h
level_1/fl_execute/c/execute-common.h
level_1/fl_execute/c/execute.h
level_1/fl_execute/data/build/settings
level_1/fl_status/c/status.c
level_1/fl_status/c/status.h
level_2/fll_control_group/c/control_group.c [new file with mode: 0644]
level_2/fll_control_group/c/control_group.h [new file with mode: 0644]
level_2/fll_control_group/data/build/defines [new file with mode: 0644]
level_2/fll_control_group/data/build/dependencies [new file with mode: 0644]
level_2/fll_control_group/data/build/settings [new file with mode: 0644]
level_2/fll_error/c/error-common.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_status/c/status.c
level_3/byte_dump/c/byte_dump.h
level_3/control/c/control.h
level_3/controller/c/controller.h
level_3/controller/c/private-common.h
level_3/controller/c/private-rule.c
level_3/controller/c/private-rule.h
level_3/controller/data/build/dependencies
level_3/controller/data/build/settings
level_3/controller/data/settings/example/entries/test.entry
level_3/controller/data/settings/example/rules/command/multiple.rule
level_3/controller/data/settings/example/rules/script/fail.rule
level_3/controller/data/settings/example/rules/script/require_me.rule [new file with mode: 0644]
level_3/controller/data/settings/example/rules/script/succeed.rule
level_3/controller/documents/rule.txt
level_3/controller/specifications/rule.txt
level_3/fake/c/fake.h
level_3/fake/c/private-fake.c
level_3/fake/c/private-make.c
level_3/fake/data/build/dependencies
level_3/fake/data/build/settings
level_3/firewall/c/firewall.h
level_3/firewall/data/build/dependencies
level_3/firewall/data/build/settings
level_3/fss_basic_list_read/c/fss_basic_list_read.h
level_3/fss_basic_list_write/c/fss_basic_list_write.h
level_3/fss_basic_read/c/fss_basic_read.h
level_3/fss_basic_write/c/fss_basic_write.h
level_3/fss_embedded_list_read/c/fss_embedded_list_read.h
level_3/fss_embedded_list_write/c/fss_embedded_list_write.h
level_3/fss_extended_list_read/c/fss_extended_list_read.h
level_3/fss_extended_list_write/c/fss_extended_list_write.h
level_3/fss_extended_read/c/fss_extended_read.h
level_3/fss_extended_write/c/fss_extended_write.h
level_3/fss_status_code/c/fss_status_code.h
level_3/iki_read/c/iki_read.h
level_3/iki_write/c/iki_write.h
level_3/init/c/init.h
level_3/status_code/c/status_code.h

index a59c5a705fe2a3b7313e6edb43e7fade040aecd9..210815ae83374da9444918ee1ef4cb2e9f1ba72b 100644 (file)
@@ -20,9 +20,9 @@ build_indexer ar
 build_language c
 build_libraries -lc -lcap
 build_libraries-level
-build_sources_library 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 process.c serialize.c private-serialize.c signal.c socket.c utf.c private-utf.c
+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 process.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 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 process.h process-common.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 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 process.h process-common.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 a7d23f075e875c917d3ba3625d97f91afca650cc..94f4a28ff9d8f433e59822832ba9ed6f5dece8dc 100644 (file)
@@ -20,9 +20,9 @@ build_indexer ar
 build_language c
 build_libraries -lc
 build_libraries-level -lfll_0
-build_sources_library color.c console.c conversion.c directory.c private-directory.c environment.c private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c iki.c print.c private-print.c status.c string.c private-string.c type.c private-type.c utf.c private-utf.c utf_file.c private-utf_file.c
+build_sources_library color.c console.c control_group.c conversion.c directory.c private-directory.c environment.c private-fss.c fss_basic.c fss_basic_list.c fss_embedded_list.c fss_extended.c fss_extended_list.c iki.c print.c private-print.c status.c string.c private-string.c type.c private-type.c utf.c private-utf.c utf_file.c private-utf_file.c
 build_sources_program
-build_sources_headers color.h console.h conversion.h directory.h environment.h execute.h execute-common.h fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_status.h iki.h print.h status.h string.h type.h utf.h utf_file.h
+build_sources_headers color.h console.h control_group.h conversion.h directory.h environment.h execute.h execute-common.h fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_status.h iki.h print.h status.h string.h type.h utf.h utf_file.h
 build_sources_script
 build_sources_setting
 build_script yes
index d63d28aa2c5e4470be31a7b0e1e3883fbe8132ce..4ba2922fc1bfd58aaf4232263e55ee8959af1abe 100644 (file)
@@ -20,9 +20,9 @@ build_indexer ar
 build_language c
 build_libraries -lc -lcap
 build_libraries-level -lfll_1 -lfll_0
-build_sources_library 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
+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
 build_sources_program
-build_sources_headers environment.h error.h error-common.h execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_status.h iki.h path.h program.h status.h
+build_sources_headers control_group.h environment.h error.h error-common.h execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_embedded_list.h fss_extended.h fss_extended_list.h fss_status.h iki.h path.h program.h status.h
 build_sources_script
 build_sources_setting
 build_script yes
index 44bb2c4c4c6357e5760624a64297381cbe0b4221..093c43e7b5fcf232be8e8c5af88156abdc2ac89f 100644 (file)
@@ -20,9 +20,9 @@ build_indexer ar
 build_language c
 build_libraries -lc -lcap
 build_libraries-monolithic
-build_sources_library level_0/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/process.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/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/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 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/process.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/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/process.h level_0/process-common.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/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/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 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/process.h level_0/process-common.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 7d5593dbfa3b25596a42c2e63240ef0fd90ad25f..4a578e4a7db0190b5e49529b3641c297ff169cb7 100644 (file)
@@ -41,7 +41,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_conversion f_directory f_environment f_execute f_file f_fss f_iki f_path f_pipe f_print f_process f_serialize f_signal f_socket fl_color fl_console 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_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_path f_pipe f_print f_process f_serialize f_signal f_socket 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 625e1c13e87942f0ad5c8ecb4881f402c5a16e8f..817623464185421c7cf251f39f64203af65db0c9 100644 (file)
@@ -27,6 +27,178 @@ extern "C" {
   #define f_account_pwd_length_fallback_second 32767
 #endif // _di_f_account_defines_
 
+/**
+ * Provide a complete standard password account structure.
+ *
+ * id_user:  The user ID.
+ * id_group: The group ID.
+ * home:     The user's home directory.
+ * label:    The user's display name (gecos).
+ * name:     The user's account name.
+ * password: The user's password.
+ * shell:    The user's shell program.
+ */
+#ifndef _di_f_account_t_
+  typedef struct {
+    uid_t id_user;
+    gid_t id_group;
+
+    f_string_dynamic_t home;
+    f_string_dynamic_t label;
+    f_string_dynamic_t name;
+    f_string_dynamic_t password;
+    f_string_dynamic_t shell;
+  } f_account_t;
+
+  #define f_account_t_initialize { 0, 0, f_string_dynamic_t_initialize, f_string_dynamic_t_initialize, f_string_dynamic_t_initialize, f_string_dynamic_t_initialize, f_string_dynamic_t_initialize }
+
+  #define f_macro_account_t_clear(account) \
+    account.id_user = 0; \
+    account.id_group = 0; \
+    f_macro_account_t_clear(account.home); \
+    f_macro_account_t_clear(account.label); \
+    f_macro_account_t_clear(account.name); \
+    f_macro_account_t_clear(account.password); \
+    f_macro_account_t_clear(account.shell);
+
+  #define f_macro_account_t_delete(status, account) \
+    f_macro_string_dynamic_t_delete(status, account.home); \
+    if (F_status_is_error_not(status)) f_macro_string_dynamic_t_delete(status, account.label); \
+    if (F_status_is_error_not(status)) f_macro_string_dynamic_t_delete(status, account.name); \
+    if (F_status_is_error_not(status)) f_macro_string_dynamic_t_delete(status, account.password); \
+    if (F_status_is_error_not(status)) f_macro_string_dynamic_t_delete(status, account.shell);
+
+  #define f_macro_account_t_destroy(status, account) \
+    f_macro_string_dynamic_t_destroy(status, account.home); \
+    if (F_status_is_error_not(status)) f_macro_string_dynamic_t_destroy(status, account.label); \
+    if (F_status_is_error_not(status)) f_macro_string_dynamic_t_destroy(status, account.name); \
+    if (F_status_is_error_not(status)) f_macro_string_dynamic_t_destroy(status, account.password); \
+    if (F_status_is_error_not(status)) f_macro_string_dynamic_t_destroy(status, account.shell);
+
+  #define f_macro_account_t_delete_simple(account) \
+    f_macro_string_dynamic_t_delete_simple(account.home); \
+    f_macro_string_dynamic_t_delete_simple(account.label); \
+    f_macro_string_dynamic_t_delete_simple(account.name); \
+    f_macro_string_dynamic_t_delete_simple(account.password); \
+    f_macro_string_dynamic_t_delete_simple(account.shell);
+
+  #define f_macro_account_t_destroy_simple(account) \
+    f_macro_string_dynamic_t_destroy_simple(account.home); \
+    f_macro_string_dynamic_t_destroy_simple(account.label); \
+    f_macro_string_dynamic_t_destroy_simple(account.name); \
+    f_macro_string_dynamic_t_destroy_simple(account.password); \
+    f_macro_string_dynamic_t_destroy_simple(account.shell);
+#endif // _di_f_account_t_
+
+/**
+ * An array of accounts.
+ *
+ * array: the array of accounts.
+ * size: total amount of space available.
+ * used: total number of space used.
+ */
+#ifndef _di_f_accounts_t_
+  typedef struct {
+    f_account_t *array;
+
+    f_array_length_t size;
+    f_array_length_t used;
+  } f_accounts_t;
+
+  #define f_accounts_t_initialize { 0, 0, 0 }
+
+  #define f_macro_accounts_t_clear(accounts) \
+    accounts.array = 0; \
+    accounts.size = 0; \
+    accounts.used = 0;
+
+  #define f_macro_accounts_new(status, accounts, length) \
+    f_macro_accounts_clear(accounts) \
+    status = f_memory_new((void **) & accounts.array, sizeof(f_account_t), length); \
+    if (status == F_none) { \
+      accounts.size = length; \
+      accounts.used = 0; \
+    }
+
+  #define f_macro_string_accounts_t_delete(status, accounts) \
+    status = F_none; \
+    accounts.used = accounts.size; \
+    while (accounts.used) { \
+      accounts.used--; \
+      f_macro_account_t_delete(status, accounts.array[accounts.used]); \
+      if (status != F_none) break; \
+    } \
+    if (status == F_none) status = f_memory_delete((void **) & accounts.array, sizeof(f_account_t), accounts.size); \
+    if (status == F_none) accounts.size = 0;
+
+  #define f_macro_string_accounts_t_destroy(status, accounts) \
+    status = F_none; \
+    accounts.used = accounts.size; \
+    while (accounts.used) { \
+      accounts.used--; \
+      f_macro_account_t_destroy(status, accounts.array[accounts.used]); \
+      if (status != F_none) break; \
+    } \
+    if (status == F_none) status = f_memory_destroy((void **) & accounts.array, sizeof(f_account_t), accounts.size); \
+    if (status == F_none) accounts.size = 0;
+
+  #define f_macro_string_accounts_t_delete_simple(accounts) \
+    accounts.used = accounts.size; \
+    while (accounts.used) { \
+      accounts.used--; \
+      f_macro_account_t_delete_simple(accounts.array[accounts.used]); \
+    } \
+    f_memory_delete((void **) & accounts.array, sizeof(f_account_t), accounts.size); \
+    accounts.size = 0;
+
+  #define f_macro_string_accounts_t_destroy_simple(accounts) \
+    accounts.used = accounts.size; \
+    while (accounts.used > 0) { \
+      accounts.used--; \
+      f_macro_account_t_destroy_simple(accounts.array[accounts.used]); \
+    } \
+    f_memory_destroy((void **) & accounts.array, sizeof(f_account_t), accounts.size); \
+    accounts.size = 0;
+
+  #define f_macro_string_accounts_t_resize(status, accounts, new_length) \
+    status = F_none; \
+    if (new_length < accounts.size) { \
+      for (f_array_length_t _macro__i = accounts.size - new_length; _macro__i < accounts.size; _macro__i++) { \
+        f_macro_account_t_delete(status, accounts.array[_macro__i]); \
+        if (status != F_none) break; \
+      } \
+    } \
+    if (status == F_none) status = f_memory_resize((void **) & accounts.array, sizeof(f_account_t), accounts.size, new_length); \
+    if (status == F_none) { \
+      if (new_length > accounts.size) { \
+        for (f_array_length_t _macro__i = accounts.size; _macro__i < new_length; _macro__i++) { \
+          memset(&accounts.array[_macro__i], 0, sizeof(f_account_t)); \
+        } \
+      } \
+      accounts.size = new_length; \
+      if (accounts.used > accounts.size) accounts.used = new_length; \
+    }
+
+  #define f_macro_string_accounts_t_adjust(status, accounts, new_length) \
+    status = F_none; \
+    if (new_length < accounts.size) { \
+      for (f_array_length_t _macro__i = accounts.size - new_length; _macro__i < accounts.size; _macro__i++) { \
+        f_macro_account_t_destroy(status, accounts.array[_macro__i], f_account_t); \
+        if (status != F_none) break; \
+      } \
+    } \
+    if (status == F_none) status = f_memory_adjust((void **) & accounts.array, sizeof(f_account_t), accounts.size, new_length); \
+    if (status == F_none) { \
+      if (new_length > accounts.size) { \
+        for (f_array_length_t _macro__i = accounts.size; _macro__i < new_length; _macro__i++) { \
+          memset(&accounts.array[_macro__i], 0, sizeof(f_account_t)); \
+        } \
+      } \
+      accounts.size = new_length; \
+      if (accounts.used > accounts.size) accounts.used = new_length; \
+    }
+#endif // _di_f_accounts_t_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 86149d1eba50073000c07c09d288a68d3edbaa2c..020bf5c66666e41ef89c4efa276cca23928a0569 100644 (file)
@@ -1,9 +1,176 @@
 #include "account.h"
+#include "private-account.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#ifndef _di_f_account_by_name_
+  f_return_status f_account_by_name(const f_string_t name, f_account_t *account) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!account) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    account->id_user = 0;
+    account->id_group = 0;
+    account->home.used = 0;
+    account->label.used = 0;
+    account->name.used = 0;
+    account->password.used = 0;
+    account->shell.used = 0;
+
+    f_status_t status = F_none;
+
+    const size_t length_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+
+    // note: pointer seems pointless except that it is used to determine if the name was found.
+    struct passwd password;
+    struct passwd *pointer = 0;
+
+    size_t length = length_max;
+
+    {
+      if (length == -1) {
+        length = f_account_pwd_length_fallback_first;
+      }
+
+      // must be set to 0 to avoid problems due to the design of getpwnam()/getpwnam_r().
+      errno = 0;
+
+      char buffer[length];
+      const int result = getpwnam_r(name, &password, buffer, length, &pointer);
+
+      if (result) {
+        if (errno == EINTR) return F_status_set_error(F_interrupt);
+        if (errno == EIO) return F_status_set_error(F_input_output);
+        if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max);
+        if (errno == ENFILE) return F_status_set_error(F_file_open_max);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+
+        if (errno == ERANGE) {
+          if (length_max > 0) return F_status_set_error(F_buffer_too_small);
+        }
+        else {
+          return F_status_set_error(F_failure);
+        }
+      }
+      else {
+        if (!pointer) {
+          return F_exist_not;
+        }
+
+        return private_f_account_from_passwd(password, length, account);
+      }
+    }
+
+    length = f_account_pwd_length_fallback_second;
+
+    char buffer[f_account_pwd_length_fallback_second];
+
+    const int result = getpwnam_r(name, &password, buffer, length, &pointer);
+
+    if (result) {
+      if (errno == EINTR) return F_status_set_error(F_interrupt);
+      if (errno == EIO) return F_status_set_error(F_input_output);
+      if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max);
+      if (errno == ENFILE) return F_status_set_error(F_file_open_max);
+      if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+      if (errno == ERANGE) return F_status_set_error(F_buffer_too_small);
+
+      return F_status_set_error(F_failure);
+    }
+
+    if (!pointer) {
+      return F_exist_not;
+    }
+
+    return private_f_account_from_passwd(password, length, account);
+  }
+#endif // _di_f_account_by_name_
+
+#ifndef _di_f_account_by_id_
+  f_return_status f_account_by_id(const uid_t id, f_account_t *account) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!account) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    account->id_user = 0;
+    account->id_group = 0;
+    account->home.used = 0;
+    account->label.used = 0;
+    account->name.used = 0;
+    account->password.used = 0;
+    account->shell.used = 0;
+
+    f_status_t status = F_none;
+
+    const size_t length_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+
+    // note: pointer seems pointless except that it is used to determine if the name was found.
+    struct passwd password;
+    struct passwd *pointer = 0;
+
+    size_t length = length_max;
+
+    {
+      if (length == -1) {
+        length = f_account_pwd_length_fallback_first;
+      }
+
+      // must be set to 0 to avoid problems due to the design of getpwuid()/getpwuid_r().
+      errno = 0;
+
+      char buffer[length];
+      const int result = getpwuid_r(id, &password, buffer, length, &pointer);
+
+      if (result) {
+        if (errno == EINTR) return F_status_set_error(F_interrupt);
+        if (errno == EIO) return F_status_set_error(F_input_output);
+        if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max);
+        if (errno == ENFILE) return F_status_set_error(F_file_open_max);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+
+        if (errno == ERANGE) {
+          if (length_max > 0) return F_status_set_error(F_buffer_too_small);
+        }
+        else {
+          return F_status_set_error(F_failure);
+        }
+      }
+      else {
+        if (!pointer) {
+          return F_exist_not;
+        }
+
+        return private_f_account_from_passwd(password, length, account);
+      }
+    }
+
+    length = f_account_pwd_length_fallback_second;
+
+    char buffer[f_account_pwd_length_fallback_second];
+
+    const int result = getpwuid_r(id, &password, buffer, length, &pointer);
+
+    if (result) {
+      if (errno == EINTR) return F_status_set_error(F_interrupt);
+      if (errno == EIO) return F_status_set_error(F_input_output);
+      if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max);
+      if (errno == ENFILE) return F_status_set_error(F_file_open_max);
+      if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+      if (errno == ERANGE) return F_status_set_error(F_buffer_too_small);
+
+      return F_status_set_error(F_failure);
+    }
+
+    if (!pointer) {
+      return F_exist_not;
+    }
+
+    return private_f_account_from_passwd(password, length, account);
+  }
+#endif // _di_f_account_by_id_
+
 #ifndef _di_f_account_id_group_by_name_
   f_return_status f_account_id_group_by_name(const f_string_t name, gid_t *id) {
     #ifndef _di_level_0_parameter_checking_
@@ -162,6 +329,103 @@ extern "C" {
   }
 #endif // _di_f_account_id_user_by_name_
 
+#ifndef _di_f_account_name_user_by_id_
+  f_return_status f_account_name_user_by_id(const uid_t id, f_string_dynamic_t *name) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!name) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    name->used = 0;
+
+    f_status_t status = F_none;
+
+    const size_t length_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+
+    // note: pointer seems pointless except that it is used to determine if the name was found.
+    struct passwd password;
+    struct passwd *pointer = 0;
+
+    size_t length = length_max + 1;
+
+    {
+      if (length == -1) {
+        length = f_account_pwd_length_fallback_first;
+      }
+
+      // must be set to 0 to avoid problems due to the design of getpwuid()/getpwuid_r().
+      errno = 0;
+
+      char buffer[length];
+      const int result = getpwuid_r(id, &password, buffer, length, &pointer);
+
+      if (result) {
+        if (errno == EINTR) return F_status_set_error(F_interrupt);
+        if (errno == EIO) return F_status_set_error(F_input_output);
+        if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max);
+        if (errno == ENFILE) return F_status_set_error(F_file_open_max);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+
+        if (errno == ERANGE) {
+          if (length_max > 0) return F_status_set_error(F_buffer_too_small);
+        }
+        else {
+          return F_status_set_error(F_failure);
+        }
+      }
+      else {
+        if (!pointer) {
+          return F_exist_not;
+        }
+
+        const f_string_length_t name_length = strnlen(password.pw_name, length);
+
+        f_macro_string_dynamic_t_resize(status, (*name), name_length + 1);
+        if (F_status_is_error(status)) return status;
+
+        memcpy(name->string, password.pw_name, name_length);
+
+        name->string[name_length] = 0;
+        name->used = name_length;
+
+        return F_none;
+      }
+    }
+
+    length = f_account_pwd_length_fallback_second;
+
+    char buffer[f_account_pwd_length_fallback_second];
+
+    const int result = getpwuid_r(id, &password, buffer, length, &pointer);
+
+    if (result) {
+      if (errno == EINTR) return F_status_set_error(F_interrupt);
+      if (errno == EIO) return F_status_set_error(F_input_output);
+      if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max);
+      if (errno == ENFILE) return F_status_set_error(F_file_open_max);
+      if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+      if (errno == ERANGE) return F_status_set_error(F_buffer_too_small);
+
+      return F_status_set_error(F_failure);
+    }
+
+    if (!pointer) {
+      return F_exist_not;
+    }
+
+    const f_string_length_t name_length = strnlen(password.pw_name, length);
+
+    f_macro_string_dynamic_t_resize(status, (*name), name_length + 1);
+    if (F_status_is_error(status)) return status;
+
+    memcpy(name->string, password.pw_name, name_length);
+
+    name->string[name_length] = 0;
+    name->used = name_length;
+
+    return F_none;
+  }
+#endif // _di_f_account_name_user_by_id_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 9be5caad249f8a00e21f03ef65bdc132b2af025d..853e854cfdf0a303e3cfa501bffced2575bdc517 100644 (file)
@@ -7,8 +7,8 @@
  *
  * Provides account related functionality (users, groups, roles, etc..).
  *
- * @todo POSIX as of POSIX.1-2001, at least getpwnam() does not call "not found" an error.
- *       For now, using getpwnam_r() in place of getpwnam() (and similar) seems the safest way to avoid this bad design.
+ * POSIX as of POSIX.1-2001, at least getpwnam() does not call "not found" an error.
+ * This uses getpwnam_r() in place of getpwnam() (and similar) as the safest way to avoid this bad design.
  */
 #ifndef _F_account_h
 #define _F_account_h
@@ -33,6 +33,61 @@ extern "C" {
 #endif
 
 /**
+ * Get the user account by the user name.
+ *
+ * @param name
+ *   The user name.
+ *   The name must be NULL terminated.
+ * @param account
+ *   This is replaced with by the account information.
+ *   All strings will be NULL terminated.
+ *
+ * @return
+ *   F_none on success.
+ *   F_buffer_too_small (with error bit) if the buffer is too small to store the account data.
+ *   F_exist_non if no user by that name exists.
+ *   F_file_descriptor_max (with error bit) if max file descriptors was reached.
+ *   F_file_open_max (with error bit) too many open files.
+ *   F_input_output (with error bit) if an I/O error occurred.
+ *   F_interrupt (with error bit) when program received an interrupt signal, halting operation.
+ *   F_memory_not (with error bit) if out of memory.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_failure (with error bit) on any other error.
+ *
+ * @see getpwnam_r()
+ */
+#ifndef _di_f_account_by_name_
+  extern f_return_status f_account_by_name(const f_string_t name, f_account_t *account);
+#endif // _di_f_account_by_name_
+
+/**
+ * Get the user account by the user id.
+ *
+ * @param id
+ *   The id of the user.
+ * @param account
+ *   This is replaced with by the account information.
+ *   All strings will be NULL terminated.
+ *
+ * @return
+ *   F_none on success.
+ *   F_buffer_too_small (with error bit) if the buffer is too small to store the account data.
+ *   F_exist_non if no user by that name exists.
+ *   F_file_descriptor_max (with error bit) if max file descriptors was reached.
+ *   F_file_open_max (with error bit) too many open files.
+ *   F_input_output (with error bit) if an I/O error occurred.
+ *   F_interrupt (with error bit) when program received an interrupt signal, halting operation.
+ *   F_memory_not (with error bit) if out of memory.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_failure (with error bit) on any other error.
+ *
+ * @see getpwuid_r()
+ */
+#ifndef _di_f_account_by_id_
+  extern f_return_status f_account_by_id(const uid_t id, f_account_t *account);
+#endif // _di_f_account_by_id_
+
+/**
  * Get the group account id by the group name.
  *
  * @param name
@@ -86,6 +141,33 @@ extern "C" {
   extern f_return_status f_account_id_user_by_name(const f_string_t name, uid_t *id);
 #endif // _di_f_account_id_user_by_name_
 
+/**
+ * Get the user account name by the user id.
+ *
+ * @param id
+ *   The id of the user.
+ * @param name
+ *   This is replaced with by the user name.
+ *   The name will be NULL terminated.
+ *
+ * @return
+ *   F_none on success.
+ *   F_buffer_too_small (with error bit) if the buffer is too small to store the account data.
+ *   F_exist_non if no user by that name exists.
+ *   F_file_descriptor_max (with error bit) if max file descriptors was reached.
+ *   F_file_open_max (with error bit) too many open files.
+ *   F_input_output (with error bit) if an I/O error occurred.
+ *   F_interrupt (with error bit) when program received an interrupt signal, halting operation.
+ *   F_memory_not (with error bit) if out of memory.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_failure (with error bit) on any other error.
+ *
+ * @see getpwuid_r()
+ */
+#ifndef _di_f_account_name_user_by_id_
+  extern f_return_status f_account_name_user_by_id(const uid_t id, f_string_dynamic_t *name);
+#endif // _di_f_account_name_user_by_id_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/level_0/f_account/c/private-account.c b/level_0/f_account/c/private-account.c
new file mode 100644 (file)
index 0000000..f79bd72
--- /dev/null
@@ -0,0 +1,83 @@
+#include "account.h"
+#include "private-account.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_di_f_account_by_name_) || !defined(_di_f_account_by_id_)
+  f_return_status private_f_account_from_passwd(const struct passwd password, const f_string_length_t password_length, f_account_t *account) {
+    f_status_t status = F_none;
+
+
+    // Account UID and GID.
+    account->id_user = password.pw_uid;
+    account->id_group = password.pw_gid;
+
+
+    // account home directory.
+    f_string_length_t string_length = strnlen(password.pw_dir, password_length);
+
+    f_macro_string_dynamic_t_resize(status, account->home, string_length + 1);
+    if (F_status_is_error(status)) return status;
+
+    memcpy(account->home.string, password.pw_dir, string_length);
+
+    account->home.string[string_length] = 0;
+    account->home.used = string_length;
+
+
+    // account label (gecos).
+    string_length = strnlen(password.pw_gecos, password_length);
+
+    f_macro_string_dynamic_t_resize(status, account->label, string_length + 1);
+    if (F_status_is_error(status)) return status;
+
+    memcpy(account->label.string, password.pw_gecos, string_length);
+
+    account->label.string[string_length] = 0;
+    account->label.used = string_length;
+
+
+    // account name.
+    string_length = strnlen(password.pw_name, password_length);
+
+    f_macro_string_dynamic_t_resize(status, account->name, string_length + 1);
+    if (F_status_is_error(status)) return status;
+
+    memcpy(account->name.string, password.pw_name, string_length);
+
+    account->name.string[string_length] = 0;
+    account->name.used = string_length;
+
+
+    // account password directory.
+    string_length = strnlen(password.pw_passwd, password_length);
+
+    f_macro_string_dynamic_t_resize(status, account->password, string_length + 1);
+    if (F_status_is_error(status)) return status;
+
+    memcpy(account->password.string, password.pw_passwd, string_length);
+
+    account->password.string[string_length] = 0;
+    account->password.used = string_length;
+
+
+    // account shell directory.
+    string_length = strnlen(password.pw_shell, password_length);
+
+    f_macro_string_dynamic_t_resize(status, account->shell, string_length + 1);
+    if (F_status_is_error(status)) return status;
+
+    memcpy(account->shell.string, password.pw_shell, string_length);
+
+    account->shell.string[string_length] = 0;
+    account->shell.used = string_length;
+
+    return F_none;
+  }
+#endif // !defined(_di_f_account_by_name_) || !defined(_di_f_account_by_id_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_account/c/private-account.h b/level_0/f_account/c/private-account.h
new file mode 100644 (file)
index 0000000..9cdab9c
--- /dev/null
@@ -0,0 +1,49 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Account
+ * 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_account_h
+#define _PRIVATE_F_account_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Private helper for converting an entire "struct passwd" to a complete f_account_t.
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param passwd
+ *   The password structure.
+ * @param passwd_length
+ *   The length of the password structure buffer.
+ * @param account
+ *   This is replaced with by the account information.
+ *   All strings will be NULL terminated.
+ *   This assumes that all strings in account have their used set to the desired length, such as 0.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Errors (with error bit) from f_macro_string_dynamic_t_resize().
+ *
+ * @see f_account_by_name()
+ * @see f_account_by_id()
+ * @see f_macro_string_dynamic_t_resize()
+ */
+#if !defined(_di_f_account_by_name_) || !defined(_di_f_account_by_id_)
+  extern f_return_status private_f_account_from_passwd(const struct passwd password, const f_string_length_t password_length, f_account_t *account) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_f_account_by_name_) || !defined(_di_f_account_by_id_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_F_account_h
index 8813f2dd2ccfd110623f2e453714507c7ead1a8e..eacbe7f020546efc9eb38f51448e8282316b17b7 100644 (file)
@@ -20,7 +20,7 @@ build_indexer ar
 build_language c
 build_libraries -lc
 build_libraries-individual -lf_memory
-build_sources_library account.c
+build_sources_library account.c private-account.c
 build_sources_program
 build_sources_headers account.h account-common.h
 build_sources_script
index 599ff22505bee7acb5fee768aff3a32ca3d91a87..0af5f38a0dfe44c28f5bcc165612528e236c8739 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Defines common data to be used for/by capability related functionality.
  *
- * This is auto-included by account.h and should not need to be explicitly included.
+ * This is auto-included by capability.h and should not need to be explicitly included.
  */
 #ifndef _F_capability_common_h
 #define _F_capability_common_h
diff --git a/level_0/f_control_group/c/control_group-common.h b/level_0/f_control_group/c/control_group-common.h
new file mode 100644 (file)
index 0000000..95f0f6d
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Control Group
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * Defines common data to be used for/by control group (cgroup) related functionality.
+ *
+ * This is auto-included by control.h and should not need to be explicitly included.
+ */
+#ifndef _F_control_group_common_h
+#define _F_control_group_common_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The defines for control groups.
+ */
+#ifndef _di_fl_control_group_defines_
+  #define f_control_group_path_system_default "sys/fs/cgroup/"
+  #define f_control_group_path_system_prefix  "/"
+  #define f_control_group_path_system_suffix   "/cgroup.procs"
+
+  #define f_control_group_path_system_default_length 14
+  #define f_control_group_path_system_prefix_length  1
+  #define f_control_group_path_system_suffix_length  13
+
+  #define f_control_group_pid_length_max 64
+
+  const static f_string_t f_control_group_path_system_default_s = f_control_group_path_system_default;
+  const static f_string_t f_control_group_path_system_prefix_s = f_control_group_path_system_prefix;
+  const static f_string_t f_control_group_path_system_suffix_s = f_control_group_path_system_suffix;
+#endif // _di_fl_control_group_defines_
+
+/**
+ * Provide a structure for associating some process with one or more control groups (cgroups).
+ *
+ * as_new: If TRUE then the control group is to be unshared, and FALSE the control group is not to be unshared.
+ * path:   The sysfs path, must have the trailing slash (such as "/sys/fs/cgroup/").
+ * groups: An array of control groups, relative to the sysfs path (such as "memory/example").
+ */
+#ifndef _di_f_control_group_t_
+  typedef struct {
+    bool as_new;
+
+    f_string_dynamic_t path;
+    f_string_dynamics_t groups;
+  } f_control_group_t;
+
+  #define f_control_group_t_initialize { F_false, f_string_dynamic_t_initialize, f_string_dynamics_t_initialize }
+
+  #define f_macro_control_group_t_clear(control) \
+    control.as_new = F_false; \
+    f_macro_string_dynamic_t_clear(control.path); \
+    f_macro_string_dynamics_t_clear(control.groups);
+
+  #define f_macro_control_group_t_delete(status, control) \
+    f_macro_string_dynamic_t_delete(status, control.path); \
+    if (F_status_is_error_not(status)) f_macro_string_dynamics_t_delete(status, control.groups);
+
+  #define f_macro_control_group_t_destroy(status, control) \
+    f_macro_string_dynamic_t_destroy(status, control.path); \
+    if (F_status_is_error_not(status)) f_macro_string_dynamics_t_destroy(status, control.groups);
+
+  #define f_macro_control_group_t_delete_simple(control) \
+    f_macro_string_dynamic_t_delete_simple(control.path); \
+    f_macro_string_dynamics_t_delete_simple(control.groups);
+
+  #define f_macro_control_group_t_destroy_simple(control) \
+    f_macro_string_dynamic_t_destroy_simple(control.path); \
+    f_macro_string_dynamics_t_destroy_simple(control.groups);
+#endif // _di_f_control_group_t_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _F_control_group_common_h
diff --git a/level_0/f_control_group/c/control_group.h b/level_0/f_control_group/c/control_group.h
new file mode 100644 (file)
index 0000000..100242b
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * FLL - Level 1
+ *
+ * Project: Control Group
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * Provides control group (cgroup) related functionality.
+ *
+ * It appears that the control group, as documented in the Linux kernel, is changed via the sysfs instead of system calls.
+ * If there are system calls to set the control group for a given process then this will need to be updated to utilize that.
+ * Until then, this is an implementation that helps facilitate writing to the sysfs filesystem for adding a process to a particular control group.
+ *
+ * This is intended to be used with Control Groups (cgroups) Version 2.
+ */
+#ifndef _F_control_group_h
+#define _F_control_group_h
+
+// libc includes
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+
+// fll-1 control includes
+#include <level_0/control_group-common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _F_control_group_h
diff --git a/level_0/f_control_group/data/build/defines b/level_0/f_control_group/data/build/defines
new file mode 100644 (file)
index 0000000..4f13080
--- /dev/null
@@ -0,0 +1 @@
+# fss-0000
diff --git a/level_0/f_control_group/data/build/dependencies b/level_0/f_control_group/data/build/dependencies
new file mode 100644 (file)
index 0000000..d798245
--- /dev/null
@@ -0,0 +1,6 @@
+# fss-0000
+
+f_type
+f_status
+f_memory
+f_string
diff --git a/level_0/f_control_group/data/build/settings b/level_0/f_control_group/data/build/settings
new file mode 100644 (file)
index 0000000..48fec22
--- /dev/null
@@ -0,0 +1,55 @@
+# fss-0001
+
+project_name f_control_group
+
+version_major 0
+version_minor 5
+version_micro 2
+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
+build_sources_program
+build_sources_headers control_group.h control_group-common.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+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 4aece7b5aa3d8de1a3a18c043dd62af7690941a0..5350e5db442b94a9df5fbd8628961ed587bce0eb 100644 (file)
@@ -116,7 +116,8 @@ extern "C" {
 
   #define f_file_t_initialize { 0, -1, f_file_flag_read_only, f_file_default_read_size, f_file_default_write_size }
 
-  #define f_macro_file_t_initialize(stream, id, flag) { stream, id, flag, f_file_default_read_size, f_file_default_write_size }
+  #define f_macro_file_t_initialize(stream, id, flag, read_size, write_size) { stream, id, flag, read_size, write_size }
+  #define f_macro_file_t_initialize2(stream, id, flag) { stream, id, flag, f_file_default_read_size, f_file_default_write_size }
 
   #define f_macro_file_t_clear(file) \
     file.stream = 0; \
index a43b0d66fe64c7a796fc324ad0df4bf646b3cbe4..d16afd346edb779cfec0b8e967b2e94e338d2a64 100644 (file)
@@ -163,6 +163,10 @@ extern "C" {
       F_connected_not,
       F_container,
       F_container_not,
+      F_control,
+      F_control_not,
+      F_control_group,
+      F_control_group_not,
       F_critical,
       F_critical_not,
       F_deadlock,
index f950bf2f6274bd8952cf68bb7764f33a3bc6ce5f..9e1b2d428667bb34c061963c5e513c656bcf5fc3 100644 (file)
@@ -146,10 +146,10 @@ extern "C" {
 
   #define f_string_dynamics_t_initialize f_string_statics_t_initialize
 
-  #define f_macro_string_dynamics_clear(dynamics) f_macro_string_statics_t_clear(dynamics)
+  #define f_macro_string_dynamics_t_clear(dynamics) f_macro_string_statics_t_clear(dynamics)
 
   #define f_macro_string_dynamics_new(status, dynamics, length) \
-    f_macro_string_dynamics_clear(dynamics) \
+    f_macro_string_dynamics_t_clear(dynamics) \
     status = f_memory_new((void **) & dynamics.array, sizeof(f_string_dynamic_t), length); \
     if (status == F_none) { \
       dynamics.size = length; \
index aee9fbae13d14c6227b04376dd7125fe1999493c..b2fa00a5c562dd2ef1e61686915a431402ff6b19 100644 (file)
@@ -184,7 +184,7 @@ extern "C" {
 
   #define f_macro_string_map_multi_t_clear(map) \
     f_macro_string_dynamic_t_clear(map.name) \
-    f_macro_string_dynamics_clear(map.value)
+    f_macro_string_dynamics_t_clear(map.value)
 
   #define f_macro_string_map_multi_t_delete(status, map) \
     f_macro_string_dynamic_t_delete(status, map.name) \
diff --git a/level_1/fl_control_group/c/control_group.c b/level_1/fl_control_group/c/control_group.c
new file mode 100644 (file)
index 0000000..c541fa0
--- /dev/null
@@ -0,0 +1,75 @@
+#include "control_group.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fl_control_group_apply_
+  f_return_status fl_control_group_apply(const f_control_group_t control_group, const pid_t id) {
+    #ifndef _di_level_1_parameter_checking_
+      if (!id) return F_status_set_error(F_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (control_group.as_new) {
+      if (unshare(CLONE_NEWCGROUP) < 0) {
+        if (errno == EINVAL) return F_status_set_error(F_parameter);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+        if (errno == ENOSPC) return F_status_set_error(F_space_not);
+        if (errno == EPERM) return F_status_set_error(F_prohibited);
+
+        return F_status_set_error(F_failure);
+      }
+    }
+
+    f_file_t file = f_macro_file_t_initialize2(0, -1, f_file_flag_write_only);
+    f_status_t status = F_none;
+    f_string_length_t length = 0;
+
+    for (f_array_length_t i = 0; i < control_group.groups.used; ++i) {
+
+      if (!control_group.groups.array[i].used) continue;
+
+      length = control_group.path.used + control_group.groups.array[i].used + f_control_group_path_system_suffix_length;
+
+      char path[length + 1];
+
+      if (control_group.path.used) {
+        memcpy(path, control_group.path.string, control_group.path.used);
+      }
+
+      memcpy(path + control_group.path.used, control_group.groups.array[i].string, control_group.groups.array[i].used);
+      memcpy(path + control_group.path.used + f_control_group_path_system_default_length, f_control_group_path_system_suffix, f_control_group_path_system_suffix_length);
+
+      path[length] = 0;
+
+      status = f_file_stream_open(path, 0, &file);
+      if (F_status_is_error(status)) break;
+
+      fprintf(file.stream, "%llu", id);
+      fflush(file.stream);
+
+      f_file_stream_close(F_true, &file);
+      if (F_status_is_error(status)) break;
+    } // for
+
+    if (F_status_is_error(status)) {
+      return status;
+    }
+
+    return F_none;
+  }
+#endif // _di_fl_control_group_apply_
+
+#ifndef _di_fl_control_group_delete_
+  f_return_status fl_control_group_delete(f_control_group_t *control_group) {
+    f_status_t status = F_none;
+
+    f_macro_control_group_t_delete(status, (*control_group));
+
+    return status;
+  }
+#endif // _di_fl_control_group_delete_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_1/fl_control_group/c/control_group.h b/level_1/fl_control_group/c/control_group.h
new file mode 100644 (file)
index 0000000..445bef7
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * FLL - Level 1
+ *
+ * Project: Control Group
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * Provides control group (cgroup) related functionality.
+ *
+ * It appears that the control group, as documented in the Linux kernel, is changed via the sysfs instead of system calls.
+ * If there are system calls to set the control group for a given process then this will need to be updated to utilize that.
+ * Until then, this is an implementation that helps facilitate writing to the sysfs filesystem for adding a process to a particular control group.
+ *
+ * This is intended to be used with Control Groups (cgroups) Version 2.
+ */
+#ifndef _FL_control_group_h
+#define _FL_control_group_h
+
+// include pre-requirements
+#define _GNU_SOURCE
+
+// libc includes
+#include <sched.h>
+#include <stdio.h>
+#include <string.h>
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/control_group.h>
+#include <level_0/file.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Apply the given control groups to the process represented by the PID.
+ *
+ * @param control
+ *   The control group(s) to apply.
+ * @param id
+ *   The PID of the process to apply the control group(s) to.
+ *
+ * @return
+ *   F_none on success.
+ *   F_memory_not (with error bit) if a out of memory.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_prohibited (with error bit) if the current user/process has insufficient privileges to set certain cgroup settings.
+ *   F_space_not (with error bit) if a maximum resource limit is reached and there is not enough space.
+ *   F_failure (with error bit) on any other error.
+ *
+ *   Errors (with error bit) from: f_file_stream_open().
+ *
+ * @see fprintf()
+ * @see fflush()
+ * @see memcpy()
+ * @see unshare()
+ *
+ * @see f_file_stream_close()
+ * @see f_file_stream_open()
+ */
+#ifndef _di_fl_control_group_apply_
+  extern f_return_status fl_control_group_apply(const f_control_group_t control_group, const pid_t id);
+#endif // _di_fl_control_group_apply_
+
+/**
+ * Delete the control group structure.
+ *
+ * @param control_group
+ *   The control group to delete.
+ *
+ * @return
+ *   F_none on success.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_fl_control_group_delete_
+  extern f_return_status fl_control_group_delete(f_control_group_t *control_group);
+#endif // _di_fl_control_group_delete_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _FL_control_group_h
diff --git a/level_1/fl_control_group/data/build/defines b/level_1/fl_control_group/data/build/defines
new file mode 100644 (file)
index 0000000..4f13080
--- /dev/null
@@ -0,0 +1 @@
+# fss-0000
diff --git a/level_1/fl_control_group/data/build/dependencies b/level_1/fl_control_group/data/build/dependencies
new file mode 100644 (file)
index 0000000..1a6851d
--- /dev/null
@@ -0,0 +1,8 @@
+# fss-0000
+
+f_type
+f_status
+f_memory
+f_string
+f_control_group
+f_file
diff --git a/level_1/fl_control_group/data/build/settings b/level_1/fl_control_group/data/build/settings
new file mode 100644 (file)
index 0000000..ca16cd7
--- /dev/null
@@ -0,0 +1,55 @@
+# fss-0001
+
+project_name fl_control_group
+
+version_major 0
+version_minor 5
+version_micro 2
+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_file -lf_memory
+build_sources_library control_group.c
+build_sources_program
+build_sources_headers control_group.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+path_headers level_1
+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 c89197f81bf8d27633895e71889d7b8441dd4d0d..46e55c4968b5e05599b90f926567a0ece9bf53eb 100644 (file)
@@ -83,7 +83,7 @@ extern "C" {
     f_directory_statuss_t *failures;
   } fl_directory_recurse_t;
 
-  #define fl_directory_recurse_t_initialize { fl_directory_recurse_depth_max, f_file_default_read_size, F_false, f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), 0, 0 }
+  #define fl_directory_recurse_t_initialize { fl_directory_recurse_depth_max, f_file_default_read_size, F_false, f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), 0, 0 }
 #endif // _di_fl_directory_recurse_t_
 
 /**
index 455b5b7caf823200afd31d18128d0cea35c636e6..7cc9e2c6f400c29faaf3253200a03d8b802c1e68 100644 (file)
@@ -80,13 +80,13 @@ extern "C" {
  * Control Groups, or cgroups, exist here as a full file path in which the PID of a child process is to be written to.
  * This may change as more is learned about using cgroups, but it is not known if there are any functions available like set_cgroup(..).
  *
- * 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.
- * capability: all of the capabilities to assign the child process to, set to 0 to not use (f_capability_t is a pointer).
- * 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.
- * controls:   an array of cgroups (control groups) to assign the child PID to, set to 0 to not use.
+ * 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.
+ * capability:    all of the capabilities to assign the child process to, set to 0 to not use (f_capability_t is a pointer).
+ * 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.
+ * control_group: an array of cgroups (control groups) to assign the child PID to, set to 0 to not use.
  */
 #ifndef _di_fl_execute_as_t_
   typedef struct {
@@ -97,12 +97,12 @@ extern "C" {
 
     f_int32s_t *id_groups;
     fl_execute_scheduler_t *scheduler;
-    f_string_dynamics_t *controls;
+    f_control_group_t *control_group;
   } fl_execute_as_t;
 
   #define fl_execute_as_t_initialize { 0, 0, 0, 0, 0, 0, 0 }
 
-  #define fl_macro_execute_as_t_initialize(nice, id_user, id_group, capability, id_groups, scheduler, controls) { nice, id_user, id_group, capability, id_groups, scheduler, controls }
+  #define fl_macro_execute_as_t_initialize(nice, id_user, id_group, capability, id_groups, scheduler, control_group) { nice, id_user, id_group, capability, id_groups, scheduler, control_group }
 
   #define fl_execute_as_t_clear(as) \
     as.nice = 0; \
@@ -111,7 +111,7 @@ extern "C" {
     as.capability = 0; \
     as.id_groups = 0; \
     as.scheduler = 0; \
-    as.controls = 0;
+    as.control_group = 0;
 #endif // _di_fl_execute_as_t_
 
 #ifdef __cplusplus
index ab3ba2d5fb7214f079aed122a80804331cf2ade2..9f030053c93c21f1f0cc16a093357969a83fac5a 100644 (file)
@@ -14,6 +14,9 @@
 #ifndef _FL_execute_h
 #define _FL_execute_h
 
+// include pre-requirements
+#define _GNU_SOURCE
+
 // libc includes
 #include <grp.h>
 #include <sched.h>
index a13c57cd2781f9a5b481abda1e815a963810c127..bdcf7176c35fd5cdeafb69cfb95dab50bffe4329 100644 (file)
@@ -29,7 +29,7 @@ build_script yes
 build_shared yes
 build_static yes
 
-path_headers level_0
+path_headers level_1
 path_headers_preserve no
 path_library_script script
 path_library_shared shared
index 0b311ca15ebacf84f0551f8b49994f32fdf7f6ab..aae9382f4e14ed520d04037284a141c490442cb4 100644 (file)
@@ -272,6 +272,18 @@ extern "C" {
         case F_container_not:
           *string = FL_status_string_container_not;
           break;
+        case F_control:
+          *string = FL_status_string_control;
+          break;
+        case F_control_not:
+          *string = FL_status_string_control_not;
+          break;
+        case F_control_group:
+          *string = FL_status_string_control_group;
+          break;
+        case F_control_group_not:
+          *string = FL_status_string_control_group_not;
+          break;
         case F_critical:
           *string = FL_status_string_critical;
           break;
index f11acf6199ade8d2d2deb870975d60b257ae0724..9a3710f328ded65948f692831198b99f22cfa33c 100644 (file)
@@ -163,283 +163,291 @@ extern "C" {
   #endif // _di_F_status_signal_
 
   #ifndef _di_F_status_basic_
-    #define FL_status_string_none             "F_none"
-    #define FL_status_string_absolute         "F_absolute"
-    #define FL_status_string_absolute_not     "F_absolute_not"
-    #define FL_status_string_address          "F_address"
-    #define FL_status_string_address_not      "F_address_not"
-    #define FL_status_string_block            "F_block"
-    #define FL_status_string_block_not        "F_block_not"
-    #define FL_status_string_bound            "F_bound"
-    #define FL_status_string_bound_not        "F_bound_not"
-    #define FL_status_string_capability       "F_capability"
-    #define FL_status_string_capability_not   "F_capability_not"
-    #define FL_status_string_child            "F_child"
-    #define FL_status_string_child_not        "F_child_not"
-    #define FL_status_string_complete         "F_complete"
-    #define FL_status_string_complete_not     "F_complete_not"
-    #define FL_status_string_connected        "F_connected"
-    #define FL_status_string_connected_not    "F_connected_not"
-    #define FL_status_string_container        "F_container"
-    #define FL_status_string_container_not    "F_container_not"
-    #define FL_status_string_critical         "F_critical"
-    #define FL_status_string_critical_not     "F_critical_not"
-    #define FL_status_string_deadlock         "F_deadlock"
-    #define FL_status_string_deadlock_not     "F_deadlock_not"
-    #define FL_status_string_descriptor       "F_descriptor"
-    #define FL_status_string_descriptor_not   "F_descriptor_not"
-    #define FL_status_string_device           "F_device"
-    #define FL_status_string_device_not       "F_device_not"
-    #define FL_status_string_dummy            "F_dummy"
-    #define FL_status_string_dummy_not        "F_dummy_not"
-    #define FL_status_string_encoding         "F_encoding"
-    #define FL_status_string_encoding_not     "F_encoding_not"
-    #define FL_status_string_eof              "F_eof"
-    #define FL_status_string_eof_not          "F_eof_not"
-    #define FL_status_string_eol              "F_eol"
-    #define FL_status_string_eol_not          "F_eol_not"
-    #define FL_status_string_eos              "F_eos"
-    #define FL_status_string_eos_not          "F_eos_not"
-    #define FL_status_string_exist            "F_exist"
-    #define FL_status_string_exist_not        "F_exist_not"
-    #define FL_status_string_failure          "F_failure"
-    #define FL_status_string_failure_not      "F_failure_not"
-    #define FL_status_string_fork             "F_fork"
-    #define FL_status_string_fork_not         "F_fork_not"
-    #define FL_status_string_found            "F_found"
-    #define FL_status_string_found_not        "F_found_not"
-    #define FL_status_string_group            "F_group"
-    #define FL_status_string_group_not        "F_group_not"
-    #define FL_status_string_ignore           "F_ignore"
-    #define FL_status_string_ignore_not       "F_ignore_not"
-    #define FL_status_string_input            "F_input"
-    #define FL_status_string_input_not        "F_input_not"
-    #define FL_status_string_input_output     "F_input_output"
-    #define FL_status_string_interrupt        "F_interrupt"
-    #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_link             "F_link"
-    #define FL_status_string_link_not         "F_link_not"
-    #define FL_status_string_lock             "F_lock"
-    #define FL_status_string_lock_not         "F_lock_not"
-    #define FL_status_string_loop             "F_loop"
-    #define FL_status_string_loop_not         "F_loop_not"
-    #define FL_status_string_maybe            "F_maybe"
-    #define FL_status_string_maybe_not        "F_maybe_not"
-    #define FL_status_string_minor            "F_minor"
-    #define FL_status_string_minor_not        "F_minor_not"
-    #define FL_status_string_moderate         "F_moderate"
-    #define FL_status_string_moderate_not     "F_moderate_not"
-    #define FL_status_string_mount            "F_mount"
-    #define FL_status_string_mount_not        "F_mount_not"
-    #define FL_status_string_name             "F_name"
-    #define FL_status_string_name_not         "F_name_not"
-    #define FL_status_string_nice             "F_nice"
-    #define FL_status_string_nice_not         "F_nice_not"
-    #define FL_status_string_optional         "F_optional"
-    #define FL_status_string_optional_not     "F_optional_not"
-    #define FL_status_string_output           "F_output"
-    #define FL_status_string_output_not       "F_output_not"
-    #define FL_status_string_parameter        "F_parameter"
-    #define FL_status_string_parameter_not    "F_parameter_not"
-    #define FL_status_string_parent           "F_parent"
-    #define FL_status_string_parent_not       "F_parent_not"
-    #define FL_status_string_pipe             "F_pipe"
-    #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_prohibited       "F_prohibited"
-    #define FL_status_string_prohibited_not   "F_prohibited_not"
-    #define FL_status_string_range            "F_range"
-    #define FL_status_string_range_not        "F_range_not"
-    #define FL_status_string_read             "F_read"
-    #define FL_status_string_read_not         "F_read_not"
-    #define FL_status_string_read_only        "F_read_only"
-    #define FL_status_string_ready            "F_ready"
-    #define FL_status_string_ready_not        "F_ready_not"
-    #define FL_status_string_recurse          "F_recurse"
-    #define FL_status_string_recurse_not      "F_recurse_not"
-    #define FL_status_string_relative         "F_relative"
-    #define FL_status_string_relative_not     "F_relative_not"
-    #define FL_status_string_require          "F_require"
-    #define FL_status_string_require_not      "F_require_not"
-    #define FL_status_string_resource         "F_resource"
-    #define FL_status_string_resource_not     "F_resource_not"
-    #define FL_status_string_search           "F_search"
-    #define FL_status_string_search_not       "F_search_not"
-    #define FL_status_string_schedule         "F_schedule"
-    #define FL_status_string_schedule_not     "F_schedule_not"
-    #define FL_status_string_signal           "F_signal"
-    #define FL_status_string_signal_not       "F_signal_not"
-    #define FL_status_string_space            "F_space"
-    #define FL_status_string_space_not        "F_space_not"
-    #define FL_status_string_stop             "F_stop"
-    #define FL_status_string_stop_not         "F_stop_not"
-    #define FL_status_string_string           "F_string"
-    #define FL_status_string_string_not       "F_string_not"
-    #define FL_status_string_string_too_large "F_string_too_large"
-    #define FL_status_string_string_too_small "F_string_too_small"
-    #define FL_status_string_syntax           "F_syntax"
-    #define FL_status_string_syntax_not       "F_syntax_not"
-    #define FL_status_string_supported        "F_supported"
-    #define FL_status_string_supported_not    "F_supported_not"
-    #define FL_status_string_user             "F_user"
-    #define FL_status_string_user_not         "F_user_not"
-    #define FL_status_string_utf              "F_utf"
-    #define FL_status_string_utf_not          "F_utf_not"
-    #define FL_status_string_valid            "F_valid"
-    #define FL_status_string_valid_not        "F_valid_not"
-    #define FL_status_string_value            "F_value"
-    #define FL_status_string_value_not        "F_value_not"
-    #define FL_status_string_wait             "F_wait"
-    #define FL_status_string_wait_not         "F_wait_not"
-    #define FL_status_string_warn             "F_warn"
-    #define FL_status_string_warn_not         "F_warn_not"
-    #define FL_status_string_world            "F_world"
-    #define FL_status_string_world_not        "F_world_not"
-    #define FL_status_string_write            "F_write"
-    #define FL_status_string_write_not        "F_write_not"
-    #define FL_status_string_write_only       "F_write_only"
-
-    #define FL_status_string_none_length             6
-    #define FL_status_string_absolute_length         10
-    #define FL_status_string_absolute_not_length     14
-    #define FL_status_string_address_length          9
-    #define FL_status_string_address_not_length      13
-    #define FL_status_string_block_length            7
-    #define FL_status_string_block_not_length        11
-    #define FL_status_string_bound_length            7
-    #define FL_status_string_bound_not_length        11
-    #define FL_status_string_capability_length       12
-    #define FL_status_string_capability_not_length   16
-    #define FL_status_string_child_length            7
-    #define FL_status_string_child_not_length        11
-    #define FL_status_string_complete_length         10
-    #define FL_status_string_complete_not_length     14
-    #define FL_status_string_connected_length        11
-    #define FL_status_string_connected_not_length    15
-    #define FL_status_string_container_length        11
-    #define FL_status_string_container_not_length    15
-    #define FL_status_string_critical_length         10
-    #define FL_status_string_critical_not_length     14
-    #define FL_status_string_deadlock_length         10
-    #define FL_status_string_deadlock_not_length     14
-    #define FL_status_string_descriptor_length       12
-    #define FL_status_string_descriptor_not_length   16
-    #define FL_status_string_device_length           8
-    #define FL_status_string_device_not_length       12
-    #define FL_status_string_dummy_length            7
-    #define FL_status_string_dummy_not_length        11
-    #define FL_status_string_encoding_length         10
-    #define FL_status_string_encoding_not_length     14
-    #define FL_status_string_eof_length              5
-    #define FL_status_string_eof_not_length          9
-    #define FL_status_string_eol_length              5
-    #define FL_status_string_eol_not_length          9
-    #define FL_status_string_eos_length              5
-    #define FL_status_string_eos_not_length          9
-    #define FL_status_string_exist_length            7
-    #define FL_status_string_exist_not_length        11
-    #define FL_status_string_failure_length          9
-    #define FL_status_string_failure_not_length      13
-    #define FL_status_string_fork_length             6
-    #define FL_status_string_fork_not_length         10
-    #define FL_status_string_found_length            7
-    #define FL_status_string_found_not_length        11
-    #define FL_status_string_group_length            7
-    #define FL_status_string_group_not_length        11
-    #define FL_status_string_ignore_length           8
-    #define FL_status_string_ignore_not_length       12
-    #define FL_status_string_input_length            7
-    #define FL_status_string_input_not_length        11
-    #define FL_status_string_input_output_length     14
-    #define FL_status_string_interrupt_length        11
-    #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_link_length             6
-    #define FL_status_string_link_not_length         10
-    #define FL_status_string_lock_length             6
-    #define FL_status_string_lock_not_length         10
-    #define FL_status_string_loop_length             6
-    #define FL_status_string_loop_not_length         10
-    #define FL_status_string_maybe_length            7
-    #define FL_status_string_maybe_not_length        11
-    #define FL_status_string_minor_length            7
-    #define FL_status_string_minor_not_length        11
-    #define FL_status_string_moderate_length         10
-    #define FL_status_string_moderate_not_length     14
-    #define FL_status_string_mount_length            7
-    #define FL_status_string_mount_not_length        11
-    #define FL_status_string_name_length             6
-    #define FL_status_string_name_not_length         10
-    #define FL_status_string_nice_length             6
-    #define FL_status_string_nice_not_length         10
-    #define FL_status_string_optional_length         10
-    #define FL_status_string_optional_not_length     14
-    #define FL_status_string_output_length           8
-    #define FL_status_string_output_not_length       12
-    #define FL_status_string_parameter_length        11
-    #define FL_status_string_parameter_not_length    15
-    #define FL_status_string_parent_length           8
-    #define FL_status_string_parent_not_length       12
-    #define FL_status_string_pipe_length             6
-    #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_prohibited_length       12
-    #define FL_status_string_prohibited_not_length   16
-    #define FL_status_string_range_length            7
-    #define FL_status_string_range_not_length        11
-    #define FL_status_string_read_length             6
-    #define FL_status_string_read_not_length         10
-    #define FL_status_string_read_only_length        11
-    #define FL_status_string_ready_length            7
-    #define FL_status_string_ready_not_length        11
-    #define FL_status_string_recurse_length          9
-    #define FL_status_string_recurse_not_length      13
-    #define FL_status_string_relative_length         10
-    #define FL_status_string_relative_not_length     14
-    #define FL_status_string_require_length          9
-    #define FL_status_string_require_not_length      13
-    #define FL_status_string_resource_length         10
-    #define FL_status_string_resource_not_length     14
-    #define FL_status_string_search_length           8
-    #define FL_status_string_search_not_length       12
-    #define FL_status_string_schedule_length         10
-    #define FL_status_string_schedule_not_length     14
-    #define FL_status_string_signal_length           8
-    #define FL_status_string_signal_not_length       12
-    #define FL_status_string_space_length            7
-    #define FL_status_string_space_not_length        11
-    #define FL_status_string_stop_length             6
-    #define FL_status_string_stop_not_length         10
-    #define FL_status_string_string_length           8
-    #define FL_status_string_string_not_length       12
-    #define FL_status_string_string_too_large_length 18
-    #define FL_status_string_string_too_small_length 18
-    #define FL_status_string_supported_length        11
-    #define FL_status_string_supported_not_length    15
-    #define FL_status_string_syntax_length           8
-    #define FL_status_string_syntax_not_length       12
-    #define FL_status_string_user_length             6
-    #define FL_status_string_user_not_length         10
-    #define FL_status_string_utf_length              5
-    #define FL_status_string_utf_not_length          9
-    #define FL_status_string_valid_length            7
-    #define FL_status_string_valid_not_length        11
-    #define FL_status_string_value_length            7
-    #define FL_status_string_value_not_length        11
-    #define FL_status_string_wait_length             6
-    #define FL_status_string_wait_not_length         10
-    #define FL_status_string_warn_length             6
-    #define FL_status_string_warn_not_length         10
-    #define FL_status_string_world_length            7
-    #define FL_status_string_world_not_length        11
-    #define FL_status_string_write_length            7
-    #define FL_status_string_write_not_length        11
-    #define FL_status_string_write_only_length       12
+    #define FL_status_string_none              "F_none"
+    #define FL_status_string_absolute          "F_absolute"
+    #define FL_status_string_absolute_not      "F_absolute_not"
+    #define FL_status_string_address           "F_address"
+    #define FL_status_string_address_not       "F_address_not"
+    #define FL_status_string_block             "F_block"
+    #define FL_status_string_block_not         "F_block_not"
+    #define FL_status_string_bound             "F_bound"
+    #define FL_status_string_bound_not         "F_bound_not"
+    #define FL_status_string_capability        "F_capability"
+    #define FL_status_string_capability_not    "F_capability_not"
+    #define FL_status_string_child             "F_child"
+    #define FL_status_string_child_not         "F_child_not"
+    #define FL_status_string_complete          "F_complete"
+    #define FL_status_string_complete_not      "F_complete_not"
+    #define FL_status_string_connected         "F_connected"
+    #define FL_status_string_connected_not     "F_connected_not"
+    #define FL_status_string_container         "F_container"
+    #define FL_status_string_container_not     "F_container_not"
+    #define FL_status_string_control           "F_control"
+    #define FL_status_string_control_not       "F_control_not"
+    #define FL_status_string_control_group     "F_control_group"
+    #define FL_status_string_control_group_not "F_control_group_not"
+    #define FL_status_string_critical          "F_critical"
+    #define FL_status_string_critical_not      "F_critical_not"
+    #define FL_status_string_deadlock          "F_deadlock"
+    #define FL_status_string_deadlock_not      "F_deadlock_not"
+    #define FL_status_string_descriptor        "F_descriptor"
+    #define FL_status_string_descriptor_not    "F_descriptor_not"
+    #define FL_status_string_device            "F_device"
+    #define FL_status_string_device_not        "F_device_not"
+    #define FL_status_string_dummy             "F_dummy"
+    #define FL_status_string_dummy_not         "F_dummy_not"
+    #define FL_status_string_encoding          "F_encoding"
+    #define FL_status_string_encoding_not      "F_encoding_not"
+    #define FL_status_string_eof               "F_eof"
+    #define FL_status_string_eof_not           "F_eof_not"
+    #define FL_status_string_eol               "F_eol"
+    #define FL_status_string_eol_not           "F_eol_not"
+    #define FL_status_string_eos               "F_eos"
+    #define FL_status_string_eos_not           "F_eos_not"
+    #define FL_status_string_exist             "F_exist"
+    #define FL_status_string_exist_not         "F_exist_not"
+    #define FL_status_string_failure           "F_failure"
+    #define FL_status_string_failure_not       "F_failure_not"
+    #define FL_status_string_fork              "F_fork"
+    #define FL_status_string_fork_not          "F_fork_not"
+    #define FL_status_string_found             "F_found"
+    #define FL_status_string_found_not         "F_found_not"
+    #define FL_status_string_group             "F_group"
+    #define FL_status_string_group_not         "F_group_not"
+    #define FL_status_string_ignore            "F_ignore"
+    #define FL_status_string_ignore_not        "F_ignore_not"
+    #define FL_status_string_input             "F_input"
+    #define FL_status_string_input_not         "F_input_not"
+    #define FL_status_string_input_output      "F_input_output"
+    #define FL_status_string_interrupt         "F_interrupt"
+    #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_link              "F_link"
+    #define FL_status_string_link_not          "F_link_not"
+    #define FL_status_string_lock              "F_lock"
+    #define FL_status_string_lock_not          "F_lock_not"
+    #define FL_status_string_loop              "F_loop"
+    #define FL_status_string_loop_not          "F_loop_not"
+    #define FL_status_string_maybe             "F_maybe"
+    #define FL_status_string_maybe_not         "F_maybe_not"
+    #define FL_status_string_minor             "F_minor"
+    #define FL_status_string_minor_not         "F_minor_not"
+    #define FL_status_string_moderate          "F_moderate"
+    #define FL_status_string_moderate_not      "F_moderate_not"
+    #define FL_status_string_mount             "F_mount"
+    #define FL_status_string_mount_not         "F_mount_not"
+    #define FL_status_string_name              "F_name"
+    #define FL_status_string_name_not          "F_name_not"
+    #define FL_status_string_nice              "F_nice"
+    #define FL_status_string_nice_not          "F_nice_not"
+    #define FL_status_string_optional          "F_optional"
+    #define FL_status_string_optional_not      "F_optional_not"
+    #define FL_status_string_output            "F_output"
+    #define FL_status_string_output_not        "F_output_not"
+    #define FL_status_string_parameter         "F_parameter"
+    #define FL_status_string_parameter_not     "F_parameter_not"
+    #define FL_status_string_parent            "F_parent"
+    #define FL_status_string_parent_not        "F_parent_not"
+    #define FL_status_string_pipe              "F_pipe"
+    #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_prohibited        "F_prohibited"
+    #define FL_status_string_prohibited_not    "F_prohibited_not"
+    #define FL_status_string_range             "F_range"
+    #define FL_status_string_range_not         "F_range_not"
+    #define FL_status_string_read              "F_read"
+    #define FL_status_string_read_not          "F_read_not"
+    #define FL_status_string_read_only         "F_read_only"
+    #define FL_status_string_ready             "F_ready"
+    #define FL_status_string_ready_not         "F_ready_not"
+    #define FL_status_string_recurse           "F_recurse"
+    #define FL_status_string_recurse_not       "F_recurse_not"
+    #define FL_status_string_relative          "F_relative"
+    #define FL_status_string_relative_not      "F_relative_not"
+    #define FL_status_string_require           "F_require"
+    #define FL_status_string_require_not       "F_require_not"
+    #define FL_status_string_resource          "F_resource"
+    #define FL_status_string_resource_not      "F_resource_not"
+    #define FL_status_string_search            "F_search"
+    #define FL_status_string_search_not        "F_search_not"
+    #define FL_status_string_schedule          "F_schedule"
+    #define FL_status_string_schedule_not      "F_schedule_not"
+    #define FL_status_string_signal            "F_signal"
+    #define FL_status_string_signal_not        "F_signal_not"
+    #define FL_status_string_space             "F_space"
+    #define FL_status_string_space_not         "F_space_not"
+    #define FL_status_string_stop              "F_stop"
+    #define FL_status_string_stop_not          "F_stop_not"
+    #define FL_status_string_string            "F_string"
+    #define FL_status_string_string_not        "F_string_not"
+    #define FL_status_string_string_too_large  "F_string_too_large"
+    #define FL_status_string_string_too_small  "F_string_too_small"
+    #define FL_status_string_syntax            "F_syntax"
+    #define FL_status_string_syntax_not        "F_syntax_not"
+    #define FL_status_string_supported         "F_supported"
+    #define FL_status_string_supported_not     "F_supported_not"
+    #define FL_status_string_user              "F_user"
+    #define FL_status_string_user_not          "F_user_not"
+    #define FL_status_string_utf               "F_utf"
+    #define FL_status_string_utf_not           "F_utf_not"
+    #define FL_status_string_valid             "F_valid"
+    #define FL_status_string_valid_not         "F_valid_not"
+    #define FL_status_string_value             "F_value"
+    #define FL_status_string_value_not         "F_value_not"
+    #define FL_status_string_wait              "F_wait"
+    #define FL_status_string_wait_not          "F_wait_not"
+    #define FL_status_string_warn              "F_warn"
+    #define FL_status_string_warn_not          "F_warn_not"
+    #define FL_status_string_world             "F_world"
+    #define FL_status_string_world_not         "F_world_not"
+    #define FL_status_string_write             "F_write"
+    #define FL_status_string_write_not         "F_write_not"
+    #define FL_status_string_write_only        "F_write_only"
+
+    #define FL_status_string_none_length              6
+    #define FL_status_string_absolute_length          10
+    #define FL_status_string_absolute_not_length      14
+    #define FL_status_string_address_length           9
+    #define FL_status_string_address_not_length       13
+    #define FL_status_string_block_length             7
+    #define FL_status_string_block_not_length         11
+    #define FL_status_string_bound_length             7
+    #define FL_status_string_bound_not_length         11
+    #define FL_status_string_capability_length        12
+    #define FL_status_string_capability_not_length    16
+    #define FL_status_string_child_length             7
+    #define FL_status_string_child_not_length         11
+    #define FL_status_string_complete_length          10
+    #define FL_status_string_complete_not_length      14
+    #define FL_status_string_connected_length         11
+    #define FL_status_string_connected_not_length     15
+    #define FL_status_string_container_length         11
+    #define FL_status_string_container_not_length     15
+    #define FL_status_string_control_length           9
+    #define FL_status_string_control_not_length       13
+    #define FL_status_string_control_group_length     15
+    #define FL_status_string_control_group_not_length 19
+    #define FL_status_string_critical_length          10
+    #define FL_status_string_critical_not_length      14
+    #define FL_status_string_deadlock_length          10
+    #define FL_status_string_deadlock_not_length      14
+    #define FL_status_string_descriptor_length        12
+    #define FL_status_string_descriptor_not_length    16
+    #define FL_status_string_device_length            8
+    #define FL_status_string_device_not_length        12
+    #define FL_status_string_dummy_length             7
+    #define FL_status_string_dummy_not_length         11
+    #define FL_status_string_encoding_length          10
+    #define FL_status_string_encoding_not_length      14
+    #define FL_status_string_eof_length               5
+    #define FL_status_string_eof_not_length           9
+    #define FL_status_string_eol_length               5
+    #define FL_status_string_eol_not_length           9
+    #define FL_status_string_eos_length               5
+    #define FL_status_string_eos_not_length           9
+    #define FL_status_string_exist_length             7
+    #define FL_status_string_exist_not_length         11
+    #define FL_status_string_failure_length           9
+    #define FL_status_string_failure_not_length       13
+    #define FL_status_string_fork_length              6
+    #define FL_status_string_fork_not_length          10
+    #define FL_status_string_found_length             7
+    #define FL_status_string_found_not_length         11
+    #define FL_status_string_group_length             7
+    #define FL_status_string_group_not_length         11
+    #define FL_status_string_ignore_length            8
+    #define FL_status_string_ignore_not_length        12
+    #define FL_status_string_input_length             7
+    #define FL_status_string_input_not_length         11
+    #define FL_status_string_input_output_length      14
+    #define FL_status_string_interrupt_length         11
+    #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_link_length              6
+    #define FL_status_string_link_not_length          10
+    #define FL_status_string_lock_length              6
+    #define FL_status_string_lock_not_length          10
+    #define FL_status_string_loop_length              6
+    #define FL_status_string_loop_not_length          10
+    #define FL_status_string_maybe_length             7
+    #define FL_status_string_maybe_not_length         11
+    #define FL_status_string_minor_length             7
+    #define FL_status_string_minor_not_length         11
+    #define FL_status_string_moderate_length          10
+    #define FL_status_string_moderate_not_length      14
+    #define FL_status_string_mount_length             7
+    #define FL_status_string_mount_not_length         11
+    #define FL_status_string_name_length              6
+    #define FL_status_string_name_not_length          10
+    #define FL_status_string_nice_length              6
+    #define FL_status_string_nice_not_length          10
+    #define FL_status_string_optional_length          10
+    #define FL_status_string_optional_not_length      14
+    #define FL_status_string_output_length            8
+    #define FL_status_string_output_not_length        12
+    #define FL_status_string_parameter_length         11
+    #define FL_status_string_parameter_not_length     15
+    #define FL_status_string_parent_length            8
+    #define FL_status_string_parent_not_length        12
+    #define FL_status_string_pipe_length              6
+    #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_prohibited_length        12
+    #define FL_status_string_prohibited_not_length    16
+    #define FL_status_string_range_length             7
+    #define FL_status_string_range_not_length         11
+    #define FL_status_string_read_length              6
+    #define FL_status_string_read_not_length          10
+    #define FL_status_string_read_only_length         11
+    #define FL_status_string_ready_length             7
+    #define FL_status_string_ready_not_length         11
+    #define FL_status_string_recurse_length           9
+    #define FL_status_string_recurse_not_length       13
+    #define FL_status_string_relative_length          10
+    #define FL_status_string_relative_not_length      14
+    #define FL_status_string_require_length           9
+    #define FL_status_string_require_not_length       13
+    #define FL_status_string_resource_length          10
+    #define FL_status_string_resource_not_length      14
+    #define FL_status_string_search_length            8
+    #define FL_status_string_search_not_length        12
+    #define FL_status_string_schedule_length          10
+    #define FL_status_string_schedule_not_length      14
+    #define FL_status_string_signal_length            8
+    #define FL_status_string_signal_not_length        12
+    #define FL_status_string_space_length             7
+    #define FL_status_string_space_not_length         11
+    #define FL_status_string_stop_length              6
+    #define FL_status_string_stop_not_length          10
+    #define FL_status_string_string_length            8
+    #define FL_status_string_string_not_length        12
+    #define FL_status_string_string_too_large_length  18
+    #define FL_status_string_string_too_small_length  18
+    #define FL_status_string_supported_length         11
+    #define FL_status_string_supported_not_length     15
+    #define FL_status_string_syntax_length            8
+    #define FL_status_string_syntax_not_length        12
+    #define FL_status_string_user_length              6
+    #define FL_status_string_user_not_length          10
+    #define FL_status_string_utf_length               5
+    #define FL_status_string_utf_not_length           9
+    #define FL_status_string_valid_length             7
+    #define FL_status_string_valid_not_length         11
+    #define FL_status_string_value_length             7
+    #define FL_status_string_value_not_length         11
+    #define FL_status_string_wait_length              6
+    #define FL_status_string_wait_not_length          10
+    #define FL_status_string_warn_length              6
+    #define FL_status_string_warn_not_length          10
+    #define FL_status_string_world_length             7
+    #define FL_status_string_world_not_length         11
+    #define FL_status_string_write_length             7
+    #define FL_status_string_write_not_length         11
+    #define FL_status_string_write_only_length        12
   #endif // _di_F_status_basic_
 
   #ifndef _di_F_status_array_
diff --git a/level_2/fll_control_group/c/control_group.c b/level_2/fll_control_group/c/control_group.c
new file mode 100644 (file)
index 0000000..6aa95a0
--- /dev/null
@@ -0,0 +1,51 @@
+#include "control_group.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fll_control_group_prepare_
+  f_return_status fll_control_group_prepare(const f_control_group_t control_group) {
+    f_status_t status = F_none;
+
+    if (control_group.path.used) {
+      status = f_directory_exists(control_group.path.string);
+      if (F_status_is_error(status)) return status;
+
+      if (status == F_false) {
+        return F_status_set_error(F_directory_not);
+      }
+    }
+
+    f_string_length_t length = 0;
+
+    for (f_array_length_t i = 0; i < control_group.groups.used; ++i) {
+
+      if (!control_group.groups.array[i].used) continue;
+
+      length = control_group.path.used + control_group.groups.array[i].used;
+
+      char path[length + 1];
+
+      if (control_group.path.used) {
+        memcpy(path, control_group.path.string, control_group.path.used);
+      }
+
+      memcpy(path + control_group.path.used, control_group.groups.array[i].string, control_group.groups.array[i].used);
+      path[length] = 0;
+
+      status = fl_directory_create(path, length, f_file_mode_all_rwx);
+      if (F_status_is_error(status)) break;
+    } // for
+
+    if (F_status_is_error(status)) {
+      return status;
+    }
+
+    return F_none;
+  }
+#endif // _di_fll_control_group_prepare_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_2/fll_control_group/c/control_group.h b/level_2/fll_control_group/c/control_group.h
new file mode 100644 (file)
index 0000000..ba06370
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * FLL - Level 2
+ *
+ * Project: Control Group
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * Provides control group (cgroup) related functionality.
+ */
+#ifndef _FLL_control_h
+#define _FLL_control_h
+
+// libc includes
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/utf.h>
+#include <level_0/control_group.h>
+#include <level_0/directory.h>
+#include <level_0/file.h>
+#include <level_0/path.h>
+
+// fll-1 includes
+#include <level_1/control_group.h>
+#include <level_1/directory.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Make sure all directories specified in groups exist, creating all directories in the path.
+ *
+ * This does not, however, create the control_group.path and will error out if that directory does not exist.
+ *
+ * @param control
+ *   The control group(s) to ensure the directories exist.
+ *
+ * @return
+ *   F_none on success.
+ *   F_directory_not (with error bit) if control_group.path does not exist.
+ *
+ *   Errors (with error bit) from: f_directory_exists().
+ *   Errors (with error bit) from: fl_directory_create().
+ *
+ * @see f_directory_exists()
+ * @see fl_directory_create()
+ */
+#ifndef _di_fll_control_group_prepare_
+  extern f_return_status fll_control_group_prepare(const f_control_group_t control_group);
+#endif // _di_fll_control_group_prepare_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _FLL_control_h
diff --git a/level_2/fll_control_group/data/build/defines b/level_2/fll_control_group/data/build/defines
new file mode 100644 (file)
index 0000000..4f13080
--- /dev/null
@@ -0,0 +1 @@
+# fss-0000
diff --git a/level_2/fll_control_group/data/build/dependencies b/level_2/fll_control_group/data/build/dependencies
new file mode 100644 (file)
index 0000000..5e94b53
--- /dev/null
@@ -0,0 +1,13 @@
+# fss-0000
+
+f_type
+f_status
+f_memory
+f_string
+f_utf
+f_control_group
+f_directory
+f_file
+f_path
+fl_control_group
+fl_directory
diff --git a/level_2/fll_control_group/data/build/settings b/level_2/fll_control_group/data/build/settings
new file mode 100644 (file)
index 0000000..6afda91
--- /dev/null
@@ -0,0 +1,55 @@
+# fss-0001
+
+project_name fll_control_group
+
+version_major 0
+version_minor 5
+version_micro 2
+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 -lfl_control_group -lfl_directory -lf_directory -lf_file -lf_memory -lf_path -lf_utf
+build_sources_library control_group.c
+build_sources_program
+build_sources_headers control_group.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+path_headers level_2
+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 b5d8e0cc9308dc8b2130513d2eb2f5375375e30d..6b15caabbd0c0ae5d44f2f5c8b78e81a38cbabaf 100644 (file)
@@ -64,7 +64,7 @@ extern "C" {
   } fll_error_print_t;
 
   #define fll_error_print_t_initialize { \
-    f_macro_file_t_initialize(f_type_error, f_type_descriptor_error, f_file_flag_write_only), \
+    f_macro_file_t_initialize2(f_type_error, f_type_descriptor_error, f_file_flag_write_only), \
     f_console_verbosity_normal, \
     fll_error_print_error, \
     f_color_set_t_initialize, \
@@ -72,8 +72,8 @@ extern "C" {
   }
 
   #define fll_macro_error_print_t_initialize(to, verbosity, prefix, context, notable) { to, verbosity, prefix, context, notable }
-  #define fll_macro_error_print_t_initialize_debug() fll_macro_error_print_t_initialize(f_macro_file_t_initialize(f_type_debug, f_type_descriptor_debug, f_file_flag_write_only), f_console_verbosity_normal, fll_error_print_debug, f_color_set_t_initialize, f_color_set_t_initialize)
-  #define fll_macro_error_print_t_initialize_warning() fll_macro_error_print_t_initialize(f_macro_file_t_initialize(f_type_warning, f_type_descriptor_warning, f_file_flag_write_only), f_console_verbosity_normal, fll_error_print_warning, f_color_set_t_initialize, f_color_set_t_initialize)
+  #define fll_macro_error_print_t_initialize_debug() fll_macro_error_print_t_initialize(f_macro_file_t_initialize2(f_type_debug, f_type_descriptor_debug, f_file_flag_write_only), f_console_verbosity_normal, fll_error_print_debug, f_color_set_t_initialize, f_color_set_t_initialize)
+  #define fll_macro_error_print_t_initialize_warning() fll_macro_error_print_t_initialize(f_macro_file_t_initialize2(f_type_warning, f_type_descriptor_warning, f_file_flag_write_only), f_console_verbosity_normal, fll_error_print_warning, f_color_set_t_initialize, f_color_set_t_initialize)
 #endif // _di_fll_error_print_t_
 
 #ifdef __cplusplus
index 817a8598110e2323f18d99cd1d323bd89ce4dec2..3db3dc5b2e6522ec3f4996060443d799b0229279 100644 (file)
@@ -13,6 +13,9 @@
 #ifndef _FLL_execute_h
 #define _FLL_execute_h
 
+// include pre-requirements
+#define _GNU_SOURCE
+
 // libc includes
 #include <memory.h>
 #include <sched.h>
@@ -30,6 +33,7 @@
 #include <level_0/string.h>
 #include <level_0/utf.h>
 #include <level_0/capability.h>
+#include <level_0/control_group.h>
 #include <level_0/environment.h>
 #include <level_0/execute.h>
 #include <level_0/file.h>
@@ -37,6 +41,7 @@
 #include <level_0/signal.h>
 
 // fll-1 includes
+#include <level_1/control_group.h>
 #include <level_1/environment.h>
 #include <level_1/execute.h>
 #include <level_1/string.h>
@@ -387,9 +392,11 @@ extern "C" {
  * Otherwise, this returns F_child and assigns the child's return code to result for the child process.
  * The caller is expected to handle the appropriate exit procedures and memory deallocation for the child process when F_child is returned.
  *
- * This returns F_capability, F_group, and F_user only for the child process and must be treated the same as F_child for the purposes of understanding what the current process is.
+ * 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.
+ *
  * @param program
  *   The name or path of the program.
  *   The string pointer may be set to 0, to designate that the first index in arguments is assumed to be the program.
@@ -420,14 +427,16 @@ extern "C" {
  *
  * @return
  *   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_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_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_schedule (with error bit) on failure to set scheduler in the child (only the child 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().
@@ -462,6 +471,7 @@ extern "C" {
  * @see f_environment_get()
  * @see f_file_exists()
  * @see f_signal_set_handle()
+ * @see fl_control_group_apply()
  * @see fl_environment_path_explode_dynamic()
  * @see fl_string_append()
  * @see fl_string_dynamic_terminate()
index fdb45f30c3c07ccbbb2a18ada9c76e7d7ff03b90..3f5b0d29b1743039a61a0d2c4c180dcabe1aca3b 100644 (file)
@@ -117,7 +117,7 @@ extern "C" {
 #endif // !defined(_di_fll_execute_arguments_add_parameter_) || !defined(_di_fll_execute_arguments_add_parameter_set_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_) || !defined(_di_fll_execute_arguments_dynamic_add_parameter_set_)
 
 #if !defined(_di_fll_execute_program_)
-  f_return_status private_fll_execute_as(const fl_execute_as_t as, fl_execute_parameter_t * const parameter, int *result) {
+  f_return_status private_fll_execute_as_child(const fl_execute_as_t as, fl_execute_parameter_t * const parameter, int *result) {
 
     if (as.nice) {
       errno = 0;
@@ -133,25 +133,6 @@ extern "C" {
       }
     }
 
-    if (as.scheduler) {
-      const int process_id = getpid();
-
-      struct sched_param parameter_schedule;
-      parameter_schedule.sched_priority = as.scheduler->priority;
-
-      errno = 0;
-
-      if (sched_setscheduler(process_id, as.scheduler->policy, &parameter_schedule) == -1) {
-        *result = -1;
-
-        if (parameter && parameter->option & fl_execute_parameter_option_exit) {
-          exit(*result);
-        }
-
-        return F_status_set_error(F_schedule);
-      }
-    }
-
     if (as.capability) {
       const f_status_t status = f_capability_process_set(as.capability);
 
@@ -207,18 +188,92 @@ extern "C" {
 #endif // !defined(_di_fll_execute_program_)
 
 #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.scheduler) {
+      struct sched_param parameter_schedule;
+      parameter_schedule.sched_priority = as.scheduler->priority;
+
+      errno = 0;
+
+      if (sched_setscheduler(id_child, as.scheduler->policy, &parameter_schedule) == -1) {
+        result[0] = '1';
+
+        return F_status_set_error(F_schedule);
+      }
+    }
+
+    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);
+      }
+    }
+
+    return F_none;
+  }
+#endif // !defined(_di_fll_execute_program_)
+
+#if !defined(_di_fll_execute_program_)
   f_return_status private_fll_execute_fork(const f_string_t program, const f_string_t fixed_arguments[], fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, int *result) {
 
-    const pid_t process_id = fork();
+    int descriptors[2] = { -1, -1 };
+
+    if (as) {
+      if (pipe(descriptors) == -1) {
+        return F_status_set_error(F_pipe);
+      }
+    }
+
+    const pid_t id_process = fork();
+
+    if (id_process < 0) {
+      if (as) {
+        close(descriptors[0]);
+        close(descriptors[1]);
+      }
 
-    if (process_id < 0) {
       return F_status_set_error(F_fork);
     }
 
-    if (process_id) {
+    if (id_process) {
+
+      if (as) {
+
+        // close the read pipe for the parent.
+        close(descriptors[0]);
+
+        // have the parent perform all appropriate access controls and then send either '0' for no error or '1' for error to the child.
+        {
+          char string_result[2] = { '0', 0 };
+
+          const f_file_t file = f_macro_file_t_initialize2(0, descriptors[1], f_file_flag_write_only);
+
+          f_string_static_t result = f_string_static_t_initialize;
+
+          result.string = string_result;
+          result.used = 1;
+          result.size = 2;
+
+          const f_status_t status = private_fll_execute_as_parent(*as, id_process, parameter, string_result);
+
+          // inform the child that it can now safely begin (or exit).
+          if (F_status_is_error(f_file_write(file, result, 0))) {
+            string_result[0] = '1';
+          }
+
+          // close the write pipe for the parent when finished writing.
+          close(descriptors[1]);
+
+          if (F_status_is_error(status)) {
+            return status;
+          }
+        }
+      }
 
       // have the parent wait for the child process to finish.
-      waitpid(process_id, result, WUNTRACED | WCONTINUED);
+      waitpid(id_process, result, WUNTRACED | WCONTINUED);
 
       // this must explicitly check for 0 (as opposed to checking (!result)).
       if (result != 0) {
@@ -232,6 +287,38 @@ extern "C" {
       return F_none;
     }
 
+    if (as) {
+
+      // close the write pipe for the child.
+      close(descriptors[1]);
+
+      char string_response[2] = { 0, 0 };
+
+      f_string_static_t response = f_string_static_t_initialize;
+
+      response.string = string_response;
+      response.used = 0;
+      response.size = 2;
+
+      const f_file_t file = f_macro_file_t_initialize(0, descriptors[0], f_file_flag_read_only, 1, 1);
+
+      f_file_read_block(file, &response);
+
+      if (!response.used || response.string[0] == '1') {
+        close(descriptors[0]);
+
+        if (result) {
+          *result = -1;
+        }
+
+        if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+          exit(-1);
+        }
+
+        return F_child;
+      }
+    }
+
     if (parameter && parameter->signals) {
       f_signal_set_handle(SIG_BLOCK, &parameter->signals->block);
       f_signal_set_handle(SIG_UNBLOCK, &parameter->signals->block_not);
@@ -246,7 +333,11 @@ extern "C" {
     }
 
     if (as) {
-      const f_status_t status = private_fll_execute_as(*as, parameter, result);
+
+      // close the write pipe for the child when done.
+      close(descriptors[0]);
+
+      const f_status_t status = private_fll_execute_as_child(*as, parameter, result);
 
       if (F_status_is_error(status)) {
         return status;
@@ -276,32 +367,58 @@ extern "C" {
       return F_status_set_error(F_pipe);
     }
 
-    const pid_t process_id = fork();
+    const pid_t id_process = fork();
 
-    if (process_id < 0) {
+    if (id_process < 0) {
       close(descriptors[0]);
       close(descriptors[1]);
 
       return F_status_set_error(F_fork);
     }
 
-    if (process_id) {
+    if (id_process) {
 
       // close the read pipe for the parent.
       close(descriptors[0]);
 
-      // write all data, if child doesn't read this could block until child closes the pipe.
       {
-        const f_file_t file = f_macro_file_t_initialize(0, descriptors[1], f_file_flag_write_only);
+        char string_result[2] = { '0', 0 };
+
+        const f_file_t file = f_macro_file_t_initialize2(0, descriptors[1], f_file_flag_write_only);
+
+        f_status_t status = F_none;
+
+        // have the parent perform all appropriate access controls and then send either '0' for no error or '1' for error to the child.
+        if (as) {
+          f_string_static_t result = f_string_static_t_initialize;
 
-        f_file_write(file, *parameter->data, 0);
+          result.string = string_result;
+          result.used = 1;
+          result.size = 2;
+
+          status = private_fll_execute_as_parent(*as, id_process, parameter, string_result);
+
+          // inform the child that it can now safely begin (or exit).
+          if (F_status_is_error(f_file_write(file, result, 0))) {
+            string_result[0] = '1';
+          }
+        }
+
+        // write all data, if child doesn't read this could block until child closes the pipe.
+        if (string_result[0] == '0') {
+          f_file_write(file, *parameter->data, 0);
+        }
 
         // close the write pipe for the parent when finished writing.
         close(descriptors[1]);
+
+        if (F_status_is_error(status)) {
+          return status;
+        }
       }
 
       // have the parent wait for the child process to finish.
-      waitpid(process_id, result, WUNTRACED | WCONTINUED);
+      waitpid(id_process, result, WUNTRACED | WCONTINUED);
 
       // this must explicitly check for 0 (as opposed to checking (!result)).
       if (result != 0) {
@@ -318,6 +435,35 @@ extern "C" {
     // close the write pipe for the child.
     close(descriptors[1]);
 
+    // wait for parent to tell child to begin.
+    if (as) {
+      char string_response[2] = { 0, 0 };
+
+      f_string_static_t response = f_string_static_t_initialize;
+
+      response.string = string_response;
+      response.used = 0;
+      response.size = 2;
+
+      const f_file_t file = f_macro_file_t_initialize(0, descriptors[0], f_file_flag_read_only, 1, 1);
+
+      f_file_read_block(file, &response);
+
+      if (!response.used || response.string[0] == '1') {
+        close(descriptors[0]);
+
+        if (result) {
+          *result = -1;
+        }
+
+        if (parameter && parameter->option & fl_execute_parameter_option_exit) {
+          exit(-1);
+        }
+
+        return F_child;
+      }
+    }
+
     if (parameter && parameter->signals) {
       f_signal_set_handle(SIG_BLOCK, &parameter->signals->block);
       f_signal_set_handle(SIG_UNBLOCK, &parameter->signals->block_not);
@@ -334,7 +480,7 @@ extern "C" {
     dup2(descriptors[0], f_type_descriptor_input);
 
     if (as) {
-      const f_status_t status = private_fll_execute_as(*as, parameter, result);
+      const f_status_t status = private_fll_execute_as_child(*as, parameter, result);
 
       if (F_status_is_error(status)) {
         return status;
index 3e9a0486d7dc92a837451dd16bd3f0a528598c7d..e946412c6af524a153c7fe9956e2db61bd3d83fb 100644 (file)
@@ -139,7 +139,47 @@ extern "C" {
  * @see fll_execute_program()
  */
 #if !defined(_di_fll_execute_program_)
-  extern f_return_status private_fll_execute_as(const fl_execute_as_t as, fl_execute_parameter_t * const parameter, int *result) f_gcc_attribute_visibility_internal;
+  extern f_return_status private_fll_execute_as_child(const fl_execute_as_t as, fl_execute_parameter_t * const parameter, int *result) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fll_execute_program_)
+
+/**
+ * Private function for perform the execute as operations.
+ *
+ * This should be executed in the parent thread.
+ *
+ * @param as
+ *   The "as" operations to perform.
+ * @param id_child
+ *   The child PID.
+ * @param parameter
+ *   (optional) This and most of its fields are optional and are disabled when set to 0.
+ *   This function only cares about "option" on this structure.
+ *   option:
+ *     A bitwise set of options, such as: fl_execute_parameter_option_exit, and fl_execute_parameter_option_path.
+ * @param result
+ *   A NULL termianted 2-byte string array where the first character represents the return code ('0' for success, '1' for failure).
+ *
+ * @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_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_setscheduler()
+ * @see setgid()
+ * @see setgroups()
+ * @see setuid()
+ *
+ * @see f_capability_process_set()
+ * @see fll_execute_program()
+ */
+#if !defined(_di_fll_execute_program_)
+  extern 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) f_gcc_attribute_visibility_internal;
 #endif // !defined(_di_fll_execute_program_)
 
 /**
@@ -176,23 +216,30 @@ extern "C" {
  *
  * @return
  *   F_none on success.
- *   F_capability (with error bit) on failure to set capabilities in the child (only the child process returns this).
  *   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_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_nice (with error bit) on failure to set process niceness in the child (only the child process returns this).
- *   F_schedule (with error bit) on failure to set scheduler in the child (only the child process returns this).
+ *   F_pipe (with error bit) on pipe failure.
+ *   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).
  *
  * @see clearenv()
+ * @see close()
+ * @see dup2()
  * @see execv()
  * @see execvp()
  * @see fork()
+ * @see pipe()
  * @see waitpid()
  *
  * @see f_environment_set_dynamic()
  * @see f_signal_set_handle()
+ * @see fl_control_group_apply()
  * @see fll_execute_program()
  */
 #if !defined(_di_fll_execute_program_)
@@ -233,14 +280,16 @@ extern "C" {
  *
  * @return
  *   F_none on success.
- *   F_capability (with error bit) on failure to set capabilities in the child (only the child process returns this).
  *   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_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_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_schedule (with error bit) on failure to set scheduler in the child (only the child 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).
  *
  * @see clearenv()
index 9f340366dc0d9d9552aa07710aa96bb0953c5d46..0b7c46f2b7a3cb9c95ff717ecfd26a422b2e4160 100644 (file)
@@ -4,12 +4,14 @@ f_type
 f_status
 f_memory
 f_string
+f_account
 f_capability
 f_environment
 f_execute
 f_file
 f_path
 f_signal
+fl_control_group
 fl_environment
 fl_execute
 fl_string
index a789937bcc34e9879e768b15c95686cc1b514460..44665a6965db4c3bb1b434c00ac551746ea2c21c 100644 (file)
@@ -19,7 +19,7 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc -lcap
-build_libraries-individual -lfl_environment -lfl_string -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_memory -lf_path -lf_signal -lf_utf
 build_sources_library execute.c private-execute.c
 build_sources_program
 build_sources_headers execute.h
index 6d749f566e3b1887d6fe68c3a299ce8f1aaa2626..41cfd2d770eb51995a37d963da31e374150e0fc6 100644 (file)
@@ -456,6 +456,26 @@ extern "C" {
         return F_none;
       }
 
+      if (fl_string_compare(string, FL_status_string_control, length, FL_status_string_control_length) == F_equal_to) {
+        *code = F_control;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_control_not, length, FL_status_string_control_not_length) == F_equal_to) {
+        *code = F_control_not;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_control_group, length, FL_status_string_control_group_length) == F_equal_to) {
+        *code = F_control_group;
+        return F_none;
+      }
+
+      if (fl_string_compare(string, FL_status_string_control_group_not, length, FL_status_string_control_group_not_length) == F_equal_to) {
+        *code = F_control_group_not;
+        return F_none;
+      }
+
       if (fl_string_compare(string, FL_status_string_critical, length, FL_status_string_critical_length) == F_equal_to) {
         *code = F_critical;
         return F_none;
index 67062b18a3759d0a6238a060171baf0cb1c4802a..0829a66f47bcfd7cd4e3fc279636014bb77e1a7c 100644 (file)
@@ -231,7 +231,7 @@ extern "C" {
       byte_dump_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       0, \
       0, \
index 031111173f75b87692540ddcf9d549a5d35e17d0..8c92cfbd8c4339d0d4e2bcdf71b968f30b95842d 100644 (file)
@@ -100,7 +100,7 @@ extern "C" {
       control_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_color_context_t_initialize, \
     }
index 4c4c826381c1bab7c9ae7ca20d5d2dc80bad04e1..28b4200e1473f0757c18ce5b715a09f12ee4e97c 100644 (file)
@@ -19,6 +19,9 @@
  */
 #ifndef _controller_h
 
+// include pre-requirements
+#define _GNU_SOURCE
+
 // libc includes
 #include <sched.h>
 #include <string.h>
@@ -36,6 +39,7 @@
 #include <level_0/capability.h>
 #include <level_0/color.h>
 #include <level_0/console.h>
+#include <level_0/control_group.h>
 #include <level_0/directory.h>
 #include <level_0/environment.h>
 #include <level_0/execute.h>
 // fll-1 includes
 #include <level_1/color.h>
 #include <level_1/console.h>
+#include <level_1/control_group.h>
 #include <level_1/fss.h>
 #include <level_1/string.h>
 #include <level_1/type.h>
 
 // fll-2 includes
+#include <level_2/control_group.h>
 #include <level_2/environment.h>
 #include <level_2/error.h>
 #include <level_2/execute.h>
@@ -180,7 +186,7 @@ extern "C" {
       controller_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       fll_macro_error_print_t_initialize_warning(), \
       0, \
index 58a5ddcd4db114939c4bd49e24178bbdae2d4603..714397ad2d0d01b71e816eba63fe3596b159bfe6 100644 (file)
@@ -23,12 +23,14 @@ extern "C" {
   #define controller_string_command       "command"
   #define controller_string_consider      "consider"
   #define controller_string_control       "control"
+  #define controller_string_control_group "control_group"
   #define controller_string_deadline      "deadline"
   #define controller_string_default       "default"
   #define controller_string_define        "define"
   #define controller_string_entry         "entry"
   #define controller_string_entries       "entries"
   #define controller_string_environment   "environment"
+  #define controller_string_existing      "existing"
   #define controller_string_fail          "fail"
   #define controller_string_failsafe      "failsafe"
   #define controller_string_fifo          "fifo"
@@ -42,6 +44,7 @@ extern "C" {
   #define controller_string_method        "method"
   #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_optional      "optional"
@@ -85,12 +88,14 @@ extern "C" {
   #define controller_string_command_length       7
   #define controller_string_consider_length      8
   #define controller_string_control_length       7
+  #define controller_string_control_group_length 13
   #define controller_string_deadline_length      8
   #define controller_string_define_length        6
   #define controller_string_default_length       7
   #define controller_string_entry_length         5
   #define controller_string_entries_length       7
   #define controller_string_environment_length   11
+  #define controller_string_existing_length      8
   #define controller_string_fail_length          4
   #define controller_string_failsafe_length      8
   #define controller_string_fifo_length          4
@@ -103,6 +108,7 @@ extern "C" {
   #define controller_string_method_length        6
   #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_optional_length      8
@@ -262,7 +268,7 @@ extern "C" {
 #ifndef _di_controller_rule_t_
   enum {
     controller_rule_setting_type_capability = 1,
-    controller_rule_setting_type_control,
+    controller_rule_setting_type_control_group,
     controller_rule_setting_type_define,
     controller_rule_setting_type_environment,
     controller_rule_setting_type_group,
@@ -284,10 +290,11 @@ extern "C" {
   #define controller_rule_option_wait         0x8
 
   // bitwise codes representing properties on controller_rule_t that have been found in the rule file.
-  #define controller_rule_has_group     0x1
-  #define controller_rule_has_nice      0x2
-  #define controller_rule_has_scheduler 0x4
-  #define controller_rule_has_user      0x8
+  #define controller_rule_has_control_group 0x1
+  #define controller_rule_has_group         0x2
+  #define controller_rule_has_nice          0x4
+  #define controller_rule_has_scheduler     0x8
+  #define controller_rule_has_user          0x10
 
   typedef struct {
     f_status_t status;
@@ -306,7 +313,6 @@ extern "C" {
 
     f_string_dynamic_t id;
     f_string_dynamic_t name;
-    f_string_dynamic_t control;
     f_string_dynamic_t path;
     f_string_dynamic_t script;
 
@@ -319,6 +325,7 @@ extern "C" {
     f_string_dynamics_t wish;
 
     f_capability_t capability;
+    f_control_group_t control_group;
     f_int32s_t groups;
     fl_execute_scheduler_t scheduler;
 
@@ -341,7 +348,6 @@ extern "C" {
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
-      f_string_dynamic_t_initialize, \
       f_string_maps_t_initialize, \
       f_string_maps_t_initialize, \
       f_string_dynamics_t_initialize, \
@@ -349,6 +355,7 @@ extern "C" {
       f_string_dynamics_t_initialize, \
       f_string_dynamics_t_initialize, \
       f_capability_t_initialize, \
+      f_control_group_t_initialize, \
       f_int32s_t_initialize, \
       fl_execute_scheduler_t_initialize, \
       controller_rule_items_initialize, \
@@ -357,7 +364,6 @@ extern "C" {
   #define controller_macro_rule_t_delete_simple(rule) \
     fl_string_dynamic_delete(&rule.id); \
     fl_string_dynamic_delete(&rule.name); \
-    fl_string_dynamic_delete(&rule.control); \
     fl_string_dynamic_delete(&rule.path); \
     fl_string_dynamic_delete(&rule.script); \
     f_macro_string_maps_t_delete_simple(rule.define) \
@@ -367,6 +373,7 @@ extern "C" {
     fl_string_dynamics_delete(&rule.want); \
     fl_string_dynamics_delete(&rule.wish); \
     f_capability_delete(&rule.capability); \
+    fl_control_group_delete(&rule.control_group); \
     fl_type_int32s_delete(&rule.groups); \
     controller_macro_rule_items_t_delete_simple(rule.items)
 #endif // _di_controller_rule_t_
index cb6723382256ba6ad6ef6e1a3bddc963d22f51c5..04f6643a66a329d02cc22f0537c8bd56973f932e 100644 (file)
@@ -393,14 +393,19 @@ extern "C" {
 #endif // _di_controller_rule_error_print_
 
 #ifndef _di_controller_rule_error_print_execute_
-  void controller_rule_error_print_execute(const fll_error_print_t output, const bool script_is, const f_string_t name, const int code) {
+  void controller_rule_error_print_execute(const fll_error_print_t output, const bool script_is, const f_string_t name, const int code, const f_status_t status) {
 
     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%s%s%s", output.context.after->string, output.notable.before->string, name ? name : f_string_empty_s, output.notable.after->string);
 
-      if (code) {
+      if (status == F_control_group || 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%c", output.context.before->string, output.context.after->string, f_string_eol_s[0]);
+      }
+      else if (code) {
         fprintf(output.to.stream, "%s' failed with the exit code '", output.context.before->string);
         fprintf(output.to.stream, "%s%s%i%s", output.context.after->string, output.notable.before->string, code, output.notable.after->string);
         fprintf(output.to.stream, "%s'.%s%c", output.context.before->string, output.context.after->string, f_string_eol_s[0]);
@@ -484,14 +489,28 @@ extern "C" {
       as.scheduler = &rule->scheduler;
     }
 
-    if (rule->control.used) {
-      // @todo: as.controls =
+    if (rule->has & controller_rule_has_control_group) {
+      as.control_group = &rule->control_group;
+
+      // make sure all required cgroup directories exist.
+      if (rule->status == F_known_not) {
+        status = fll_control_group_prepare(rule->control_group);
+
+        if (F_status_is_error(status)) {
+          fll_error_print(data->error, F_status_set_fine(status), "fll_control_group_prepare", F_true);
+
+          rule->status = F_status_set_error(F_failure);
+          return status;
+        }
+      }
     }
 
     status = fll_environment_load_names(rule->environment, &environment);
 
     if (F_status_is_error(status)) {
       fll_error_print(data->error, F_status_set_fine(status), "fll_environment_load_names", F_true);
+
+      rule->status = F_status_set_error(F_failure);
       return status;
     }
 
@@ -642,19 +661,21 @@ extern "C" {
     }
 
     if (F_status_is_error(status)) {
-      if (F_status_set_fine(status) == F_failure) {
-        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 = F_status_set_fine(status);
+
+      if (status == F_control_group || status == F_failure || 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 (F_status_set_fine(status) == F_file_found_not) {
+      else if (status == F_file_found_not) {
         controller_rule_error_print_execute_not_found(data->error, F_false, program);
       }
       else {
-        fll_error_print(data->error, F_status_set_fine(status), "fll_execute_program_environment", F_true);
+        fll_error_print(data->error, status, "fll_execute_program", F_true);
       }
 
       data->child = 0;
 
-      return status;
+      return F_status_set_error(status);
     }
 
     // @todo wait for pid file or timeout.
@@ -693,15 +714,19 @@ extern "C" {
     }
 
     if (F_status_is_error(status)) {
-      if (F_status_set_fine(status) == F_failure) {
-        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 = F_status_set_fine(status);
+
+      if (status == F_control_group || status == F_failure || 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 (F_status_set_fine(status) == F_file_found_not) {
+      else if (status == F_file_found_not) {
         controller_rule_error_print_execute_not_found(data->error, F_false, program);
       }
       else {
-        fll_error_print(data->error, F_status_set_fine(status), "fll_execute_program_environment", F_true);
+        fll_error_print(data->error, status, "fll_execute_program", F_true);
       }
+
+      status = F_status_set_error(status);
     }
 
     data->child = 0;
@@ -1361,15 +1386,23 @@ 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->control.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;
 
@@ -1570,7 +1603,6 @@ extern "C" {
       return F_false;
     }
 
-    rule->status = F_none;
     return F_true;
   }
 #endif // _di_controller_rule_read_
@@ -1634,8 +1666,8 @@ extern "C" {
       if (fl_string_dynamic_compare_string(controller_string_capability, 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, cache->name_item, controller_string_control_length) == F_equal_to) {
-        type = controller_rule_setting_type_control;
+      else if (fl_string_dynamic_compare_string(controller_string_control_group, 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) {
         type = controller_rule_setting_type_define;
@@ -1827,11 +1859,107 @@ extern "C" {
         continue;
       }
 
-      if (type == controller_rule_setting_type_control || type == controller_rule_setting_type_name || type == controller_rule_setting_type_path || type == controller_rule_setting_type_script) {
-        if (type == controller_rule_setting_type_control) {
-          setting_value = &rule->control;
+      if (type == controller_rule_setting_type_control_group) {
+
+        if (cache->content_actions.array[i].used < 2 || rule->has & controller_rule_has_control_group) {
+
+          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 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]);
+
+            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_existing, 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) {
+          rule->control_group.as_new = F_true;
+        }
+        else {
+          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 has an unknown option '", 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[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]);
+
+            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;
+        }
+
+        rule->control_group.path.used = 0;
+
+        // @todo path prefix needs to be configurable via a parameter.
+        status = fl_string_append(f_control_group_path_system_prefix, f_control_group_path_system_prefix_length, &rule->control_group.path);
+
+        if (F_status_is_error_not(status)) {
+          status = fl_string_append(f_control_group_path_system_default, f_control_group_path_system_default_length, &rule->control_group.path);
+        }
+
+        if (F_status_is_error(status)) {
+          fll_error_print(data.error, F_status_set_fine(status), "fl_string_append", F_true);
+        }
+        else {
+          rule->control_group.groups.used = 0;
+
+          for (j = 1; j < cache->content_actions.array[i].used; ++j) {
+
+            status = fl_string_dynamics_increase(&rule->control_group.groups);
+
+            if (F_status_is_error(status)) {
+              fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamics_increase", F_true);
+              break;
+            }
+
+            rule->control_group.groups.array[rule->control_group.groups.used].used = 0;
+
+            status = fl_string_dynamic_partial_append_nulless(cache->buffer_item, cache->content_actions.array[i].array[j], &rule->control_group.groups.array[rule->control_group.groups.used]);
+
+            if (F_status_is_error(status)) {
+              fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_partial_append_nulless", F_true);
+              break;
+            }
+
+            rule->control_group.groups.used++;
+          } // for
         }
-        else if (type == controller_rule_setting_type_name) {
+
+        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;
+          }
+
+          rule->control_group.path.used = 0;
+
+          if (F_status_is_error_not(status_return)) {
+            status_return = status;
+          }
+
+          controller_rule_error_print(data.error, *cache, F_false);
+          continue;
+        }
+
+        rule->has |= controller_rule_has_control_group;
+
+        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;
         }
         else if (type == controller_rule_setting_type_path) {
@@ -1857,7 +1985,7 @@ extern "C" {
           continue;
         }
 
-        if (type == controller_rule_setting_type_control || type == controller_rule_setting_type_name || type == controller_rule_setting_type_script) {
+        if (type == controller_rule_setting_type_name || type == controller_rule_setting_type_script) {
 
           status = controller_string_dynamic_rip_nulless_terminated(cache->buffer_item, cache->content_actions.array[i].array[0], setting_value);
 
@@ -1876,12 +2004,7 @@ extern "C" {
             continue;
           }
 
-          if (type == controller_rule_setting_type_control) {
-            // @todo validate that this is a valid path.
-            // @todo append setting.path_control, then path_separator, and then this string.
-            // @todo the control path doesn't have to exist just yet, but print a warning if it doesn't and debug is visible.
-          }
-          else if (type == controller_rule_setting_type_name || type == controller_rule_setting_type_script) {
+          if (type == controller_rule_setting_type_name || type == controller_rule_setting_type_script) {
             status = controller_validate_has_graph(*setting_value);
 
             if (status == F_false || F_status_set_fine(status) == F_complete_not_utf) {
@@ -1952,7 +2075,6 @@ extern "C" {
         continue;
       }
 
-
       if (type == controller_rule_setting_type_scheduler) {
 
         if (cache->content_actions.array[i].used < 1 || cache->content_actions.array[i].used > 2 || rule->has & controller_rule_has_scheduler) {
@@ -2623,9 +2745,19 @@ extern "C" {
       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 %s%c", data.context.set.important.before->string, controller_string_control, data.context.set.important.after->string, rule->control.used ? rule->control.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_path, data.context.set.important.after->string, rule->path.used ? rule->path.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_control_group, 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);
+
+      for (i = 0; i < rule->control_group.groups.used; ++i) {
 
+        if (rule->control_group.groups.array[i].used) {
+          fprintf(data.output.stream, " ");
+          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);
     if (rule->has & controller_rule_has_scheduler) {
index 3f67e1c6c5f67a089c7a3bb3508ccf3f2db38ae3..b5f14ac37fee2807bb62d789be4a50335fad737d 100644 (file)
@@ -164,9 +164,11 @@ extern "C" {
  *   The name of the program or script.
  * @param code
  *   The code returned by the executed program or script.
+ * @param status
+ *   The status code representing the failure (without the error bit set).
  */
 #ifndef _di_controller_rule_error_print_execute_
-  extern void controller_rule_error_print_execute(const fll_error_print_t output, const bool script_is, const f_string_t name, const int code) f_gcc_attribute_visibility_internal;
+  extern void controller_rule_error_print_execute(const fll_error_print_t output, const bool script_is, const f_string_t name, const int code, const f_status_t status) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_rule_error_print_execute_
 
 /**
@@ -206,7 +208,7 @@ extern "C" {
  * @param cache
  *   A structure for containing and caching relevant data.
  * @param index
- *   The position in the setting.rules array representing the rule to simulate.
+ *   The position in the setting.rules array representing the rule to execute.
  * @param type
  *   The action to perform based on the action type codes.
  *
index 5af11e3f95affe7a35a3ff79f442718022cf7c5f..3f875928f99e6b8586b23543a19fbfba5f279e29 100644 (file)
@@ -9,6 +9,7 @@ f_account
 f_capability
 f_color
 f_console
+f_control_group
 f_conversion
 f_directory
 f_environment
@@ -22,11 +23,13 @@ f_print
 f_signal
 fl_color
 fl_console
+fl_control_group
 fl_conversion
 fl_fss
 fl_iki
 fl_string
 fl_type
+fll_control_group
 fll_environment
 fll_error
 fll_execute
index 5e3ed2bff8d96b4980a79a683e7b1d560933af17..d780fc7546e6902ab4e271c75775fa8210551ce5 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_fss -lfll_path -lfll_program -lfll_status -lfl_color -lfl_console -lfl_conversion -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_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_memory -lf_path -lf_pipe -lf_print -lf_signal -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 2cfb52dd6fe52dfc09d6ebecd5e1898142054e78..2efd90816b9dbd5565e4cc56b83ef7df3001a68a 100644 (file)
@@ -11,6 +11,8 @@ main:
   item last
 
 first:
+  consider script require_me
+
   rule script succeed
   rule script php
   rule command multiple
index da9ca3ff84cb7a2563546af2314b8f646ac107de..bb18ec318c44017bf4535eb59d09913efcc3a4b8 100644 (file)
@@ -3,11 +3,21 @@
 setting:
   name "Multiple Commands: id, whoami, date, etc.."
   capability "all="
+  control_group new memory/example
   nice 15
   scheduler batch 0
   #user kevin
   #group list 8 root
 
+  need script require_me
+
+script:
+  start {
+    echo
+    echo "Current cgroup for self (PPID $PPID, PID $$) is: '$(cat /proc/self/cgroup)'"
+    sleep 20
+  }
+
 command:
   start {
     id
index e2671cf93f548d95cceb2c5682031c437ad1a754..bfc0f0b722fb3e49f90dfad4305fed89f93f35ab 100644 (file)
@@ -1,7 +1,7 @@
 # fss-000d
 
 setting:
-  name "Scipt #2"
+  name "Script #2"
   need script succeed
 
 script:
diff --git a/level_3/controller/data/settings/example/rules/script/require_me.rule b/level_3/controller/data/settings/example/rules/script/require_me.rule
new file mode 100644 (file)
index 0000000..2cc1cc8
--- /dev/null
@@ -0,0 +1,14 @@
+# fss-000d
+
+setting:
+  name "Example script for needs, wants, and wishes."
+  environment PATH
+  script sh
+
+script:
+  start {
+    echo
+    echo "This should be included via a need, want, or wish."
+    echo
+  }
+
index 9080c60268afa53d03dc16d049d7970aa81d1420..925df1c55aecbc57d538ab9cb83f70c422ca2c28 100644 (file)
@@ -1,7 +1,7 @@
 # fss-000d
 
 setting:
-  name "Scipt #1"
+  name "Script #1"
   environment PATH
   script sh
 
index 1fdf144b7d70cd5fa09a50bd9c6b49cde971961b..45199d6c40c7d9b1f90926978afd594524c19bb9 100644 (file)
@@ -10,7 +10,7 @@ Rule Documentation:
 
   The "settings" Rule Type has the following FSS-0001 (Extended) Content\:
     "capability": Define a set of capabilities in which to use, using the capability "text" format (such as "= cap_chown+ep").
-    "control": Define a control group (cgroup) in which everything within this rule executes under.
+    "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.
     "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.
@@ -30,6 +30,8 @@ Rule Documentation:
   Due to capabilities only being a draft in the POSIX standard, one may expect "capabilities" support may not be available and in such a case this setting will do nothing.
   If the dependent project (f_capability) does not have libcap support enabled, then capabilities will be unsupported by the compilation of this project.
 
+  In the case of "control", the first argument is either "existing" or "new", where for "existing" the process is run inside the existing control used by the parent and when "new" the process is executed within a new control group namespace entirely.
+
   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 "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.
@@ -75,11 +77,3 @@ Rule Documentation:
   The "create" Content designates that this controller program to create the PID file after successfully starting the service.
   The "use" Content designates that the called program will provide the PID file after successfully starting the service.
   For both "create" and "program" the PID file is expected to only exist on success or failure and the existence thereof designates the success or failure rate.
-
-  The following Content are the same as those specified in the Settings above except that they apply to a specific Rule Item instead of all Rule Items in the file\:
-  - "capability"
-  - "control"
-  - "group"
-  - "nice"
-  - "scheduler"
-  - "user"
index 5df9b62f69b49f971c08273b661aec8b64518a7f..32d1100f7c3a8cff5f04c513b845c14240de73cd 100644 (file)
@@ -29,7 +29,7 @@ Rule Specification:
 
   The "settings" Rule Type has the following FSS-0001 (Extended)\:
     "capability": One Content representing capabilities.
-    "control": One Content 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).
+    "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.
index 00d187de9fb0055ad3617b48cd67cf250562c7a5..079fec4e9703418565e8f46cbdbcf9fd30363aab 100644 (file)
@@ -444,7 +444,7 @@ extern "C" {
       fake_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       0, \
       0, \
index 5f6addddfce0bcc8e6d5d5d5fbb4f834a9816a65..1e259804c01997ec110e020c76f7de0ca6a334de 100644 (file)
@@ -73,7 +73,7 @@ extern "C" {
         }
       }
       else {
-        fll_error_print(data.error, F_status_set_fine(*status), "fll_execute_program_environment", F_true);
+        fll_error_print(data.error, F_status_set_fine(*status), "fll_execute_program", F_true);
       }
     }
 
index 63669465a9cec59649266135cf835d94d9fa4046..5b5a586cde3538ff13afc773949c8f946a00aeb0 100644 (file)
@@ -3834,7 +3834,7 @@ extern "C" {
         }
       }
       else if (F_status_set_fine(status) != F_failure) {
-        fll_error_print(data_make->error, F_status_set_fine(status), "fll_execute_program_environment", F_true);
+        fll_error_print(data_make->error, F_status_set_fine(status), "fll_execute_program", F_true);
       }
     }
 
index 015d5796584983eeead8fbd7e280619b196e5730..61eec4851d136a1bbbacc55770a70e0f47204735 100644 (file)
@@ -21,6 +21,7 @@ f_print
 f_signal
 fl_color
 fl_console
+fl_control_group
 fl_conversion
 fl_directory
 fl_fss
index 4385448590af1cbb43e374ea6d7d13f4eb2ce6b3..e2165c84266f57067f9db3e7dafaf698c484eee0 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_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_memory -lf_path -lf_print -lf_signal -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 2e193f917858eb0288c89e684b0a12a6fbede681..bc442de4fb8fb5f1e6828603595a7e56af3a663b 100644 (file)
@@ -285,7 +285,7 @@ extern "C" {
       firewall_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_string_dynamics_t_initialize, \
       f_string_dynamics_t_initialize, \
index 10b680a69f1a1fc060d1a286fa7da2b3f5cc160d..1d6921f96dd3a151fe7514cfe41182fa0f82c699 100644 (file)
@@ -5,6 +5,7 @@ f_status
 f_memory
 f_string
 f_utf
+f_account
 f_capability
 f_color
 f_console
@@ -18,6 +19,7 @@ f_pipe
 f_print
 fl_color
 fl_console
+fl_control_group
 fl_conversion
 fl_fss
 fl_status
index 185fb9312ea2600fdb0ae38e4118cdeb1df70bbc..1d082a668b17d5293511a1b6e10079b2636afa19 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_conversion -lfl_environment -lfl_fss -lfl_status -lfl_string -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_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_utf
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 build_sources_library firewall.c private-firewall.c
index f8e2782c8854c66c4340cd24dfef3f2fbb4df221..cb96f80e3cf2c8595fb6510522c3664d5a7e7917 100644 (file)
@@ -191,7 +191,7 @@ extern "C" {
       fss_basic_list_read_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_fss_objects_t_initialize, \
index 091c45282b8c53a931094161c8a0005fb6145b68..769355117e0380b2267fe146f21f6b8856d388ce 100644 (file)
@@ -145,7 +145,7 @@ extern "C" {
       fss_basic_list_write_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_string_static_t_initialize, \
       f_color_context_t_initialize, \
index e1df109c65f5d179875ca992613b3e5a655c3d46..a5f8d36fa8322b22ed9a534ade7aa87c5d35074f 100644 (file)
@@ -191,7 +191,7 @@ extern "C" {
       fss_basic_read_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_fss_objects_t_initialize, \
index 086d6ff804ca99c83982f90a25459a9510269259..1f32f26fc3deb066edbac1639e8863730d9b0cb3 100644 (file)
@@ -145,7 +145,7 @@ extern "C" {
       fss_basic_write_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_color_context_t_initialize, \
     }
index 1551fefaf250d3ec35104a6048299ec95cea92de..6970c46ea97a49b32b26644369748ef92bbf3818 100644 (file)
@@ -190,7 +190,7 @@ extern "C" {
       fss_embedded_list_read_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_fss_nest_t_initialize, \
index 9e573889638845eaa3ea7448430d438e13ce666d..3fbf1fcef25843a07c75416b87190d59808e03fd 100644 (file)
@@ -146,7 +146,7 @@ extern "C" {
       fss_embedded_list_write_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_string_static_t_initialize, \
       f_color_context_t_initialize, \
index 79b2929622d4828cf951b7d7df3b916b407590da..becc57dae1dae954eed003ed45ed6e48c48ae25e 100644 (file)
@@ -191,7 +191,7 @@ extern "C" {
       fss_extended_list_read_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_fss_objects_t_initialize, \
index fc4151b2b44b0af05af6367997094072358fb0c1..c75f3a0c56410064dae9c595bcbd9466c8d59e36 100644 (file)
@@ -146,7 +146,7 @@ extern "C" {
       fss_extended_list_write_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_string_static_t_initialize, \
       f_color_context_t_initialize, \
index c9bd1dd3d3bd981f5c4be94ab5b87f5344d0a5ca..261bac8fbd91546ff6f8022733521d8f54859116 100644 (file)
@@ -191,7 +191,7 @@ extern "C" {
       fss_extended_read_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_fss_objects_t_initialize, \
index 9b94f5d32d86dbe0836d55c78d5bd899782944d8..1f83daefd2fd0074c7ac4267b46e4675daca6efe 100644 (file)
@@ -145,7 +145,7 @@ extern "C" {
       fss_extended_write_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_string_static_t_initialize, \
       f_color_context_t_initialize, \
index 20af5677e0ed9f13cf8bf8c2ed6c036adcc536f5..7abe8030ffc091a11730413ca3ac7b7860c9278d 100644 (file)
@@ -121,7 +121,7 @@ extern "C" {
       fss_status_code_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_color_context_t_initialize, \
     }
index 23c1a9eda9ad48cfb01005b295492b01668feb74..f279233cd790a69f2f7d2fe4480915be4cb25bab 100644 (file)
@@ -257,7 +257,7 @@ extern "C" {
       iki_read_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       0, \
       0, \
index 1bddce4bf9f09428ea1381578fc90fe1baa76991..92ef6d5b14b6d4c3d8f4869431a31a4a7ea774f9 100644 (file)
@@ -136,7 +136,7 @@ extern "C" {
       iki_write_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_color_context_t_initialize, \
index 84979cb23cdc532acde519eee09d135ac22834c8..da14e42aa868965128dad2a2483740b554c3d8de 100644 (file)
@@ -260,7 +260,7 @@ extern "C" {
     { \
       init_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       0, \
       f_signal_t_initialize, \
index ab1222507ee0094b24a10febd7839e2b02852539..ccba53b19e3e14017ca58acff1579bdd68e29dd2 100644 (file)
@@ -120,7 +120,7 @@ extern "C" {
       status_code_console_parameter_t_initialize, \
       f_string_lengths_t_initialize, \
       F_false, \
-      f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+      f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
       fll_error_print_t_initialize, \
       f_color_context_t_initialize, \
     }