Blame SOURCES/0027-lib-add-authselect_profile_features-to-list-supporte.patch

1756dc
From 3935dd9f2ac3aab9027783e45f499401476f52cd Mon Sep 17 00:00:00 2001
1756dc
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
1756dc
Date: Mon, 19 Nov 2018 15:04:42 +0100
1756dc
Subject: [PATCH 09/15] lib: add authselect_profile_features to list supported
1756dc
 features
1756dc
1756dc
The feature list is automatically obtained from profile's template files.
1756dc
1756dc
Related to:
1756dc
https://github.com/pbrezina/authselect/issues/107
1756dc
---
1756dc
 include/authselect.h         | 12 +++++
1756dc
 src/lib/authselect_profile.c | 51 ++++++++++++++++++++++
1756dc
 src/lib/util/string_array.c  | 36 +++++++++++++++
1756dc
 src/lib/util/string_array.h  | 20 +++++++++
1756dc
 src/lib/util/template.c      | 85 ++++++++++++++++++++++++++++++++++--
1756dc
 src/lib/util/template.h      | 11 +++++
1756dc
 6 files changed, 211 insertions(+), 4 deletions(-)
1756dc
1756dc
diff --git a/include/authselect.h b/include/authselect.h
1756dc
index d52d460e38132cf81e8a03b88a530c634a2c8937..462f54291e8283d5778005ac1747dd03258584be 100644
1756dc
--- a/include/authselect.h
1756dc
+++ b/include/authselect.h
1756dc
@@ -273,6 +273,18 @@ char **
1756dc
 authselect_profile_nsswitch_maps(const struct authselect_profile *profile,
1756dc
                                  const char **features);
1756dc
 
1756dc
+/**
1756dc
+ * List features supported by the profile.
1756dc
+ *
1756dc
+ * It is necessary to free the returned pointer with @authselect_array_free.
1756dc
+ *
1756dc
+ * @param profile    Pointer to structure obtained by @authselect_profile.
1756dc
+ *
1756dc
+ * @return NULL-terminated array of supported features, NULL on error.
1756dc
+ */
1756dc
+char **
1756dc
+authselect_profile_features(const struct authselect_profile *profile);
1756dc
+
1756dc
 /**
1756dc
  * Free authconfig_profile structure obtained by @authselect_profile.
1756dc
  *
1756dc
diff --git a/src/lib/authselect_profile.c b/src/lib/authselect_profile.c
1756dc
index 8a12a082802fbc4f3c8cb3af7379ad26372dcc0c..d0cf17b8b7a414a41427c88039687725dcf1a560 100644
1756dc
--- a/src/lib/authselect_profile.c
1756dc
+++ b/src/lib/authselect_profile.c
1756dc
@@ -115,6 +115,57 @@ authselect_profile_nsswitch_maps(const struct authselect_profile *profile,
1756dc
     return maps;
1756dc
 }
1756dc
 
1756dc
+_PUBLIC_ char **
1756dc
+authselect_profile_features(const struct authselect_profile *profile)
1756dc
+{
1756dc
+    char **features;
1756dc
+    char **array;
1756dc
+    errno_t ret;
1756dc
+    int i;
1756dc
+
1756dc
+    if (profile == NULL) {
1756dc
+        return NULL;
1756dc
+    }
1756dc
+
1756dc
+    features = string_array_create(10);
1756dc
+    if (features == NULL) {
1756dc
+        ERROR("Unable to create array (out of memory)");
1756dc
+        return NULL;
1756dc
+    }
1756dc
+
1756dc
+    struct authselect_generated files[] = PROFILE_FILES(profile->files);
1756dc
+
1756dc
+    for (i = 0; files[i].path != NULL; i++) {
1756dc
+        array = template_list_features(files[i].content);
1756dc
+        if (array == NULL) {
1756dc
+            ERROR("Unable to obtain feature list (out of memory)");
1756dc
+            ret = ENOMEM;
1756dc
+            goto done;
1756dc
+        }
1756dc
+
1756dc
+        features = string_array_concat(features, array, true);
1756dc
+        string_array_free(array);
1756dc
+
1756dc
+        if (features == NULL) {
1756dc
+            ERROR("Unable to obtain feature list (out of memory)");
1756dc
+            ret = ENOMEM;
1756dc
+            goto done;
1756dc
+        }
1756dc
+    }
1756dc
+
1756dc
+    string_array_sort(features);
1756dc
+
1756dc
+    ret = EOK;
1756dc
+
1756dc
+done:
1756dc
+    if (ret != EOK) {
1756dc
+        string_array_free(features);
1756dc
+        return NULL;
1756dc
+    }
1756dc
+
1756dc
+    return features;
1756dc
+}
1756dc
+
1756dc
 _PUBLIC_ void
1756dc
 authselect_profile_free(struct authselect_profile *profile)
1756dc
 {
1756dc
diff --git a/src/lib/util/string_array.c b/src/lib/util/string_array.c
1756dc
index a074e23ee504792da7f1a9262e15c549de5747d3..43e30d0008b5709f97da9c43f8f2c28ef2475df5 100644
1756dc
--- a/src/lib/util/string_array.c
1756dc
+++ b/src/lib/util/string_array.c
1756dc
@@ -159,3 +159,39 @@ string_array_del_value(char **array, const char *value)
1756dc
 
1756dc
     return array;
1756dc
 }
1756dc
+
1756dc
+char **
1756dc
+string_array_concat(char **to, char **items, bool unique)
1756dc
+{
1756dc
+    int i;
1756dc
+
1756dc
+    if (items == NULL) {
1756dc
+        return to;
1756dc
+    }
1756dc
+
1756dc
+    for (i = 0; items[i] != NULL; i++) {
1756dc
+        to = string_array_add_value(to, items[i], unique);
1756dc
+        if (to == NULL) {
1756dc
+            return NULL;
1756dc
+        }
1756dc
+    }
1756dc
+
1756dc
+    return to;
1756dc
+}
1756dc
+
1756dc
+static int
1756dc
+string_array_sort_callback(const void *a, const void *b)
1756dc
+{
1756dc
+    return strcmp(*(char* const*)a, *(char* const*)b);
1756dc
+}
1756dc
+
1756dc
+void
1756dc
+string_array_sort(char **array)
1756dc
+{
1756dc
+    if (array == NULL) {
1756dc
+        return;
1756dc
+    }
1756dc
+
1756dc
+    qsort(array, string_array_count(array), sizeof(char *),
1756dc
+          string_array_sort_callback);
1756dc
+}
1756dc
diff --git a/src/lib/util/string_array.h b/src/lib/util/string_array.h
1756dc
index 9545685b2553228a109ab51e7c6a0fd16698fa3e..06aa46c008058163e5557d51e18258fa4e9a1523 100644
1756dc
--- a/src/lib/util/string_array.h
1756dc
+++ b/src/lib/util/string_array.h
1756dc
@@ -118,4 +118,24 @@ string_array_add_value(char **array, const char *value, bool unique);
1756dc
 char **
1756dc
 string_array_del_value(char **array, const char *value);
1756dc
 
1756dc
+/**
1756dc
+ * Concatenate two array. Array @items values will be appended to arra @to.
1756dc
+ *
1756dc
+ * @param to    NULL-terminated destination array.
1756dc
+ * @param items NULL-terminated array to be appended into @to.
1756dc
+ * @param unique If true, value will not be added if it is already present.
1756dc
+ *
1756dc
+ * @return Array or NULL if reallocation fails.
1756dc
+ */
1756dc
+char **
1756dc
+string_array_concat(char **to, char **items, bool unique);
1756dc
+
1756dc
+/**
1756dc
+ * Alphabetically sort a NULL-terminated string array.
1756dc
+ *
1756dc
+ * @param array NULL-terminated string array.
1756dc
+ */
1756dc
+void
1756dc
+string_array_sort(char **array);
1756dc
+
1756dc
 #endif /* _STRING_ARRAY_H_ */
1756dc
diff --git a/src/lib/util/template.c b/src/lib/util/template.c
1756dc
index e38d1d7f1db2c90f1281e97f3ebbdd9d9d1a935d..fb373c0fd83e04c6c78d5f57d3d8e50e54c0377b 100644
1756dc
--- a/src/lib/util/template.c
1756dc
+++ b/src/lib/util/template.c
1756dc
@@ -325,10 +325,27 @@ template_process_matches(const char *match_string,
1756dc
         return ret;
1756dc
     }
1756dc
 
1756dc
-    *_op = op;
1756dc
-    *_feature = feature;
1756dc
-    *_if_true = if_true;
1756dc
-    *_if_false = if_false;
1756dc
+    if (_op != NULL) {
1756dc
+        *_op = op;
1756dc
+    }
1756dc
+
1756dc
+    if (_feature != NULL) {
1756dc
+        *_feature = feature;
1756dc
+    } else {
1756dc
+        free(feature);
1756dc
+    }
1756dc
+
1756dc
+    if (_if_true != NULL) {
1756dc
+        *_if_true = if_true;
1756dc
+    } else {
1756dc
+        free(if_true);
1756dc
+    }
1756dc
+
1756dc
+    if (_if_false != NULL) {
1756dc
+        *_if_false = if_false;
1756dc
+    } else {
1756dc
+        free(if_false);
1756dc
+    }
1756dc
 
1756dc
     return EOK;
1756dc
 }
1756dc
@@ -478,6 +495,66 @@ template_generate_preamble()
1756dc
     return preamble;
1756dc
 }
1756dc
 
1756dc
+char **
1756dc
+template_list_features(const char *template)
1756dc
+{
1756dc
+    regmatch_t m[RE_MATCHES];
1756dc
+    const char *match_string;
1756dc
+    char **features;
1756dc
+    char *feature;
1756dc
+    regex_t regex;
1756dc
+    errno_t ret;
1756dc
+    int reret;
1756dc
+
1756dc
+    features = string_array_create(10);
1756dc
+    if (features == NULL) {
1756dc
+        return NULL;
1756dc
+    }
1756dc
+
1756dc
+    if (template == NULL) {
1756dc
+        return features;
1756dc
+    }
1756dc
+
1756dc
+    reret = regcomp(&regex, OP_RE, REG_EXTENDED | REG_NEWLINE);
1756dc
+    if (reret != REG_NOERROR) {
1756dc
+        ERROR("Unable to compile regular expression: regex error %d", reret);
1756dc
+        ret = EFAULT;
1756dc
+        goto done;
1756dc
+    }
1756dc
+
1756dc
+    match_string = template;
1756dc
+    while ((reret = regexec(&regex, match_string, RE_MATCHES, m, 0)) == REG_NOERROR) {
1756dc
+        ret = template_process_matches(match_string, m, NULL, &feature,
1756dc
+                                       NULL, NULL);
1756dc
+        if (ret != EOK) {
1756dc
+            ERROR("Unable to process match [%d]: %s", ret, strerror(ret));
1756dc
+            goto done;
1756dc
+        }
1756dc
+
1756dc
+        features = string_array_add_value(features, feature, true);
1756dc
+        free(feature);
1756dc
+
1756dc
+        match_string += m[0].rm_eo;
1756dc
+    }
1756dc
+
1756dc
+    if (reret != REG_NOMATCH) {
1756dc
+        ERROR("Unable to search string: regex error %d", reret);
1756dc
+        ret = EFAULT;
1756dc
+        goto done;
1756dc
+    }
1756dc
+
1756dc
+    ret = EOK;
1756dc
+
1756dc
+done:
1756dc
+    if (ret != EOK) {
1756dc
+        string_array_free(features);
1756dc
+        return NULL;
1756dc
+    }
1756dc
+
1756dc
+    regfree(&regex);
1756dc
+    return features;
1756dc
+}
1756dc
+
1756dc
 errno_t
1756dc
 template_write(const char *filepath,
1756dc
                const char *content,
1756dc
diff --git a/src/lib/util/template.h b/src/lib/util/template.h
1756dc
index 57e076c257a8cdcbc9c2c8f4f5266b4c21f27941..1c412dcf15a7f0d5a5897b78b8b52ff67b7c3f95 100644
1756dc
--- a/src/lib/util/template.h
1756dc
+++ b/src/lib/util/template.h
1756dc
@@ -37,6 +37,17 @@ char *
1756dc
 template_generate(const char *template,
1756dc
                   const char **features);
1756dc
 
1756dc
+/**
1756dc
+ * Find all features available withint the @template and return them in
1756dc
+ * NULL-terminated array.
1756dc
+ *
1756dc
+ * @param template    Template.
1756dc
+ *
1756dc
+ * @return List of features in NULL-terminated array or NULL on error.
1756dc
+ */
1756dc
+char **
1756dc
+template_list_features(const char *template);
1756dc
+
1756dc
 /**
1756dc
  * Write generated file preamble together with its content to a file.
1756dc
  * If the file does not exist, it is created, otherwise its content
1756dc
-- 
1756dc
2.17.2
1756dc