]> granicus.if.org Git - sudo/commitdiff
Move string list functions to their own file.
authorTodd C. Miller <Todd.Miller@sudo.ws>
Mon, 27 Aug 2018 01:48:14 +0000 (19:48 -0600)
committerTodd C. Miller <Todd.Miller@sudo.ws>
Mon, 27 Aug 2018 01:48:14 +0000 (19:48 -0600)
MANIFEST
plugins/sudoers/Makefile.in
plugins/sudoers/cvtsudoers.c
plugins/sudoers/cvtsudoers.h
plugins/sudoers/cvtsudoers_ldif.c
plugins/sudoers/cvtsudoers_pwutil.c
plugins/sudoers/strlist.c [new file with mode: 0644]
plugins/sudoers/strlist.h [new file with mode: 0644]

index f2e81be2074431fd65a70d548bf0b0addb0950ba..105030924a22eea5f1425fc7422878f9beb3db08 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -643,6 +643,8 @@ plugins/sudoers/solaris_audit.c
 plugins/sudoers/solaris_audit.h
 plugins/sudoers/sssd.c
 plugins/sudoers/starttime.c
+plugins/sudoers/strlist.c
+plugins/sudoers/strlist.h
 plugins/sudoers/stubs.c
 plugins/sudoers/sudo_ldap.h
 plugins/sudoers/sudo_ldap_conf.h
index e090bea0b6428bdd8e62d029d3afd4a35f0ca1ec..9a2e1e1847a6aecb3ba05979905c260c4c9a3e63 100644 (file)
@@ -164,8 +164,8 @@ VISUDO_OBJS = editor.lo find_path.lo goodpath.lo locale.lo stubs.o \
              sudo_printf.o visudo.o
 
 CVTSUDOERS_OBJS = cvtsudoers.o cvtsudoers_json.o cvtsudoers_ldif.o \
-                 cvtsudoers_pwutil.o fmtsudoers.lo locale.lo stubs.o \
-                 sudo_printf.o ldap_util.lo
+                 cvtsudoers_pwutil.o fmtsudoers.lo locale.lo \
+                 strlist.o stubs.o sudo_printf.o ldap_util.lo
 
 REPLAY_OBJS = getdate.o sudoreplay.o iolog_util.lo
 
@@ -752,9 +752,10 @@ cvtsudoers.o: $(srcdir)/cvtsudoers.c $(devdir)/def_data.h $(devdir)/gram.h \
               $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
               $(incdir)/sudo_util.h $(srcdir)/cvtsudoers.h \
               $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
-              $(srcdir)/redblack.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
-              $(srcdir)/sudoers_debug.h $(srcdir)/sudoers_version.h \
-              $(top_builddir)/config.h $(top_builddir)/pathnames.h
+              $(srcdir)/redblack.h $(srcdir)/strlist.h $(srcdir)/sudo_nss.h \
+              $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+              $(srcdir)/sudoers_version.h $(top_builddir)/config.h \
+              $(top_builddir)/pathnames.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/cvtsudoers.c
 cvtsudoers_json.o: $(srcdir)/cvtsudoers_json.c $(devdir)/def_data.h \
                    $(devdir)/gram.h $(incdir)/compat/stdbool.h \
@@ -763,9 +764,10 @@ cvtsudoers_json.o: $(srcdir)/cvtsudoers_json.c $(devdir)/def_data.h \
                    $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
                    $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
                    $(srcdir)/cvtsudoers.h $(srcdir)/defaults.h \
-                   $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/sudo_nss.h \
-                   $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
-                   $(top_builddir)/config.h $(top_builddir)/pathnames.h
+                   $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/strlist.h \
+                   $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+                   $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+                   $(top_builddir)/pathnames.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/cvtsudoers_json.c
 cvtsudoers_ldif.o: $(srcdir)/cvtsudoers_ldif.c $(devdir)/def_data.h \
                    $(devdir)/gram.h $(incdir)/compat/stdbool.h \
@@ -775,10 +777,10 @@ cvtsudoers_ldif.o: $(srcdir)/cvtsudoers_ldif.c $(devdir)/def_data.h \
                    $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
                    $(incdir)/sudo_util.h $(srcdir)/cvtsudoers.h \
                    $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
-                   $(srcdir)/redblack.h $(srcdir)/sudo_ldap.h \
-                   $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
-                   $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
-                   $(top_builddir)/pathnames.h
+                   $(srcdir)/redblack.h $(srcdir)/strlist.h \
+                   $(srcdir)/sudo_ldap.h $(srcdir)/sudo_nss.h \
+                   $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+                   $(top_builddir)/config.h $(top_builddir)/pathnames.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/cvtsudoers_ldif.c
 cvtsudoers_pwutil.o: $(srcdir)/cvtsudoers_pwutil.c $(devdir)/def_data.h \
                      $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
@@ -787,9 +789,10 @@ cvtsudoers_pwutil.o: $(srcdir)/cvtsudoers_pwutil.c $(devdir)/def_data.h \
                      $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
                      $(incdir)/sudo_util.h $(srcdir)/cvtsudoers.h \
                      $(srcdir)/defaults.h $(srcdir)/logging.h \
-                     $(srcdir)/parse.h $(srcdir)/pwutil.h $(srcdir)/sudo_nss.h \
-                     $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
-                     $(top_builddir)/config.h $(top_builddir)/pathnames.h
+                     $(srcdir)/parse.h $(srcdir)/pwutil.h $(srcdir)/strlist.h \
+                     $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+                     $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+                     $(top_builddir)/pathnames.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/cvtsudoers_pwutil.c
 dce.lo: $(authdir)/dce.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
         $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
@@ -1275,6 +1278,11 @@ starttime.lo: $(srcdir)/starttime.c $(devdir)/def_data.h \
               $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
               $(top_builddir)/config.h $(top_builddir)/pathnames.h
        $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/starttime.c
+strlist.o: $(srcdir)/strlist.c $(incdir)/compat/stdbool.h \
+           $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+           $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/strlist.h \
+           $(srcdir)/sudoers_debug.h $(top_builddir)/config.h
+       $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/strlist.c
 stubs.o: $(srcdir)/stubs.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
          $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
          $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
index a2881f0d738962c53d254e525911d802c4350a4b..3adf5215302f19ef791d2b4af7353a638148f2d4 100644 (file)
@@ -548,7 +548,7 @@ cvtsudoers_parse_filter(char *expression)
         *      user=foo,group=bar,host=baz
         */
        char *keyword;
-       struct cvtsudoers_string *s;
+       struct sudoers_string *s;
 
        if ((s = malloc(sizeof(*s))) == NULL) {
            sudo_fatalx(U_("%s: %s"), __func__,
@@ -581,65 +581,6 @@ cvtsudoers_parse_filter(char *expression)
     debug_return_bool(true);
 }
 
-struct cvtsudoers_string *
-cvtsudoers_string_alloc(const char *s)
-{
-    struct cvtsudoers_string *cs;
-    debug_decl(cvtsudoers_string_alloc, SUDOERS_DEBUG_UTIL)
-
-    if ((cs = malloc(sizeof(*cs))) != NULL) {
-       if ((cs->str = strdup(s)) == NULL) {
-           free(cs);
-           cs = NULL;
-       }
-    }
-
-    debug_return_ptr(cs);
-}
-
-void
-cvtsudoers_string_free(struct cvtsudoers_string *cs)
-{
-    if (cs != NULL) {
-       free(cs->str);
-       free(cs);
-    }
-}
-
-struct cvtsudoers_str_list *
-str_list_alloc(void)
-{
-    struct cvtsudoers_str_list *strlist;
-    debug_decl(str_list_alloc, SUDOERS_DEBUG_UTIL)
-
-    strlist = malloc(sizeof(*strlist));
-    if (strlist != NULL) {
-       STAILQ_INIT(strlist);
-       strlist->refcnt = 1;
-    }
-
-    debug_return_ptr(strlist);
-}
-
-void
-str_list_free(void *v)
-{
-    struct cvtsudoers_str_list *strlist = v;
-    struct cvtsudoers_string *first;
-    debug_decl(str_list_free, SUDOERS_DEBUG_UTIL)
-
-    if (strlist != NULL) {
-       if (--strlist->refcnt == 0) {
-           while ((first = STAILQ_FIRST(strlist)) != NULL) {
-               STAILQ_REMOVE_HEAD(strlist, entries);
-               cvtsudoers_string_free(first);
-           }
-           free(strlist);
-       }
-    }
-    debug_return;
-}
-
 static bool
 parse_sudoers(const char *input_file, struct cvtsudoers_config *conf)
 {
@@ -680,7 +621,7 @@ static bool
 userlist_matches_filter(struct sudoers_parse_tree *parse_tree,
     struct member_list *users, struct cvtsudoers_config *conf)
 {
-    struct cvtsudoers_string *s;
+    struct sudoers_string *s;
     struct member *m, *next;
     bool ret = false;
     debug_decl(userlist_matches_filter, SUDOERS_DEBUG_UTIL)
@@ -755,7 +696,7 @@ static bool
 hostlist_matches_filter(struct sudoers_parse_tree *parse_tree,
     struct member_list *hostlist, struct cvtsudoers_config *conf)
 {
-    struct cvtsudoers_string *s;
+    struct sudoers_string *s;
     struct member *m, *next;
     char *lhost, *shost;
     bool ret = false;
index 1826b84637f397471946b9106ed704e2bd346d50..8d6d48407b0f4bce2b4197a3537044268a4bf01e 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef SUDOERS_CVTSUDOERS_H
 #define SUDOERS_CVTSUDOERS_H
 
+#include "strlist.h"
+
 /* Supported input/output formats. */
 enum sudoers_formats {
     format_json,
@@ -24,19 +26,6 @@ enum sudoers_formats {
     format_sudoers
 };
 
-/*
- * Simple string list with optional reference count.
- */
-struct cvtsudoers_string {
-    STAILQ_ENTRY(cvtsudoers_string) entries;
-    char *str;
-};
-struct cvtsudoers_str_list {
-    struct cvtsudoers_string *stqh_first;
-    struct cvtsudoers_string **stqh_last;
-    unsigned int refcnt;
-};
-
 /* Flags for cvtsudoers_config.defaults */
 #define CVT_DEFAULTS_GLOBAL    0x01
 #define CVT_DEFAULTS_USER      0x02
@@ -81,17 +70,13 @@ struct cvtsudoers_conf_table {
 };
 
 struct cvtsudoers_filter {
-    struct cvtsudoers_str_list users;
-    struct cvtsudoers_str_list groups;
-    struct cvtsudoers_str_list hosts;
+    struct sudoers_str_list users;
+    struct sudoers_str_list groups;
+    struct sudoers_str_list hosts;
 };
 
 /* cvtsudoers.c */
 extern struct cvtsudoers_filter *filters;
-struct cvtsudoers_str_list *str_list_alloc(void);
-void str_list_free(void *v);
-struct cvtsudoers_string *cvtsudoers_string_alloc(const char *s);
-void cvtsudoers_string_free(struct cvtsudoers_string *ls);
 
 /* cvtsudoers_json.c */
 bool convert_sudoers_json(struct sudoers_parse_tree *parse_tree, const char *output_file, struct cvtsudoers_config *conf);
index f9cd522fd13a2ca93e9b83e23483e6477a0d804a..2d5d2edaeb35002c32c2e4f9abb71be5ed83fb81 100644 (file)
@@ -661,12 +661,12 @@ struct sudo_role {
     char *notbefore;
     char *notafter;
     double order;
-    struct cvtsudoers_str_list *cmnds;
-    struct cvtsudoers_str_list *hosts;
-    struct cvtsudoers_str_list *users;
-    struct cvtsudoers_str_list *runasusers;
-    struct cvtsudoers_str_list *runasgroups;
-    struct cvtsudoers_str_list *options;
+    struct sudoers_str_list *cmnds;
+    struct sudoers_str_list *hosts;
+    struct sudoers_str_list *users;
+    struct sudoers_str_list *runasusers;
+    struct sudoers_str_list *runasgroups;
+    struct sudoers_str_list *options;
 };
 STAILQ_HEAD(sudo_role_list, sudo_role);
 
@@ -771,23 +771,23 @@ ldif_parse_attribute(char *str)
 }
 
 /*
- * Allocate a struct cvtsudoers_string, store str in it and
+ * Allocate a struct sudoers_string, store str in it and
  * insert into the specified strlist.
  */
 static void
-ldif_store_string(const char *str, struct cvtsudoers_str_list *strlist, bool sorted)
+ldif_store_string(const char *str, struct sudoers_str_list *strlist, bool sorted)
 {
-    struct cvtsudoers_string *ls;
+    struct sudoers_string *ls;
     debug_decl(ldif_store_string, SUDOERS_DEBUG_UTIL)
 
-    if ((ls = cvtsudoers_string_alloc(str)) == NULL) {
+    if ((ls = sudoers_string_alloc(str)) == NULL) {
        sudo_fatalx(U_("%s: %s"), __func__,
            U_("unable to allocate memory"));
     }
     if (!sorted) {
        STAILQ_INSERT_TAIL(strlist, ls, entries);
     } else {
-       struct cvtsudoers_string *prev, *next;
+       struct sudoers_string *prev, *next;
 
        /* Insertion sort, list is small. */
        prev = STAILQ_FIRST(strlist);
@@ -808,13 +808,13 @@ ldif_store_string(const char *str, struct cvtsudoers_str_list *strlist, bool sor
 
 /*
  * Iterator for sudo_ldap_role_to_priv().
- * Takes a pointer to a struct cvtsudoers_string *.
+ * Takes a pointer to a struct sudoers_string *.
  * Returns the string or NULL if we've reached the end.
  */
 static char *
-cvtsudoers_string_iter(void **vp)
+sudoers_string_iter(void **vp)
 {
-    struct cvtsudoers_string *ls = *vp;
+    struct sudoers_string *ls = *vp;
 
     if (ls == NULL)
        return NULL;
@@ -840,10 +840,10 @@ role_order_cmp(const void *va, const void *vb)
  */
 static void
 ldif_store_options(struct sudoers_parse_tree *parse_tree,
-    struct cvtsudoers_str_list *options)
+    struct sudoers_str_list *options)
 {
     struct defaults *d;
-    struct cvtsudoers_string *ls;
+    struct sudoers_string *ls;
     char *var, *val;
     debug_decl(ldif_store_options, SUDOERS_DEBUG_UTIL)
 
@@ -874,10 +874,10 @@ ldif_store_options(struct sudoers_parse_tree *parse_tree,
 static int
 str_list_cmp(const void *aa, const void *bb)
 {
-    const struct cvtsudoers_str_list *a = aa;
-    const struct cvtsudoers_str_list *b = bb;
-    const struct cvtsudoers_string *lsa = STAILQ_FIRST(a);
-    const struct cvtsudoers_string *lsb = STAILQ_FIRST(b);
+    const struct sudoers_str_list *a = aa;
+    const struct sudoers_str_list *b = bb;
+    const struct sudoers_string *lsa = STAILQ_FIRST(a);
+    const struct sudoers_string *lsb = STAILQ_FIRST(b);
     int ret;
 
     while (lsa != NULL && lsb != NULL) {
@@ -890,9 +890,9 @@ str_list_cmp(const void *aa, const void *bb)
 }
 
 static int
-str_list_cache(struct rbtree *cache, struct cvtsudoers_str_list **strlistp)
+str_list_cache(struct rbtree *cache, struct sudoers_str_list **strlistp)
 {
-    struct cvtsudoers_str_list *strlist = *strlistp;
+    struct sudoers_str_list *strlist = *strlistp;
     struct rbnode *node;
     int ret;
     debug_decl(str_list_cache, SUDOERS_DEBUG_UTIL)
@@ -924,7 +924,7 @@ role_to_sudoers(struct sudoers_parse_tree *parse_tree, struct sudo_role *role,
     bool reuse_runas)
 {
     struct privilege *priv;
-    struct cvtsudoers_string *ls;
+    struct sudoers_string *ls;
     struct userspec *us;
     struct member *m;
     debug_decl(role_to_sudoers, SUDOERS_DEBUG_UTIL)
@@ -1009,7 +1009,7 @@ role_to_sudoers(struct sudoers_parse_tree *parse_tree, struct sudo_role *role,
        STAILQ_FIRST(role->runasusers), STAILQ_FIRST(role->runasgroups),
        STAILQ_FIRST(role->cmnds), STAILQ_FIRST(role->options),
        role->notbefore, role->notafter, true, store_options,
-       cvtsudoers_string_iter);
+       sudoers_string_iter);
     if (priv == NULL) {
        sudo_fatalx(U_("%s: %s"), __func__,
            U_("unable to allocate memory"));
index 74d158fdc71b1c2c9264f30f0d4aa73b9399bc43..50d42afd0255784f663d8625b4ad785376693f80 100644 (file)
@@ -80,7 +80,7 @@ cvtsudoers_make_pwitem(uid_t uid, const char *name)
     size_t nsize, psize, csize, gsize, dsize, ssize, total;
     struct cache_item_pw *pwitem;
     struct passwd pw, *newpw;
-    struct cvtsudoers_string *s = NULL;
+    struct sudoers_string *s = NULL;
     debug_decl(sudo_make_pwitem, SUDOERS_DEBUG_NSS)
 
     /* Look up name or uid in filter list. */
@@ -186,7 +186,7 @@ cvtsudoers_make_gritem(gid_t gid, const char *name)
     size_t nsize, psize, nmem, total, len;
     struct cache_item_gr *gritem;
     struct group gr, *newgr;
-    struct cvtsudoers_string *s = NULL;
+    struct sudoers_string *s = NULL;
     debug_decl(sudo_make_gritem, SUDOERS_DEBUG_NSS)
 
     /* Look up name or gid in filter list. */
@@ -299,7 +299,7 @@ cvtsudoers_make_gidlist_item(const struct passwd *pw, char * const *unused1,
     char *cp;
     size_t nsize, total;
     struct cache_item_gidlist *glitem;
-    struct cvtsudoers_string *s;
+    struct sudoers_string *s;
     struct gid_list *gidlist;
     GETGROUPS_T *gids = NULL;
     int i, ngids = 0;
@@ -397,7 +397,7 @@ cvtsudoers_make_grlist_item(const struct passwd *pw, char * const *unused1)
     char *cp;
     size_t nsize, ngroups, total, len;
     struct cache_item_grlist *grlitem;
-    struct cvtsudoers_string *s;
+    struct sudoers_string *s;
     struct group_list *grlist;
     int groupname_len;
     debug_decl(sudo_make_grlist_item, SUDOERS_DEBUG_NSS)
diff --git a/plugins/sudoers/strlist.c b/plugins/sudoers/strlist.c
new file mode 100644 (file)
index 0000000..384e3d5
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+
+#include "sudo_compat.h"
+#include "sudo_util.h"
+#include "sudo_queue.h"
+#include "sudoers_debug.h"
+#include "strlist.h"
+
+struct sudoers_string *
+sudoers_string_alloc(const char *s)
+{
+    struct sudoers_string *cs;
+    debug_decl(sudoers_string_alloc, SUDOERS_DEBUG_UTIL)
+
+    if ((cs = malloc(sizeof(*cs))) != NULL) {
+       if ((cs->str = strdup(s)) == NULL) {
+           free(cs);
+           cs = NULL;
+       }
+    }
+
+    debug_return_ptr(cs);
+}
+
+void
+sudoers_string_free(struct sudoers_string *cs)
+{
+    if (cs != NULL) {
+       free(cs->str);
+       free(cs);
+    }
+}
+
+struct sudoers_str_list *
+str_list_alloc(void)
+{
+    struct sudoers_str_list *strlist;
+    debug_decl(str_list_alloc, SUDOERS_DEBUG_UTIL)
+
+    strlist = malloc(sizeof(*strlist));
+    if (strlist != NULL) {
+       STAILQ_INIT(strlist);
+       strlist->refcnt = 1;
+    }
+
+    debug_return_ptr(strlist);
+}
+
+void
+str_list_free(void *v)
+{
+    struct sudoers_str_list *strlist = v;
+    struct sudoers_string *first;
+    debug_decl(str_list_free, SUDOERS_DEBUG_UTIL)
+
+    if (strlist != NULL) {
+       if (--strlist->refcnt == 0) {
+           while ((first = STAILQ_FIRST(strlist)) != NULL) {
+               STAILQ_REMOVE_HEAD(strlist, entries);
+               sudoers_string_free(first);
+           }
+           free(strlist);
+       }
+    }
+    debug_return;
+}
diff --git a/plugins/sudoers/strlist.h b/plugins/sudoers/strlist.h
new file mode 100644 (file)
index 0000000..1a0dfc6
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_STRLIST_H
+#define SUDOERS_STRLIST_H
+
+/*
+ * Simple string list with optional reference count.
+ */
+struct sudoers_string {
+    STAILQ_ENTRY(sudoers_string) entries;
+    char *str;
+};
+struct sudoers_str_list {
+    struct sudoers_string *stqh_first;
+    struct sudoers_string **stqh_last;
+    unsigned int refcnt;
+};
+
+struct sudoers_str_list *str_list_alloc(void);
+void str_list_free(void *v);
+struct sudoers_string *sudoers_string_alloc(const char *s);
+void sudoers_string_free(struct sudoers_string *ls);
+
+#endif /* SUDOERS_STRLIST_H */