]> granicus.if.org Git - sudo/commitdiff
Use SLIST and STAILQ macros instead of doing headless singly linked
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 22 Oct 2013 15:08:09 +0000 (09:08 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 22 Oct 2013 15:08:09 +0000 (09:08 -0600)
lists manually.  As a bonus we now use a tail queue for ldap.c and
sudoreplay.c.

17 files changed:
common/Makefile.in
common/fatal.c
plugins/sudoers/Makefile.in
plugins/sudoers/defaults.c
plugins/sudoers/defaults.h
plugins/sudoers/env.c
plugins/sudoers/interfaces.c
plugins/sudoers/interfaces.h
plugins/sudoers/ldap.c
plugins/sudoers/match_addr.c
plugins/sudoers/sudoreplay.c
plugins/sudoers/toke.c
plugins/sudoers/toke.l
plugins/sudoers/visudo.c
src/Makefile.in
src/exec_pty.c
src/hooks.c

index f9e33b41ce6e4deaf7707b557ba9053837d6f1d9..cdbc5b99090575022d19268e5966c09b2c838c13 100644 (file)
@@ -189,7 +189,8 @@ event_select.lo: $(srcdir)/event_select.c $(top_builddir)/config.h \
        $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/event_select.c
 fatal.lo: $(srcdir)/fatal.c $(top_builddir)/config.h \
           $(top_srcdir)/compat/stdbool.h $(incdir)/missing.h $(incdir)/alloc.h \
-          $(incdir)/fatal.h $(incdir)/sudo_plugin.h $(incdir)/gettext.h
+          $(incdir)/fatal.h $(incdir)/queue.h $(incdir)/sudo_plugin.h \
+          $(incdir)/gettext.h
        $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/fatal.c
 fileops.lo: $(srcdir)/fileops.c $(top_builddir)/config.h \
             $(top_srcdir)/compat/stdbool.h $(top_srcdir)/compat/timespec.h \
index 1133f94aeb1ff7a868c5d5d5931b317169201059..1b50a4654b059b9d612971951ad39ce46a006642 100644 (file)
 #include "missing.h"
 #include "alloc.h"
 #include "fatal.h"
+#include "queue.h"
 #include "sudo_plugin.h"
 
 #define DEFAULT_TEXT_DOMAIN    "sudo"
 #include "gettext.h"
 
+struct sudo_fatal_callback {
+    SLIST_ENTRY(sudo_fatal_callback) entries;
+    void (*func)(void);
+};
+SLIST_HEAD(sudo_fatal_callback_list, sudo_fatal_callback);
+
 sigjmp_buf fatal_jmp;
 static bool setjmp_enabled = false;
-static struct sudo_fatal_callback {
-    void (*func)(void);
-    struct sudo_fatal_callback *next;
-} *callbacks;
+static struct sudo_fatal_callback_list callbacks;
 
 static void _warning(int, const char *, va_list);
 
@@ -51,8 +55,8 @@ do_cleanup(void)
     struct sudo_fatal_callback *cb;
 
     /* Run callbacks, removing them from the list as we go. */
-    while ((cb = callbacks) != NULL) {
-       callbacks = cb->next;
+    while ((cb = SLIST_FIRST(&callbacks)) != NULL) {
+       SLIST_REMOVE_HEAD(&callbacks, entries);
        cb->func();
        free(cb);
     }
@@ -173,8 +177,7 @@ fatal_callback_register(void (*func)(void))
     if (cb == NULL)
        return -1;
     cb->func = func;
-    cb->next = callbacks;
-    callbacks = cb;
+    SLIST_INSERT_HEAD(&callbacks, cb, entries);
 
     return 0;
 }
index 8a9e868bc8ed0524db25c130f9648bdcd0c15bb6..08d4ef3529f3dfb736ac5cb32ae3715e6f3cdbdf 100644 (file)
@@ -841,8 +841,8 @@ sudoreplay.o: $(srcdir)/sudoreplay.c $(top_builddir)/config.h \
               $(top_srcdir)/compat/getopt.h $(top_builddir)/pathnames.h \
               $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/fatal.h \
               $(incdir)/gettext.h $(srcdir)/logging.h $(srcdir)/iolog.h \
-              $(incdir)/sudo_plugin.h $(incdir)/sudo_conf.h $(incdir)/queue.h \
-              $(incdir)/sudo_debug.h
+              $(incdir)/queue.h $(incdir)/sudo_plugin.h $(incdir)/sudo_conf.h \
+              $(incdir)/queue.h $(incdir)/sudo_debug.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudoreplay.c
 testsudoers.o: $(srcdir)/testsudoers.c $(top_builddir)/config.h \
                $(top_srcdir)/compat/fnmatch.h $(srcdir)/tsgetgrpw.h \
@@ -903,6 +903,6 @@ visudo.o: $(srcdir)/visudo.c $(top_builddir)/config.h \
           $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
           $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \
           $(srcdir)/parse.h $(incdir)/list.h $(srcdir)/redblack.h \
-          $(incdir)/queue.h $(incdir)/gettext.h $(srcdir)/sudoers_version.h \
+          $(incdir)/gettext.h $(srcdir)/sudoers_version.h \
           $(incdir)/sudo_conf.h $(incdir)/queue.h $(devdir)/gram.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/visudo.c
index f263033b6e184730a18e44341b90523e5ce9a051..249e0e99914c1e7ae1ad09a01d1ebd45c4d92be5 100644 (file)
@@ -162,9 +162,9 @@ dump_defaults(void)
                    sudo_printf(SUDO_CONV_INFO_MSG, "\n");
                    break;
                case T_LIST:
-                   if (cur->sd_un.list) {
+                   if (!SLIST_EMPTY(&cur->sd_un.list)) {
                        sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc);
-                       for (item = cur->sd_un.list; item; item = item->next) {
+                       SLIST_FOREACH(item, &cur->sd_un.list, entries) {
                            sudo_printf(SUDO_CONV_INFO_MSG,
                                "\t%s\n", item->value);
                        }
@@ -826,43 +826,41 @@ store_mode(char *val, struct sudo_defs_types *def, int op)
 static void
 list_op(char *val, size_t len, struct sudo_defs_types *def, enum list_ops op)
 {
-    struct list_member *cur, *prev, *tmp;
+    struct list_member *tmp, *cur, *prev = NULL;
     debug_decl(list_op, SUDO_DEBUG_DEFAULTS)
 
     if (op == freeall) {
-       for (cur = def->sd_un.list; cur; ) {
-           tmp = cur;
-           cur = tmp->next;
+       SLIST_FOREACH_SAFE(cur, &def->sd_un.list, entries, tmp) {
            efree(tmp->value);
            efree(tmp);
        }
-       def->sd_un.list = NULL;
+       SLIST_INIT(&def->sd_un.list);
        debug_return;
     }
 
-    for (cur = def->sd_un.list, prev = NULL; cur; prev = cur, cur = cur->next) {
+    SLIST_FOREACH(cur, &def->sd_un.list, entries) {
        if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) {
 
            if (op == add)
                debug_return;           /* already exists */
 
            /* Delete node */
-           if (prev != NULL)
-               prev->next = cur->next;
+           if (prev == NULL)
+               SLIST_REMOVE_HEAD(&def->sd_un.list, entries);
            else
-               def->sd_un.list = cur->next;
+               SLIST_REMOVE_AFTER(prev, entries);
            efree(cur->value);
            efree(cur);
            break;
        }
+       prev = cur;
     }
 
     /* Add new node to the head of the list. */
     if (op == add) {
        cur = ecalloc(1, sizeof(struct list_member));
        cur->value = estrndup(val, len);
-       cur->next = def->sd_un.list;
-       def->sd_un.list = cur;
+       SLIST_INSERT_HEAD(&def->sd_un.list, cur, entries);
     }
     debug_return;
 }
index 082a001006991520ae722fdf9bd775b0b1179cdf..ef9ae65b067e029e0668876ea1e5a865bbebb6d7 100644 (file)
 #include <def_data.h>
 
 struct list_member {
+    SLIST_ENTRY(list_member) entries;
     char *value;
-    struct list_member *next;
 };
 
+SLIST_HEAD(list_members, list_member);
+
 struct def_values {
     char *sval;                /* string value */
     int ival;          /* actually an enum */
@@ -56,7 +58,7 @@ struct sudo_defs_types {
        enum def_tuple tuple;
        char *str;
        mode_t mode;
-       struct list_member *list;
+       struct list_memberlist;
     } sd_un;
 };
 
index 72218725a507549da212bd5790f7f1e4e49e6399..6076181cf089e5c9efc3d3d75804345574de0a02 100644 (file)
@@ -558,7 +558,7 @@ matches_env_delete(const char *var)
     debug_decl(matches_env_delete, SUDO_DEBUG_ENV)
 
     /* Skip anything listed in env_delete. */
-    for (cur = def_env_delete; cur; cur = cur->next) {
+    SLIST_FOREACH(cur, &def_env_delete, entries) {
        len = strlen(cur->value);
        /* Deal with '*' wildcard */
        if (cur->value[len - 1] == '*') {
@@ -589,7 +589,7 @@ matches_env_check(const char *var)
     int keepit = -1;
     debug_decl(matches_env_check, SUDO_DEBUG_ENV)
 
-    for (cur = def_env_check; cur; cur = cur->next) {
+    SLIST_FOREACH(cur, &def_env_check, entries) {
        len = strlen(cur->value);
        /* Deal with '*' wildcard */
        if (cur->value[len - 1] == '*') {
@@ -624,7 +624,7 @@ matches_env_keep(const char *var)
        goto done;
     }
 
-    for (cur = def_env_keep; cur; cur = cur->next) {
+    SLIST_FOREACH(cur, &def_env_keep, entries) {
        len = strlen(cur->value);
        /* Deal with '*' wildcard */
        if (cur->value[len - 1] == '*') {
@@ -1085,24 +1085,21 @@ init_envtables(void)
     for (p = initial_badenv_table; *p; p++) {
        cur = ecalloc(1, sizeof(struct list_member));
        cur->value = estrdup(*p);
-       cur->next = def_env_delete;
-       def_env_delete = cur;
+       SLIST_INSERT_HEAD(&def_env_delete, cur, entries);
     }
 
     /* Fill in the "env_check" list. */
     for (p = initial_checkenv_table; *p; p++) {
        cur = ecalloc(1, sizeof(struct list_member));
        cur->value = estrdup(*p);
-       cur->next = def_env_check;
-       def_env_check = cur;
+       SLIST_INSERT_HEAD(&def_env_check, cur, entries);
     }
 
     /* Fill in the "env_keep" list. */
     for (p = initial_keepenv_table; *p; p++) {
        cur = ecalloc(1, sizeof(struct list_member));
        cur->value = estrdup(*p);
-       cur->next = def_env_keep;
-       def_env_keep = cur;
+       SLIST_INSERT_HEAD(&def_env_keep, cur, entries);
     }
 }
 
index 4dc6012a3420cd4160083daa10b2a66c7f6215af..baf31d3c8cbfe1d93536399142902d4074a9c67a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2010-2013 Todd C. Miller <Todd.Miller@courtesan.com>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -51,7 +51,7 @@
 # define INADDR_NONE ((unsigned int)-1)
 #endif
 
-static struct interface *interfaces;
+static struct interface_list interfaces;
 
 /*
  * Parse a space-delimited list of IP address/netmask pairs and
@@ -95,17 +95,16 @@ set_interfaces(const char *ai)
                continue;
            }
        }
-       ifp->next = interfaces;
-       interfaces = ifp;
+       SLIST_INSERT_HEAD(&interfaces, ifp, entries);
     }
     efree(addrinfo);
     debug_return;
 }
 
-struct interface *
+struct interface_list *
 get_interfaces(void)
 {
-    return interfaces;
+    return &interfaces;
 }
 
 void
index 3ccd8169c21f7da6870038a95bdac39726a415bf..26e669824bd2e361b9c1087daf366dfc11ee6933 100644 (file)
@@ -36,18 +36,20 @@ union sudo_in_addr_un {
  * IP address and netmask pairs for checking against local interfaces.
  */
 struct interface {
+    SLIST_ENTRY(interface) entries;
     int family;        /* AF_INET or AF_INET6 */
     union sudo_in_addr_un addr;
     union sudo_in_addr_un netmask;
-    struct interface *next;
 };
 
+SLIST_HEAD(interface_list, interface);
+
 /*
  * Prototypes for external functions.
  */
 int get_net_ifs(char **addrinfo);
 void dump_interfaces(const char *);
 void set_interfaces(const char *);
-struct interface *get_interfaces(void);
+struct interface_list *get_interfaces(void);
 
 #endif /* _SUDOERS_INTERFACES_H */
index cb7be8cb6024bdd72e5503cdc2ef6fdb942eaa81..8bd1708d658d2dc36f075f50b47ad4b5b64eaf1f 100644 (file)
@@ -159,13 +159,13 @@ extern int ldapssl_set_strength(LDAP *ldap, int strength);
  * The ldap_search structure implements a linked list of ldap and
  * search result pointers, which allows us to remove them after
  * all search results have been combined in memory.
- * XXX - should probably be a tailq since we do appends
  */
-struct ldap_search_list {
+struct ldap_search_result {
+    STAILQ_ENTRY(ldap_search_result) entries;
     LDAP *ldap;
     LDAPMessage *searchresult;
-    struct ldap_search_list *next;
 };
+STAILQ_HEAD(ldap_search_list, ldap_search_result);
 
 /*
  * The ldap_entry_wrapper structure is used to implement sorted result entries.
@@ -184,7 +184,7 @@ struct ldap_entry_wrapper {
  * well as an array of all result entries sorted by the sudoOrder attribute.
  */
 struct ldap_result {
-    struct ldap_search_list *searches;
+    struct ldap_search_list searches;
     struct ldap_entry_wrapper *entries;
     int allocated_entries;
     int nentries;
@@ -200,11 +200,13 @@ struct ldap_config_table {
     void *valp;                        /* pointer into ldap_conf */
 };
 
-struct ldap_config_list_str {
-    struct ldap_config_list_str *next;
+struct ldap_config_str {
+    STAILQ_ENTRY(ldap_config_str) entries;
     char val[1];
 };
 
+STAILQ_HEAD(ldap_config_str_list, ldap_config_str);
+
 /* LDAP configuration structure */
 static struct ldap_config {
     int port;
@@ -221,11 +223,11 @@ static struct ldap_config {
     int timed;
     int deref;
     char *host;
-    struct ldap_config_list_str *uri;
+    struct ldap_config_str_list uri;
     char *binddn;
     char *bindpw;
     char *rootbinddn;
-    struct ldap_config_list_str *base;
+    struct ldap_config_str_list base;
     char *search_filter;
     char *ssl;
     char *tls_cacertfile;
@@ -433,16 +435,17 @@ toobig:
  * where the trailing slash is optional.
  */
 static int
-sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list)
+sudo_ldap_parse_uri(const struct ldap_config_str_list *uri_list)
 {
+    const struct ldap_config_str *entry;
     char *buf, *uri, *host, *cp, *port;
     char hostbuf[LINE_MAX];
     int nldap = 0, nldaps = 0;
     int rc = -1;
     debug_decl(sudo_ldap_parse_uri, SUDO_DEBUG_LDAP)
 
-    do {
-       buf = estrdup(uri_list->val);
+    STAILQ_FOREACH(entry, uri_list, entries) {
+       buf = estrdup(entry->val);
        hostbuf[0] = '\0';
        for ((uri = strtok(buf, " \t")); uri != NULL; (uri = strtok(NULL, " \t"))) {
            if (strncasecmp(uri, "ldap://", 7) == 0) {
@@ -481,7 +484,7 @@ sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list)
            }
        }
        if (hostbuf[0] == '\0') {
-           warningx(_("invalid uri: %s"), uri_list->val);
+           warningx(_("invalid uri: %s"), entry->val);
            goto done;
        }
 
@@ -500,7 +503,7 @@ sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list)
        efree(ldap_conf.host);
        ldap_conf.host = estrdup(hostbuf);
        efree(buf);
-    } while ((uri_list = uri_list->next));
+    }
 
     buf = NULL;
     rc = 0;
@@ -514,23 +517,24 @@ toobig:
 }
 #else
 static char *
-sudo_ldap_join_uri(struct ldap_config_list_str *uri_list)
+sudo_ldap_join_uri(struct ldap_config_str_list *uri_list)
 {
-    struct ldap_config_list_str *uri;
+    struct ldap_config_str *uri;
     size_t len = 0;
     char *buf, *cp;
     debug_decl(sudo_ldap_join_uri, SUDO_DEBUG_LDAP)
 
     /* Usually just a single entry. */
-    if (uri_list->next == NULL)
-       debug_return_str(estrdup(uri_list->val));
+    if (STAILQ_NEXT(STAILQ_FIRST(uri_list), entries) == NULL)
+       debug_return_str(estrdup(STAILQ_FIRST(uri_list)->val));
 
-    for (uri = uri_list; uri != NULL; uri = uri->next) {
+    /* Multiple entries. */
+    STAILQ_FOREACH(uri, uri_list, entries) {
        len += strlen(uri->val) + 1;
     }
     buf = cp = emalloc(len);
     buf[0] = '\0';
-    for (uri = uri_list; uri != NULL; uri = uri->next) {
+    STAILQ_FOREACH(uri, uri_list, entries) {
        cp += strlcpy(cp, uri->val, len - (cp - buf));
        *cp++ = ' ';
     }
@@ -1420,16 +1424,15 @@ sudo_ldap_parse_keyword(const char *keyword, const char *value,
                break;
            case CONF_LIST_STR:
                {
-                   struct ldap_config_list_str **p;
+                   struct ldap_config_str_list *head;
+                   struct ldap_config_str *str;
                    size_t len = strlen(value);
 
                    if (len > 0) {
-                       p = (struct ldap_config_list_str **)cur->valp;
-                       while (*p != NULL)
-                           p = &(*p)->next;
-                       *p = emalloc(sizeof(struct ldap_config_list_str) + len);
-                       memcpy((*p)->val, value, len + 1);
-                       (*p)->next = NULL;
+                       head = (struct ldap_config_str_list *)cur->valp;
+                       str = emalloc(sizeof(*str) + len);
+                       memcpy(str->val, value, len + 1);
+                       STAILQ_INSERT_TAIL(head, str, entries);
                    }
                }
                break;
@@ -1513,6 +1516,8 @@ sudo_ldap_read_config(void)
     ldap_conf.use_sasl = -1;
     ldap_conf.rootuse_sasl = -1;
     ldap_conf.deref = -1;
+    STAILQ_INIT(&ldap_conf.uri);
+    STAILQ_INIT(&ldap_conf.base);
 
     if ((fp = fopen(path_ldap_conf, "r")) == NULL)
        debug_return_bool(false);
@@ -1545,12 +1550,12 @@ sudo_ldap_read_config(void)
 
     DPRINTF1("LDAP Config Summary");
     DPRINTF1("===================");
-    if (ldap_conf.uri) {
-       struct ldap_config_list_str *uri = ldap_conf.uri;
+    if (!STAILQ_EMPTY(&ldap_conf.uri)) {
+       struct ldap_config_str *uri;
 
-       do {
+       STAILQ_FOREACH(uri, &ldap_conf.uri, entries) {
            DPRINTF1("uri              %s", uri->val);
-       } while ((uri = uri->next) != NULL);
+       }
     } else {
        DPRINTF1("host             %s",
            ldap_conf.host ? ldap_conf.host : "(NONE)");
@@ -1558,11 +1563,11 @@ sudo_ldap_read_config(void)
     }
     DPRINTF1("ldap_version     %d", ldap_conf.version);
 
-    if (ldap_conf.base) {
-       struct ldap_config_list_str *base = ldap_conf.base;
-       do {
+    if (!STAILQ_EMPTY(&ldap_conf.base)) {
+       struct ldap_config_str *base;
+       STAILQ_FOREACH(base, &ldap_conf.base, entries) {
            DPRINTF1("sudoers_base     %s", base->val);
-       } while ((base = base->next) != NULL);
+       }
     } else {
        DPRINTF1("sudoers_base     %s", "(NONE: LDAP disabled)");
     }
@@ -1622,7 +1627,7 @@ sudo_ldap_read_config(void)
 #endif
     DPRINTF1("===================");
 
-    if (!ldap_conf.base)
+    if (STAILQ_EMPTY(&ldap_conf.base))
        debug_return_bool(false);       /* if no base is defined, ignore LDAP */
 
     if (ldap_conf.bind_timelimit > 0)
@@ -1647,19 +1652,20 @@ sudo_ldap_read_config(void)
 
 #ifndef HAVE_LDAP_INITIALIZE
     /* Convert uri list to host list if no ldap_initialize(). */
-    if (ldap_conf.uri) {
-       struct ldap_config_list_str *uri = ldap_conf.uri;
-       if (sudo_ldap_parse_uri(uri) != 0)
+    if (!STAILQ_EMPTY(&ldap_conf.uri)) {
+       struct ldap_config_str *uri;
+
+       if (sudo_ldap_parse_uri(&ldap_conf.uri) != 0)
            debug_return_bool(false);
-       do {
-           ldap_conf.uri = uri->next;
+       while ((uri = STAILQ_FIRST(&ldap_conf.uri)) != NULL) {
+           STAILQ_REMOVE_HEAD(&ldap_conf.uri, entries);
            efree(uri);
-       } while ((uri = ldap_conf.uri));
+       }
        ldap_conf.port = LDAP_PORT;
     }
 #endif
 
-    if (!ldap_conf.uri) {
+    if (STAILQ_EMPTY(&ldap_conf.uri)) {
        /* Use port 389 for plaintext LDAP and port 636 for SSL LDAP */
        if (ldap_conf.port < 0)
            ldap_conf.port =
@@ -1744,7 +1750,7 @@ sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw,
 {
     struct berval **bv, **p;
     struct timeval tv, *tvp = NULL;
-    struct ldap_config_list_str *base;
+    struct ldap_config_str *base;
     struct sudo_ldap_handle *handle = nss->handle;
     LDAP *ld;
     LDAPMessage *entry, *result;
@@ -1757,7 +1763,7 @@ sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw,
     ld = handle->ld;
 
     filt = sudo_ldap_build_default_filter();
-    for (base = ldap_conf.base; base != NULL; base = base->next) {
+    STAILQ_FOREACH(base, &ldap_conf.base, entries) {
        if (ldap_conf.timeout > 0) {
            tv.tv_sec = ldap_conf.timeout;
            tv.tv_usec = 0;
@@ -2299,7 +2305,10 @@ sudo_ldap_result_alloc(void)
     struct ldap_result *result;
     debug_decl(sudo_ldap_result_alloc, SUDO_DEBUG_LDAP)
 
-    debug_return_ptr(ecalloc(1, sizeof(*result)));
+    result = ecalloc(1, sizeof(*result));
+    STAILQ_INIT(&result->searches);
+
+    debug_return_ptr(result);
 }
 
 /*
@@ -2308,7 +2317,7 @@ sudo_ldap_result_alloc(void)
 static void
 sudo_ldap_result_free(struct ldap_result *lres)
 {
-    struct ldap_search_list *s;
+    struct ldap_search_result *s;
     debug_decl(sudo_ldap_result_free, SUDO_DEBUG_LDAP)
 
     if (lres != NULL) {
@@ -2316,12 +2325,10 @@ sudo_ldap_result_free(struct ldap_result *lres)
            efree(lres->entries);
            lres->entries = NULL;
        }
-       if (lres->searches) {
-           while ((s = lres->searches) != NULL) {
-               ldap_msgfree(s->searchresult);
-               lres->searches = s->next;
-               efree(s);
-           }
+       while ((s = STAILQ_FIRST(&lres->searches)) != NULL) {
+           STAILQ_REMOVE_HEAD(&lres->searches, entries);
+           ldap_msgfree(s->searchresult);
+           efree(s);
        }
        efree(lres);
     }
@@ -2331,26 +2338,19 @@ sudo_ldap_result_free(struct ldap_result *lres)
 /*
  * Add a search result to the ldap_result structure.
  */
-static struct ldap_search_list *
+static struct ldap_search_result *
 sudo_ldap_result_add_search(struct ldap_result *lres, LDAP *ldap,
     LDAPMessage *searchresult)
 {
-    struct ldap_search_list *s, *news;
+    struct ldap_search_result *news;
     debug_decl(sudo_ldap_result_add_search, SUDO_DEBUG_LDAP)
 
-    news = ecalloc(1, sizeof(struct ldap_search_list));
+    /* Create new entry and add it to the end of the chain. */
+    news = ecalloc(1, sizeof(*news));
     news->ldap = ldap;
     news->searchresult = searchresult;
-    /* news->next = NULL; */
+    STAILQ_INSERT_TAIL(&lres->searches, news, entries);
 
-    /* Add entry to the end of the chain (XXX - tailq instead?). */
-    if (lres->searches) {
-       for (s = lres->searches; s->next != NULL; s = s->next)
-           continue;
-       s->next = news;
-    } else {
-       lres->searches = news;
-    }
     debug_return_ptr(news);
 }
 
@@ -2471,8 +2471,8 @@ sudo_ldap_open(struct sudo_nss *nss)
 
     /* Connect to LDAP server */
 #ifdef HAVE_LDAP_INITIALIZE
-    if (ldap_conf.uri != NULL) {
-       char *buf = sudo_ldap_join_uri(ldap_conf.uri);
+    if (!STAILQ_EMPTY(&ldap_conf.uri)) {
+       char *buf = sudo_ldap_join_uri(&ldap_conf.uri);
        DPRINTF2("ldap_initialize(ld, %s)", buf);
        rc = ldap_initialize(&ld, buf);
        efree(buf);
@@ -2537,7 +2537,7 @@ sudo_ldap_open(struct sudo_nss *nss)
 static int
 sudo_ldap_setdefs(struct sudo_nss *nss)
 {
-    struct ldap_config_list_str *base;
+    struct ldap_config_str *base;
     struct sudo_ldap_handle *handle = nss->handle;
     struct timeval tv, *tvp = NULL;
     LDAP *ld;
@@ -2553,7 +2553,7 @@ sudo_ldap_setdefs(struct sudo_nss *nss)
     filt = sudo_ldap_build_default_filter();
     DPRINTF1("Looking for cn=defaults: %s", filt);
 
-    for (base = ldap_conf.base; base != NULL; base = base->next) {
+    STAILQ_FOREACH(base, &ldap_conf.base, entries) {
        if (ldap_conf.timeout > 0) {
            tv.tv_sec = ldap_conf.timeout;
            tv.tv_usec = 0;
@@ -2713,21 +2713,15 @@ ldap_entry_compare(const void *a, const void *b)
 }
 
 /*
- * Find the last entry in the list of searches, usually the
+ * Return the last entry in the list of searches, usually the
  * one currently being used to add entries.
- * XXX - use a tailq instead?
  */
-static struct ldap_search_list *
+static struct ldap_search_result *
 sudo_ldap_result_last_search(struct ldap_result *lres)
 {
-    struct ldap_search_list *result = lres->searches;
     debug_decl(sudo_ldap_result_last_search, SUDO_DEBUG_LDAP)
 
-    if (result) {
-       while (result->next)
-           result = result->next;
-    }
-    debug_return_ptr(result);
+    debug_return_ptr(STAILQ_LAST(&lres->searches, ldap_search_result, entries));
 }
 
 /*
@@ -2736,7 +2730,7 @@ sudo_ldap_result_last_search(struct ldap_result *lres)
 static struct ldap_entry_wrapper *
 sudo_ldap_result_add_entry(struct ldap_result *lres, LDAPMessage *entry)
 {
-    struct ldap_search_list *last;
+    struct ldap_search_result *last;
     struct berval **bv;
     double order = 0.0;
     char *ep;
@@ -2806,7 +2800,7 @@ static struct ldap_result *
 sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
 {
     struct sudo_ldap_handle *handle = nss->handle;
-    struct ldap_config_list_str *base;
+    struct ldap_config_str *base;
     struct ldap_result *lres;
     struct timeval tv, *tvp = NULL;
     LDAPMessage *entry, *result;
@@ -2854,7 +2848,7 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
     for (pass = 0; pass < 2; pass++) {
        filt = pass ? sudo_ldap_build_pass2() : sudo_ldap_build_pass1(pw);
        DPRINTF1("ldap search '%s'", filt);
-       for (base = ldap_conf.base; base != NULL; base = base->next) {
+       STAILQ_FOREACH(base, &ldap_conf.base, entries) {
            DPRINTF1("searching from base '%s'",
                base->val);
            if (ldap_conf.timeout > 0) {
@@ -2957,7 +2951,7 @@ sudo_ldap_result_from_search(LDAP *ldap, LDAPMessage *searchresult)
      * Build a new list node for the search result, this creates the
      * list node.
      */
-    struct ldap_search_list *last = sudo_ldap_result_add_search(result,
+    struct ldap_search_result *last = sudo_ldap_result_add_search(result,
        ldap, searchresult);
 
     /*
index 75f82c9fbd689605fd798db03ab38351e49ca2f5..29bfd52dc3b10fa47a091f086e870ec2c3929fba 100644 (file)
@@ -70,7 +70,7 @@ addr_matches_if(char *n)
        addr.ip4.s_addr = inet_addr(n);
     }
 
-    for (ifp = get_interfaces(); ifp != NULL; ifp = ifp->next) {
+    SLIST_FOREACH(ifp, get_interfaces(), entries) {
        if (ifp->family != family)
            continue;
        switch (family) {
@@ -153,7 +153,7 @@ addr_matches_if_netmask(char *n, char *m)
     }
 #endif /* HAVE_STRUCT_IN6_ADDR */
 
-    for (ifp = get_interfaces(); ifp != NULL; ifp = ifp->next) {
+    SLIST_FOREACH(ifp, get_interfaces(), entries) {
        if (ifp->family != family)
            continue;
        switch (family) {
index 31f08974622bf738764fdf6c64b5977fe44aae7c..fcf2eafbc38d9e78dd5836e21ae95819480fae91 100644 (file)
 #include "gettext.h"
 #include "logging.h"
 #include "iolog.h"
+#include "queue.h"
 #include "sudo_plugin.h"
 #include "sudo_conf.h"
 #include "sudo_debug.h"
@@ -128,8 +129,9 @@ struct log_info {
  * Handle expressions like:
  * ( user millert or user root ) and tty console and command /bin/sh
  */
-static struct search_node {
-    struct search_node *next;
+STAILQ_HEAD(search_node_list, search_node);
+struct search_node {
+    STAILQ_ENTRY(search_node) entries;
 #define ST_EXPR                1
 #define ST_TTY         2
 #define ST_USER                3
@@ -140,9 +142,8 @@ static struct search_node {
 #define ST_TODATE      8
 #define ST_CWD         9
     char type;
-    char negated;
-    char or;
-    char pad;
+    bool negated;
+    bool or;
     union {
 #ifdef HAVE_REGCOMP
        regex_t cmdre;
@@ -154,14 +155,12 @@ static struct search_node {
        char *pattern;
        char *runas_group;
        char *runas_user;
-       struct search_node *expr;
+       struct search_node_list expr;
        void *ptr;
     } u;
-} *search_expr;
+};
 
-#define STACK_NODE_SIZE        32
-static struct search_node *node_stack[32];
-static int stack_top;
+static struct search_node_list search_expr = STAILQ_HEAD_INITIALIZER(search_expr);
 
 static int timing_idx_adj = 0;
 
@@ -186,7 +185,7 @@ extern int term_restore(int, int);
 extern void get_ttysize(int *rowp, int *colp);
 
 static int list_sessions(int, char **, const char *, const char *, const char *);
-static int parse_expr(struct search_node **, char **);
+static int parse_expr(struct search_node_list *, char **, bool);
 static void check_input(int, double *);
 static void delay(double);
 static void help(void) __attribute__((__noreturn__));
@@ -606,14 +605,14 @@ atomic_writev(int fd, struct iovec *iov, int iovcnt)
  * Build expression list from search args
  */
 static int
-parse_expr(struct search_node **headp, char *argv[])
+parse_expr(struct search_node_list *head, char *argv[], bool sub_expr)
 {
-    struct search_node *sn, *newsn;
-    char or = 0, not = 0, type, **av;
+    bool or = false, not = false;
+    struct search_node *sn;
+    char type, **av;
     debug_decl(parse_expr, SUDO_DEBUG_UTIL)
 
-    sn = *headp;
-    for (av = argv; *av; av++) {
+    for (av = argv; *av != NULL; av++) {
        switch (av[0][0]) {
        case 'a': /* and (ignore) */
            if (strncmp(*av, "and", strlen(*av)) != 0)
@@ -622,12 +621,12 @@ parse_expr(struct search_node **headp, char *argv[])
        case 'o': /* or */
            if (strncmp(*av, "or", strlen(*av)) != 0)
                goto bad;
-           or = 1;
+           or = true;
            continue;
        case '!': /* negate */
            if (av[0][1] != '\0')
                goto bad;
-           not = 1;
+           not = true;
            continue;
        case 'c': /* command */
            if (av[0][1] == '\0')
@@ -672,21 +671,13 @@ parse_expr(struct search_node **headp, char *argv[])
        case '(': /* start sub-expression */
            if (av[0][1] != '\0')
                goto bad;
-           if (stack_top + 1 == STACK_NODE_SIZE) {
-               fatalx(_("too many parenthesized expressions, max %d"),
-                   STACK_NODE_SIZE);
-           }
-           node_stack[stack_top++] = sn;
            type = ST_EXPR;
            break;
        case ')': /* end sub-expression */
            if (av[0][1] != '\0')
                goto bad;
-           /* pop */
-           if (--stack_top < 0)
+           if (!sub_expr)
                fatalx(_("unmatched ')' in expression"));
-           if (node_stack[stack_top])
-               sn->next = node_stack[stack_top]->next;
            debug_return_int(av - argv + 1);
        bad:
        default:
@@ -695,38 +686,34 @@ parse_expr(struct search_node **headp, char *argv[])
        }
 
        /* Allocate new search node */
-       newsn = ecalloc(1, sizeof(*newsn));
-       newsn->type = type;
-       newsn->or = or;
-       newsn->negated = not;
-       /* newsn->next = NULL; */
+       sn = ecalloc(1, sizeof(*sn));
+       sn->type = type;
+       sn->or = or;
+       sn->negated = not;
        if (type == ST_EXPR) {
-           av += parse_expr(&newsn->u.expr, av + 1);
+           STAILQ_INIT(&sn->u.expr);
+           av += parse_expr(&sn->u.expr, av + 1, true);
        } else {
            if (*(++av) == NULL)
                fatalx(_("%s requires an argument"), av[-1]);
 #ifdef HAVE_REGCOMP
            if (type == ST_PATTERN) {
-               if (regcomp(&newsn->u.cmdre, *av, REG_EXTENDED|REG_NOSUB) != 0)
+               if (regcomp(&sn->u.cmdre, *av, REG_EXTENDED|REG_NOSUB) != 0)
                    fatalx(_("invalid regular expression: %s"), *av);
            } else
 #endif
            if (type == ST_TODATE || type == ST_FROMDATE) {
-               newsn->u.tstamp = get_date(*av);
-               if (newsn->u.tstamp == -1)
+               sn->u.tstamp = get_date(*av);
+               if (sn->u.tstamp == -1)
                    fatalx(_("could not parse date \"%s\""), *av);
            } else {
-               newsn->u.ptr = *av;
+               sn->u.ptr = *av;
            }
        }
-       not = or = 0; /* reset state */
-       if (sn)
-           sn->next = newsn;
-       else
-           *headp = newsn;
-       sn = newsn;
+       not = or = false; /* reset state */
+       STAILQ_INSERT_TAIL(head, sn, entries);
     }
-    if (stack_top)
+    if (sub_expr)
        fatalx(_("unmatched '(' in expression"));
     if (or)
        fatalx(_("illegal trailing \"or\""));
@@ -737,17 +724,17 @@ parse_expr(struct search_node **headp, char *argv[])
 }
 
 static bool
-match_expr(struct search_node *head, struct log_info *log, bool last_match)
+match_expr(struct search_node_list *head, struct log_info *log, bool last_match)
 {
     struct search_node *sn;
     bool res, matched = last_match;
     int rc;
     debug_decl(match_expr, SUDO_DEBUG_UTIL)
 
-    for (sn = head; sn; sn = sn->next) {
+    STAILQ_FOREACH(sn, head, entries) {
        switch (sn->type) {
        case ST_EXPR:
-           res = match_expr(sn->u.expr, log, matched);
+           res = match_expr(&sn->u.expr, log, matched);
            break;
        case ST_CWD:
            res = strcmp(sn->u.cwd, log->cwd) == 0;
@@ -909,7 +896,7 @@ list_session(char *logfile, REGEX_T *re, const char *user, const char *tty)
        goto done;
 
     /* Match on search expression if there is one. */
-    if (search_expr && !match_expr(search_expr, li, true))
+    if (!STAILQ_EMPTY(&search_expr) && !match_expr(&search_expr, li, true))
        goto done;
 
     /* Convert from /var/log/sudo-sessions/00/00/01/log to 000001 */
@@ -1042,7 +1029,7 @@ list_sessions(int argc, char **argv, const char *pattern, const char *user,
     debug_decl(list_sessions, SUDO_DEBUG_UTIL)
 
     /* Parse search expression if present */
-    parse_expr(&search_expr, argv);
+    parse_expr(&search_expr, argv, false);
 
 #ifdef HAVE_REGCOMP
     /* optional regex */
index 03a979575301e95b5a746399236bf947f55565f0..936c93b88849913efbfc9ae523e30dd864b340b1 100644 (file)
@@ -3983,37 +3983,42 @@ int main()
 #line 725 "toke.l"
 
 struct path_list {
+    SLIST_ENTRY(path_list) entries;
     char *path;
-    struct path_list *next;
 };
 
+SLIST_HEAD(path_list_head, path_list);
+
 struct include_stack {
     YY_BUFFER_STATE bs;
     char *path;
-    struct path_list *more; /* more files in case of includedir */
+    struct path_list_head more; /* more files in case of includedir */
     int lineno;
     bool keepopen;
 };
 
+/*
+ * Compare two struct path_list structs in reverse order.
+ */
 static int
 pl_compare(const void *v1, const void *v2)
 {
     const struct path_list * const *p1 = v1;
     const struct path_list * const *p2 = v2;
 
-    return strcmp((*p1)->path, (*p2)->path);
+    return strcmp((*p2)->path, (*p1)->path);
 }
 
 static char *
 switch_dir(struct include_stack *stack, char *dirpath)
 {
     DIR *dir;
-    int i, count = 0;
+    unsigned int i, count = 0;
+    unsigned int max_paths = 32;
     char *path = NULL;
     struct dirent *dent;
     struct stat sb;
-    struct path_list *pl, *first = NULL;
-    struct path_list **sorted = NULL;
+    struct path_list *pl, **paths = NULL;
     debug_decl(switch_dir, SUDO_DEBUG_PARSER)
 
     if (!(dir = opendir(dirpath))) {
@@ -4023,6 +4028,11 @@ switch_dir(struct include_stack *stack, char *dirpath)
        }
        goto done;
     }
+    paths = malloc(sizeof(*paths) * max_paths);
+    if (paths == NULL) {
+       closedir(dir);
+       goto bad;
+    }
     while ((dent = readdir(dir))) {
        /* Ignore files that end in '~' or have a '.' in them. */
        if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~'
@@ -4042,54 +4052,47 @@ switch_dir(struct include_stack *stack, char *dirpath)
        if (pl == NULL)
            goto bad;
        pl->path = path;
-       pl->next = first;
-       first = pl;
+       if (count >= max_paths) {
+           struct path_list **tmp;
+           max_paths <<= 1;
+           tmp = realloc(paths, sizeof(*paths) * max_paths);
+           if (tmp == NULL) {
+               closedir(dir);
+               goto bad;
+           }
+           paths = tmp;
+       }
+       paths[count++] = pl;
        path = NULL;
-       count++;
     }
     closedir(dir);
 
     if (count == 0)
        goto done;
 
-    /* Sort the list as an array. */
-    sorted = malloc(sizeof(*sorted) * count);
-    if (sorted == NULL)
-       goto bad;
-    pl = first;
+    /* Sort the list as an array in reverse order. */
+    qsort(paths, count, sizeof(*paths), pl_compare);
+
+    /* Build up the list in sorted order. */
     for (i = 0; i < count; i++) {
-       sorted[i] = pl;
-       pl = pl->next;
+       SLIST_INSERT_HEAD(&stack->more, paths[i], entries);
     }
-    qsort(sorted, count, sizeof(*sorted), pl_compare);
-
-    /* Apply sorting to the list. */
-    first = sorted[0];
-    sorted[count - 1]->next = NULL;
-    for (i = 1; i < count; i++)
-       sorted[i - 1]->next = sorted[i];
-    efree(sorted);
 
     /* Pull out the first element for parsing, leave the rest for later. */
-    if (count) {
-       path = first->path;
-       pl = first->next;
-       efree(first);
-       stack->more = pl;
-    } else {
-       path = NULL;
-    }
+    pl = SLIST_FIRST(&stack->more);
+    SLIST_REMOVE_HEAD(&stack->more, entries);
+    path = pl->path;
+    efree(pl);
 done:
+    efree(paths);
     efree(dirpath);
     debug_return_str(path);
 bad:
-    while (first != NULL) {
-       pl = first;
-       first = pl->next;
-       efree(pl->path);
-       efree(pl);
+    for (i = 0; i < count; i++) {
+       efree(paths[i]->path);
+       efree(paths[i]);
     }
-    efree(sorted);
+    efree(paths);
     efree(dirpath);
     efree(path);
     debug_return_str(NULL);
@@ -4110,8 +4113,8 @@ init_lexer(void)
 
     while (idepth) {
        idepth--;
-       while ((pl = istack[idepth].more) != NULL) {
-           istack[idepth].more = pl->next;
+       while ((pl = SLIST_FIRST(&istack[idepth].more)) != NULL) {
+           SLIST_REMOVE_HEAD(&istack[idepth].more, entries);
            efree(pl->path);
            efree(pl);
        }
@@ -4154,6 +4157,7 @@ _push_include(char *path, bool isdir)
            debug_return_bool(false);
        }
     }
+    SLIST_INIT(&istack[idepth].more);
     if (isdir) {
        struct stat sb;
        switch (sudo_secure_dir(path, sudoers_uid, sudoers_gid, &sb)) {
@@ -4197,10 +4201,10 @@ _push_include(char *path, bool isdir)
        while ((fp = open_sudoers(path, false, &keepopen)) == NULL) {
            /* Unable to open path in includedir, go to next one, if any. */
            efree(path);
-           if ((pl = istack[idepth].more) == NULL)
+           if ((pl = SLIST_FIRST(&istack[idepth].more)) == NULL)
                debug_return_bool(false);
+           SLIST_REMOVE_HEAD(&istack[idepth].more, entries);
            path = pl->path;
-           istack[idepth].more = pl->next;
            efree(pl);
        }
     } else {
@@ -4209,7 +4213,6 @@ _push_include(char *path, bool isdir)
            sudoerserror(NULL);
            debug_return_bool(false);
        }
-       istack[idepth].more = NULL;
     }
     /* Push the old (current) file and open the new one. */
     istack[idepth].path = sudoers; /* push old path */
@@ -4238,10 +4241,10 @@ pop_include(void)
        fclose(YY_CURRENT_BUFFER->yy_input_file);
     sudoers_delete_buffer(YY_CURRENT_BUFFER);
     /* If we are in an include dir, move to the next file. */
-    while ((pl = istack[idepth - 1].more) != NULL) {
+    while ((pl = SLIST_FIRST(&istack[idepth - 1].more)) != NULL) {
+       SLIST_REMOVE_HEAD(&istack[idepth - 1].more, entries);
        fp = open_sudoers(pl->path, false, &keepopen);
        if (fp != NULL) {
-           istack[idepth - 1].more = pl->next;
            efree(sudoers);
            sudoers = pl->path;
            sudolineno = 1;
@@ -4250,7 +4253,6 @@ pop_include(void)
            break;
        }
        /* Unable to open path in include dir, go to next one. */
-       istack[idepth - 1].more = pl->next;
        efree(pl->path);
        efree(pl);
     }
index d693a693bca3f089333612bbbfd8c6ac7477e5c2..e90405d4a3987f4e077485008fc468dafc6f7272 100644 (file)
@@ -724,37 +724,42 @@ sudoedit          {
 
 %%
 struct path_list {
+    SLIST_ENTRY(path_list) entries;
     char *path;
-    struct path_list *next;
 };
 
+SLIST_HEAD(path_list_head, path_list);
+
 struct include_stack {
     YY_BUFFER_STATE bs;
     char *path;
-    struct path_list *more; /* more files in case of includedir */
+    struct path_list_head more; /* more files in case of includedir */
     int lineno;
     bool keepopen;
 };
 
+/*
+ * Compare two struct path_list structs in reverse order.
+ */
 static int
 pl_compare(const void *v1, const void *v2)
 {
     const struct path_list * const *p1 = v1;
     const struct path_list * const *p2 = v2;
 
-    return strcmp((*p1)->path, (*p2)->path);
+    return strcmp((*p2)->path, (*p1)->path);
 }
 
 static char *
 switch_dir(struct include_stack *stack, char *dirpath)
 {
     DIR *dir;
-    int i, count = 0;
+    unsigned int i, count = 0;
+    unsigned int max_paths = 32;
     char *path = NULL;
     struct dirent *dent;
     struct stat sb;
-    struct path_list *pl, *first = NULL;
-    struct path_list **sorted = NULL;
+    struct path_list *pl, **paths = NULL;
     debug_decl(switch_dir, SUDO_DEBUG_PARSER)
 
     if (!(dir = opendir(dirpath))) {
@@ -764,6 +769,11 @@ switch_dir(struct include_stack *stack, char *dirpath)
        }
        goto done;
     }
+    paths = malloc(sizeof(*paths) * max_paths);
+    if (paths == NULL) {
+       closedir(dir);
+       goto bad;
+    }
     while ((dent = readdir(dir))) {
        /* Ignore files that end in '~' or have a '.' in them. */
        if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~'
@@ -783,54 +793,47 @@ switch_dir(struct include_stack *stack, char *dirpath)
        if (pl == NULL)
            goto bad;
        pl->path = path;
-       pl->next = first;
-       first = pl;
+       if (count >= max_paths) {
+           struct path_list **tmp;
+           max_paths <<= 1;
+           tmp = realloc(paths, sizeof(*paths) * max_paths);
+           if (tmp == NULL) {
+               closedir(dir);
+               goto bad;
+           }
+           paths = tmp;
+       }
+       paths[count++] = pl;
        path = NULL;
-       count++;
     }
     closedir(dir);
 
     if (count == 0)
        goto done;
 
-    /* Sort the list as an array. */
-    sorted = malloc(sizeof(*sorted) * count);
-    if (sorted == NULL)
-       goto bad;
-    pl = first;
+    /* Sort the list as an array in reverse order. */
+    qsort(paths, count, sizeof(*paths), pl_compare);
+
+    /* Build up the list in sorted order. */
     for (i = 0; i < count; i++) {
-       sorted[i] = pl;
-       pl = pl->next;
+       SLIST_INSERT_HEAD(&stack->more, paths[i], entries);
     }
-    qsort(sorted, count, sizeof(*sorted), pl_compare);
-
-    /* Apply sorting to the list. */
-    first = sorted[0];
-    sorted[count - 1]->next = NULL;
-    for (i = 1; i < count; i++)
-       sorted[i - 1]->next = sorted[i];
-    efree(sorted);
 
     /* Pull out the first element for parsing, leave the rest for later. */
-    if (count) {
-       path = first->path;
-       pl = first->next;
-       efree(first);
-       stack->more = pl;
-    } else {
-       path = NULL;
-    }
+    pl = SLIST_FIRST(&stack->more);
+    SLIST_REMOVE_HEAD(&stack->more, entries);
+    path = pl->path;
+    efree(pl);
 done:
+    efree(paths);
     efree(dirpath);
     debug_return_str(path);
 bad:
-    while (first != NULL) {
-       pl = first;
-       first = pl->next;
-       efree(pl->path);
-       efree(pl);
+    for (i = 0; i < count; i++) {
+       efree(paths[i]->path);
+       efree(paths[i]);
     }
-    efree(sorted);
+    efree(paths);
     efree(dirpath);
     efree(path);
     debug_return_str(NULL);
@@ -851,8 +854,8 @@ init_lexer(void)
 
     while (idepth) {
        idepth--;
-       while ((pl = istack[idepth].more) != NULL) {
-           istack[idepth].more = pl->next;
+       while ((pl = SLIST_FIRST(&istack[idepth].more)) != NULL) {
+           SLIST_REMOVE_HEAD(&istack[idepth].more, entries);
            efree(pl->path);
            efree(pl);
        }
@@ -895,6 +898,7 @@ _push_include(char *path, bool isdir)
            debug_return_bool(false);
        }
     }
+    SLIST_INIT(&istack[idepth].more);
     if (isdir) {
        struct stat sb;
        switch (sudo_secure_dir(path, sudoers_uid, sudoers_gid, &sb)) {
@@ -938,10 +942,10 @@ _push_include(char *path, bool isdir)
        while ((fp = open_sudoers(path, false, &keepopen)) == NULL) {
            /* Unable to open path in includedir, go to next one, if any. */
            efree(path);
-           if ((pl = istack[idepth].more) == NULL)
+           if ((pl = SLIST_FIRST(&istack[idepth].more)) == NULL)
                debug_return_bool(false);
+           SLIST_REMOVE_HEAD(&istack[idepth].more, entries);
            path = pl->path;
-           istack[idepth].more = pl->next;
            efree(pl);
        }
     } else {
@@ -950,7 +954,6 @@ _push_include(char *path, bool isdir)
            sudoerserror(NULL);
            debug_return_bool(false);
        }
-       istack[idepth].more = NULL;
     }
     /* Push the old (current) file and open the new one. */
     istack[idepth].path = sudoers; /* push old path */
@@ -979,10 +982,10 @@ pop_include(void)
        fclose(YY_CURRENT_BUFFER->yy_input_file);
     sudoers_delete_buffer(YY_CURRENT_BUFFER);
     /* If we are in an include dir, move to the next file. */
-    while ((pl = istack[idepth - 1].more) != NULL) {
+    while ((pl = SLIST_FIRST(&istack[idepth - 1].more)) != NULL) {
+       SLIST_REMOVE_HEAD(&istack[idepth - 1].more, entries);
        fp = open_sudoers(pl->path, false, &keepopen);
        if (fp != NULL) {
-           istack[idepth - 1].more = pl->next;
            efree(sudoers);
            sudoers = pl->path;
            sudolineno = 1;
@@ -991,7 +994,6 @@ pop_include(void)
            break;
        }
        /* Unable to open path in include dir, go to next one. */
-       istack[idepth - 1].more = pl->next;
        efree(pl->path);
        efree(pl);
     }
index 79418de270b42ae16feee27be454f2608b455616..5228083c262e3873c3915a0495fec0a419b188ee 100644 (file)
@@ -79,7 +79,6 @@
 #include "sudoers.h"
 #include "parse.h"
 #include "redblack.h"
-#include "queue.h"
 #include "gettext.h"
 #include "sudoers_version.h"
 #include "sudo_conf.h"
index 9a3f93e2a9c7e99ecbcf1a941ee042c8af6ccced..55f9c4f7ef35d22135cce2cfea520563c8096790 100644 (file)
@@ -231,7 +231,7 @@ hooks.o: $(srcdir)/hooks.c $(top_builddir)/config.h $(srcdir)/sudo.h \
          $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/fatal.h \
          $(incdir)/fileops.h $(incdir)/sudo_conf.h $(incdir)/queue.h \
          $(incdir)/sudo_debug.h $(incdir)/gettext.h $(incdir)/sudo_plugin.h \
-         $(srcdir)/sudo_plugin_int.h $(incdir)/sudo_debug.h
+         $(srcdir)/sudo_plugin_int.h $(incdir)/sudo_debug.h $(incdir)/queue.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/hooks.c
 load_plugins.o: $(srcdir)/load_plugins.c $(top_builddir)/config.h \
                 $(top_srcdir)/compat/dlfcn.h $(srcdir)/sudo.h \
index a4a635e3fee0cec6017778491d652b57212d5376..7aaa8b0f2482b3b27d5b332ab2dfd34a89f416f7 100644 (file)
@@ -77,7 +77,7 @@
 #endif
 
 struct io_buffer {
-    struct io_buffer *next;
+    SLIST_ENTRY(io_buffer) entries;
     struct sudo_event *revent;
     struct sudo_event *wevent;
     bool (*action)(const char *buf, unsigned int len);
@@ -86,10 +86,7 @@ struct io_buffer {
     char buf[32 * 1024];
 };
 
-struct io_buffer_list {
-    struct io_buffer *first;
-    /* XXX - stash cstat too? */
-};
+SLIST_HEAD(io_buffer_list, io_buffer);
 
 static char slavename[PATH_MAX];
 static bool foreground, pipeline, tty_initialized;
@@ -609,9 +606,8 @@ io_buf_new(int rfd, int wfd, bool (*action)(const char *, unsigned int),
     if (n != -1 && !ISSET(n, O_NONBLOCK))
        (void) fcntl(wfd, F_SETFL, n | O_NONBLOCK);
 
-    /* Add to head of list. */
+    /* Allocate and add to head of list. */
     iob = emalloc(sizeof(*iob));
-    iob->next = head->first;
     iob->revent = sudo_ev_alloc(rfd, SUDO_EV_READ, io_callback, iob);
     iob->wevent = sudo_ev_alloc(wfd, SUDO_EV_WRITE, io_callback, iob);
     iob->len = 0;
@@ -620,7 +616,7 @@ io_buf_new(int rfd, int wfd, bool (*action)(const char *, unsigned int),
     iob->buf[0] = '\0';
     if (iob->revent == NULL || iob->wevent == NULL)
        fatal(NULL);
-    head->first = iob;
+    SLIST_INSERT_HEAD(head, iob, entries);
 
     debug_return;
 }
@@ -822,8 +818,8 @@ pty_close(struct command_status *cstat)
     del_io_events();
 
     /* Free I/O buffers. */
-    while ((iob = iobufs.first) != NULL) {
-       iobufs.first = iob->next;
+    while ((iob = SLIST_FIRST(&iobufs)) != NULL) {
+       SLIST_REMOVE_HEAD(&iobufs, entries);
        efree(iob);
     }
 
@@ -871,7 +867,7 @@ add_io_events(struct sudo_event_base *evbase)
      * Schedule writers that contain buffered data.
      * Normally, write buffers are added on demand when data is read.
      */
-    for (iob = iobufs.first; iob != NULL; iob = iob->next) {
+    SLIST_FOREACH(iob, &iobufs, entries) {
        /* Don't read/write from /dev/tty if we are not in the foreground. */
        if (iob->revent != NULL &&
            (ttymode == TERM_RAW || !USERTTY_EVENT(iob->revent))) {
@@ -909,7 +905,7 @@ del_io_events(void)
     debug_decl(del_io_events, SUDO_DEBUG_EXEC);
 
     /* Remove iobufs from existing event base. */
-    for (iob = iobufs.first; iob != NULL; iob = iob->next) {
+    SLIST_FOREACH(iob, &iobufs, entries) {
        if (iob->revent != NULL) {
            sudo_debug_printf(SUDO_DEBUG_INFO,
                "deleted I/O revent %p, fd %d, events %d",
@@ -930,7 +926,7 @@ del_io_events(void)
        fatal(NULL);
 
     /* Avoid reading from /dev/tty, just flush existing data. */
-    for (iob = iobufs.first; iob != NULL; iob = iob->next) {
+    SLIST_FOREACH(iob, &iobufs, entries) {
        /* Don't read from /dev/tty while flushing. */
        if (iob->revent != NULL && !USERTTY_EVENT(iob->revent)) {
            if (iob->len != sizeof(iob->buf)) {
@@ -951,7 +947,7 @@ del_io_events(void)
     (void) sudo_ev_loop(evbase, SUDO_EVLOOP_NONBLOCK);
 
     /* Free temporary event base. */
-    for (iob = iobufs.first; iob != NULL; iob = iob->next) {
+    SLIST_FOREACH(iob, &iobufs, entries) {
        if (iob->revent != NULL)
            sudo_ev_del(evbase, iob->revent);
        if (iob->wevent != NULL)
@@ -1484,7 +1480,7 @@ safe_close(int fd)
        debug_return_int(-1);
     }
     /* Deschedule any other users of the fd. */
-    for (iob = iobufs.first; iob != NULL; iob = iob->next) {
+    SLIST_FOREACH(iob, &iobufs, entries) {
        if (iob->revent != NULL) {
            if (sudo_ev_get_fd(iob->revent) == fd) {
                sudo_debug_printf(SUDO_DEBUG_INFO,
index 1c5f4f4b54b95ee9bb66974d7b47fe06cf97fba5..25edff66a05855c25e502466001832a357076c04 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2012-2013 Todd C. Miller <Todd.Miller@courtesan.com>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #include "sudo_plugin.h"
 #include "sudo_plugin_int.h"
 #include "sudo_debug.h"
+#include "queue.h"
 
 /* Singly linked hook list. */
-struct sudo_hook_list {
-    struct sudo_hook_list *next;
+struct sudo_hook_entry {
+    SLIST_ENTRY(sudo_hook_entry) entries;
     union {
        sudo_hook_fn_t generic_fn;
        sudo_hook_fn_setenv_t setenv_fn;
@@ -53,22 +54,27 @@ struct sudo_hook_list {
     } u;
     void *closure;
 };
+SLIST_HEAD(sudo_hook_list, sudo_hook_entry);
 
 /* Each hook type gets own hook list. */
-static struct sudo_hook_list *sudo_hook_setenv_list;
-static struct sudo_hook_list *sudo_hook_unsetenv_list;
-static struct sudo_hook_list *sudo_hook_getenv_list;
-static struct sudo_hook_list *sudo_hook_putenv_list;
+static struct sudo_hook_list sudo_hook_setenv_list =
+    SLIST_HEAD_INITIALIZER(sudo_hook_setenv_list);
+static struct sudo_hook_list sudo_hook_unsetenv_list =
+    SLIST_HEAD_INITIALIZER(sudo_hook_unsetenv_list);
+static struct sudo_hook_list sudo_hook_getenv_list =
+    SLIST_HEAD_INITIALIZER(sudo_hook_getenv_list);
+static struct sudo_hook_list sudo_hook_putenv_list =
+    SLIST_HEAD_INITIALIZER(sudo_hook_putenv_list);
 
 /* NOTE: must not anything that might call setenv() */
 int
 process_hooks_setenv(const char *name, const char *value, int overwrite)
 {
-    struct sudo_hook_list *hook;
+    struct sudo_hook_entry *hook;
     int rc = SUDO_HOOK_RET_NEXT;
 
     /* First process the hooks. */
-    for (hook = sudo_hook_setenv_list; hook != NULL; hook = hook->next) {
+    SLIST_FOREACH(hook, &sudo_hook_setenv_list, entries) {
        rc = hook->u.setenv_fn(name, value, overwrite, hook->closure);
        switch (rc) {
            case SUDO_HOOK_RET_NEXT:
@@ -89,11 +95,11 @@ done:
 int
 process_hooks_putenv(char *string)
 {
-    struct sudo_hook_list *hook;
+    struct sudo_hook_entry *hook;
     int rc = SUDO_HOOK_RET_NEXT;
 
     /* First process the hooks. */
-    for (hook = sudo_hook_putenv_list; hook != NULL; hook = hook->next) {
+    SLIST_FOREACH(hook, &sudo_hook_putenv_list, entries) {
        rc = hook->u.putenv_fn(string, hook->closure);
        switch (rc) {
            case SUDO_HOOK_RET_NEXT:
@@ -114,12 +120,12 @@ done:
 int
 process_hooks_getenv(const char *name, char **value)
 {
-    struct sudo_hook_list *hook;
+    struct sudo_hook_entry *hook;
     char *val = NULL;
     int rc = SUDO_HOOK_RET_NEXT;
 
     /* First process the hooks. */
-    for (hook = sudo_hook_getenv_list; hook != NULL; hook = hook->next) {
+    SLIST_FOREACH(hook, &sudo_hook_getenv_list, entries) {
        rc = hook->u.getenv_fn(name, &val, hook->closure);
        switch (rc) {
            case SUDO_HOOK_RET_NEXT:
@@ -142,11 +148,11 @@ done:
 int
 process_hooks_unsetenv(const char *name)
 {
-    struct sudo_hook_list *hook;
+    struct sudo_hook_entry *hook;
     int rc = SUDO_HOOK_RET_NEXT;
 
     /* First process the hooks. */
-    for (hook = sudo_hook_unsetenv_list; hook != NULL; hook = hook->next) {
+    SLIST_FOREACH(hook, &sudo_hook_unsetenv_list, entries) {
        rc = hook->u.unsetenv_fn(name, hook->closure);
        switch (rc) {
            case SUDO_HOOK_RET_NEXT:
@@ -165,17 +171,16 @@ done:
 
 /* Hook registration internals. */
 static void
-register_hook_internal(struct sudo_hook_list **head,
+register_hook_internal(struct sudo_hook_list *head,
     int (*hook_fn)(), void *closure)
 {
-    struct sudo_hook_list *hook;
+    struct sudo_hook_entry *hook;
     debug_decl(register_hook_internal, SUDO_DEBUG_HOOKS)
 
     hook = ecalloc(1, sizeof(*hook));
     hook->u.generic_fn = hook_fn;
     hook->closure = closure;
-    hook->next = *head;
-    *head = hook;
+    SLIST_INSERT_HEAD(head, hook, entries);
 
     debug_return;
 }
@@ -220,22 +225,23 @@ register_hook(struct sudo_hook *hook)
 
 /* Hook deregistration internals. */
 static void
-deregister_hook_internal(struct sudo_hook_list **head,
+deregister_hook_internal(struct sudo_hook_list *head,
     int (*hook_fn)(), void *closure)
 {
-    struct sudo_hook_list *hook, *prev = NULL;
+    struct sudo_hook_entry *hook, *prev = NULL;
     debug_decl(deregister_hook_internal, SUDO_DEBUG_HOOKS)
 
-    for (hook = *head, prev = NULL; hook != NULL; prev = hook, hook = hook->next) {
+    SLIST_FOREACH(hook, head, entries) {
        if (hook->u.generic_fn == hook_fn && hook->closure == closure) {
            /* Remove from list and free. */
            if (prev == NULL)
-               *head = hook->next;
+               SLIST_REMOVE_HEAD(head, entries);
            else
-               prev->next = hook->next;
+               SLIST_REMOVE_AFTER(prev, entries);
            efree(hook);
            break;
        }
+       prev = hook;
     }
 
     debug_return;