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