]> Kevux Git Server - fll/commitdiff
Feature: Add missing function f_environment_get_all().
authorKevin Day <thekevinday@gmail.com>
Sat, 9 Jul 2022 16:27:09 +0000 (11:27 -0500)
committerKevin Day <thekevinday@gmail.com>
Sat, 9 Jul 2022 16:27:09 +0000 (11:27 -0500)
A get all environment variables function should exist.
The POSIX/libc standards do not seem to provide one.

Utilize the "environ" variable to load all of the environment variables into a string map array.

level_0/f_environment/c/environment.c
level_0/f_environment/c/environment.h
level_0/f_environment/data/build/settings-tests
level_0/f_environment/tests/unit/c/test-environment-get_all.c [new file with mode: 0644]
level_0/f_environment/tests/unit/c/test-environment-get_all.h [new file with mode: 0644]
level_0/f_environment/tests/unit/c/test-environment.c
level_0/f_environment/tests/unit/c/test-environment.h

index 9f77e758a0a640d1278375be9d9910a1ee954a1b..64b186641880ae564c37c8c39e678abacc52b55c 100644 (file)
@@ -4,6 +4,9 @@
 extern "C" {
 #endif
 
+// for loading all current environment variables.
+extern char **environ;
+
 #ifndef _di_f_environment_clear_
   f_status_t f_environment_clear(void) {
 
@@ -69,6 +72,42 @@ extern "C" {
   }
 #endif // _di_f_environment_get_
 
+#ifndef _di_f_environment_get_all_
+  f_status_t f_environment_get_all(f_string_maps_t * const environment) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!environment) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    f_status_t status = F_none;
+    char *at = 0;
+    f_string_map_t map = f_string_map_t_initialize;
+
+    // Copy all environment variables over when a custom define is used.
+    for (char **string = environ; *string; string++) {
+
+      map.name.string = 0;
+      map.value.string = 0;
+
+      map.name.used = 0;
+      map.value.used = 0;
+
+      at = index(*string, f_string_ascii_equal_s.string[0]);
+      if (!at || at == *string) continue;
+
+      map.name.string = *string;
+      map.name.used = at - *string;
+
+      map.value.string = at + 1;
+      map.value.used = strlen(at + 1);
+
+      status = f_string_maps_append(map, environment);
+      if (F_status_is_error(status)) return status;
+    } // for
+
+    return F_none;
+  }
+#endif // _di_f_environment_get_all_
+
 #ifndef _di_f_environment_secure_is_
   f_status_t f_environment_secure_is(void) {
 
index 92f03be51882aa5a62c61e634eddf3d2a1080abd..e00fcf10142868da102cec79b7b34c0eeb8ab8f5 100644 (file)
@@ -103,6 +103,27 @@ extern "C" {
 #endif // _di_f_environment_get_
 
 /**
+ * Get all environment variables.
+ *
+ * The variables are copied into a new dynamically allocated map and is safe to alter.
+ *
+ * @param environment
+ *   An array of maps containing all available environment variable name and value pairs.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_string_maps_append().
+ *
+ * @see f_string_maps_append()
+ */
+#ifndef _di_f_environment_get_all_
+  extern f_status_t f_environment_get_all(f_string_maps_t * const environment);
+#endif // _di_f_environment_get_all_
+
+/**
  * Check to see if the environment is secure for calling getenv() safely for "secure execution".
  *
  * This is intended to closely mimic the checks secure_getenv().
index 654d7def105e75f47ed8e9a28dbc81306dc22e84..212b25812ffc1629d0b2307ced18194a70590a36 100644 (file)
@@ -25,7 +25,7 @@ build_language c
 build_libraries -lc -lcmocka
 build_libraries-individual -lf_memory -lf_string -lf_environment
 
-build_sources_program test-environment-clear.c test-environment-exists.c test-environment-get.c test-environment-secure_is.c test-environment-set.c test-environment-unset.c
+build_sources_program test-environment-clear.c test-environment-exists.c test-environment-get.c test-environment-get_all.c test-environment-secure_is.c test-environment-set.c test-environment-unset.c
 build_sources_program test-environment.c
 
 build_script no
diff --git a/level_0/f_environment/tests/unit/c/test-environment-get_all.c b/level_0/f_environment/tests/unit/c/test-environment-get_all.c
new file mode 100644 (file)
index 0000000..84fe615
--- /dev/null
@@ -0,0 +1,42 @@
+#include "test-environment.h"
+#include "test-environment-get.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_environment_get_all__parameter_checking(void **state) {
+
+  {
+    const f_status_t status = f_environment_get_all(0);
+
+    assert_int_equal(status, F_status_set_error(F_parameter));
+  }
+}
+
+void test__f_environment_get_all__works(void **state) {
+
+  const f_string_static_t name = macro_f_string_static_t_initialize("test", 0, 4);
+  const f_string_static_t value = macro_f_string_static_t_initialize("works", 0, 5);
+
+  f_string_maps_t environment = f_string_maps_t_initialize;
+
+  {
+    // Cannot easily mock because this is used: extern char **environ;
+    clearenv();
+    setenv(name.string, value.string, true);
+
+    const f_status_t status = f_environment_get_all(&environment);
+
+    assert_int_equal(status, F_none);
+    assert_int_equal(environment.used, 1);
+    assert_string_equal(environment.array[0].name.string, name.string);
+    assert_string_equal(environment.array[0].value.string, value.string);
+  }
+
+  f_string_maps_resize(0, &environment);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_environment/tests/unit/c/test-environment-get_all.h b/level_0/f_environment/tests/unit/c/test-environment-get_all.h
new file mode 100644 (file)
index 0000000..4d77ef2
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Environment
+ * API Version: 0.6
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the environment project.
+ */
+#ifndef _TEST__F_environment_get_all_h
+#define _TEST__F_environment_get_all_h
+
+/**
+ * Test that parameter checking works as expected.
+ *
+ * @see f_environment_get_all()
+ */
+extern void test__f_environment_get_all__parameter_checking(void **state);
+
+/**
+ * Test that function works.
+ *
+ * @see f_environment_get_all()
+ */
+extern void test__f_environment_get_all__works(void **state);
+
+#endif // _TEST__F_environment_get_all_h
index 8096ba7f0c16cb0aa8af1fa60df1702af92fa850..21986a413f21538af32a57ec4f33df40b2bcb97c 100644 (file)
@@ -30,6 +30,8 @@ int main(void) {
     cmocka_unit_test(test__f_environment_get__returns_data_not),
     cmocka_unit_test(test__f_environment_get__works),
 
+    cmocka_unit_test(test__f_environment_get_all__works),
+
     cmocka_unit_test(test__f_environment_secure_is__fails),
     cmocka_unit_test(test__f_environment_secure_is__works),
 
@@ -45,6 +47,7 @@ int main(void) {
       // f_environment_clear() doesn't use parameter checking.
       // f_environment_exists() doesn't use parameter checking.
       cmocka_unit_test(test__f_environment_get__parameter_checking),
+      cmocka_unit_test(test__f_environment_get_all__parameter_checking),
       // f_environment_secure_is() doesn't use parameter checking.
       // f_environment_set() doesn't use parameter checking.
       // f_environment_unset() doesn't use parameter checking.
index 62b2eab3012203953aef258db06378edb56bede8..b66d791e9f324b583194d26791a645ec59030be9 100644 (file)
@@ -29,6 +29,7 @@
 #include "test-environment-clear.h"
 #include "test-environment-exists.h"
 #include "test-environment-get.h"
+#include "test-environment-get_all.h"
 #include "test-environment-secure_is.h"
 #include "test-environment-set.h"
 #include "test-environment-unset.h"