common/fmt_string.c
common/gidlist.c
common/lbuf.c
-common/list.c
common/regress/sudo_conf/conf_test.c
common/regress/sudo_conf/test1.in
common/regress/sudo_conf/test1.out.ok
common/regress/sudo_parseln/test5.out.ok
common/regress/sudo_parseln/test6.in
common/regress/sudo_parseln/test6.out.ok
+common/regress/tailq/hltq_test.c
common/secure_path.c
common/setgroups.c
common/sudo_conf.c
include/fileops.h
include/gettext.h
include/lbuf.h
-include/list.h
include/missing.h
include/queue.h
include/secure_path.h
SSP_LDFLAGS = @SSP_LDFLAGS@
# Regression tests
-TEST_PROGS = conf_test parseln_test
+TEST_PROGS = conf_test parseln_test hltq_test
TEST_LIBS = @LIBS@ @LIBINTL@ ../compat/libreplace.la
TEST_LDFLAGS = @LDFLAGS@
SHELL = @SHELL@
LTOBJS = alloc.lo atobool.lo atoid.lo event.lo fatal.lo fileops.lo \
- fmt_string.lo gidlist.lo lbuf.lo list.lo secure_path.lo \
+ fmt_string.lo gidlist.lo lbuf.lo secure_path.lo \
setgroups.lo sudo_conf.lo sudo_debug.lo sudo_printf.lo term.lo \
ttysize.lo @COMMON_OBJS@
CONF_TEST_OBJS = conf_test.lo
+HLTQ_TEST_OBJS = hltq_test.lo
+
all: libcommon.la
Makefile: $(srcdir)/Makefile.in
parseln_test: $(PARSELN_TEST_OBJS) libcommon.la
$(LIBTOOL) --mode=link $(CC) -o $@ $(PARSELN_TEST_OBJS) libcommon.la $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+hltq_test: $(HLTQ_TEST_OBJS) libcommon.la
+ $(LIBTOOL) --mode=link $(CC) -o $@ $(HLTQ_TEST_OBJS) libcommon.la $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
pre-install:
install:
check: $(TEST_PROGS)
@if test X"$(cross_compiling)" != X"yes"; then \
passed=0; failed=0; total=0; \
+ total=1; \
+ if ./hltq_test; then \
+ passed=`expr $$passed + 1`; \
+ else \
+ failed=`expr $$failed + 1`; \
+ fi; \
for dir in sudo_conf sudo_parseln; do \
mkdir -p regress/$$dir; \
for t in $(srcdir)/regress/$$dir/*.in; do \
$(incdir)/missing.h $(incdir)/alloc.h $(incdir)/fatal.h \
$(incdir)/sudo_debug.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/gidlist.c
+hltq_test.lo: $(srcdir)/regress/tailq/hltq_test.c $(top_builddir)/config.h \
+ $(top_srcdir)/compat/stdbool.h $(incdir)/missing.h \
+ $(incdir)/fatal.h $(incdir)/queue.h
+ $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/tailq/hltq_test.c
lbuf.lo: $(srcdir)/lbuf.c $(top_builddir)/config.h $(incdir)/missing.h \
$(incdir)/alloc.h $(incdir)/fatal.h $(incdir)/lbuf.h \
$(incdir)/sudo_debug.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/lbuf.c
-list.lo: $(srcdir)/list.c $(top_builddir)/config.h $(incdir)/missing.h \
- $(incdir)/list.h $(incdir)/fatal.h
- $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/list.c
parseln_test.lo: $(srcdir)/regress/sudo_parseln/parseln_test.c \
$(top_builddir)/config.h $(top_srcdir)/compat/stdbool.h \
$(incdir)/missing.h $(incdir)/fileops.h
+++ /dev/null
-/*
- * Copyright (c) 2007-2008, 2010-2012 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
- * 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.
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <config.h>
-
-#include <sys/types.h>
-#include <stdio.h>
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif /* STDC_HEADERS */
-
-#include "missing.h"
-#include "list.h"
-#ifdef DEBUG
-# include "fatal.h"
-#endif
-
-struct list_proto {
- struct list_proto *prev;
- struct list_proto *next;
-};
-
-struct list_head_proto {
- struct list_proto *first;
- struct list_proto *last;
-};
-
-/*
- * Pop the last element off the end of vh.
- * Returns the popped element.
- */
-void *
-tq_pop(void *vh)
-{
- struct list_head_proto *h = (struct list_head_proto *)vh;
- void *last = NULL;
-
- if (!tq_empty(h)) {
- last = (void *)h->last;
- if (h->first == h->last) {
- h->first = NULL;
- h->last = NULL;
- } else {
- h->last = h->last->prev;
- h->last->next = NULL;
- }
- }
- return last;
-}
-
-/*
- * Convert from a semi-circle queue to normal doubly-linked list
- * with a head node.
- */
-void
-list2tq(void *vh, void *vl)
-{
- struct list_head_proto *h = (struct list_head_proto *)vh;
- struct list_proto *l = (struct list_proto *)vl;
-
- if (l != NULL) {
-#ifdef DEBUG
- if (l->prev == NULL) {
- warningx_nodebug("list2tq called with non-semicircular list");
- abort();
- }
-#endif
- h->first = l;
- h->last = l->prev; /* l->prev points to the last member of l */
- l->prev = NULL; /* zero last ptr now that we have a head */
- } else {
- h->first = NULL;
- h->last = NULL;
- }
-}
-
-/*
- * Append one queue (or single entry) to another using the
- * circular properties of the prev pointer to simplify the logic.
- */
-void
-list_append(void *vl1, void *vl2)
-{
- struct list_proto *l1 = (struct list_proto *)vl1;
- struct list_proto *l2 = (struct list_proto *)vl2;
- void *tail = l2->prev;
-
- l1->prev->next = l2;
- l2->prev = l1->prev;
- l1->prev = tail;
-}
-
-/*
- * Append the list of entries to the head node and convert
- * from a semi-circle queue to normal doubly-linked list.
- */
-void
-tq_append(void *vh, void *vl)
-{
- struct list_head_proto *h = (struct list_head_proto *)vh;
- struct list_proto *l = (struct list_proto *)vl;
- void *tail = l->prev;
-
- if (h->first == NULL)
- h->first = l;
- else
- h->last->next = l;
- l->prev = h->last;
- h->last = tail;
-}
-
-/*
- * Remove element from the tail_queue
- */
-void
-tq_remove(void *vh, void *vl)
-{
- struct list_head_proto *h = (struct list_head_proto *)vh;
- struct list_proto *l = (struct list_proto *)vl;
-
- if (h->first == l && h->last == l) {
- /* Single element in the list. */
- h->first = NULL;
- h->last = NULL;
- } else {
- /* At least two elements in the list. */
- if (h->first == l) {
- h->first = l->next;
- h->first->prev = h->first;
- } else if (h->last == l) {
- h->last = l->prev;
- h->last->next = NULL;
- } else {
- l->prev->next = l->next;
- l->next->prev = l->prev;
- }
- }
-}
--- /dev/null
+/*
+ * Copyright (c) 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
+ * 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>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
+# include <memory.h>
+# endif
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include "compat/stdbool.h"
+#endif
+
+#include "missing.h"
+#include "fatal.h"
+#include "queue.h"
+
+__dso_public int main(int argc, char *argv[]);
+
+/*
+ * Note: HLTQ_ENTRY is intentionally in the middle of the struct
+ * to catch bad assumptions in the PREV/NEXT macros.
+ */
+struct test_data {
+ int a;
+ HLTQ_ENTRY(test_data) entries;
+ char b;
+};
+
+TAILQ_HEAD(test_data_list, test_data);
+
+/*
+ * Simple tests for headless tail queue macros.
+ */
+int
+main(int argc, char *argv[])
+{
+ struct test_data d1, d2, d3;
+ struct test_data *hltq;
+ struct test_data_list tq;
+ int errors = 0;
+
+ /*
+ * Initialize three data elements and concatenate them in order.
+ */
+ HLTQ_INIT(&d1, entries);
+ d1.a = 1;
+ d1.b = 'a';
+ if (HLTQ_FIRST(&d1) != &d1) {
+ warningx_nodebug("FAIL: HLTQ_FIRST(1 entry) doesn't return first element: got %p, expected %p", HLTQ_FIRST(&d1), &d1);
+ errors++;
+ }
+ if (HLTQ_LAST(&d1, test_data, entries) != &d1) {
+ warningx_nodebug("FAIL: HLTQ_LAST(1 entry) doesn't return first element: got %p, expected %p", HLTQ_LAST(&d1, test_data, entries), &d1);
+ errors++;
+ }
+ if (HLTQ_PREV(&d1, test_data, entries) != NULL) {
+ warningx_nodebug("FAIL: HLTQ_PREV(1 entry) doesn't return NULL: got %p", HLTQ_PREV(&d1, test_data, entries));
+ errors++;
+ }
+
+ HLTQ_INIT(&d2, entries);
+ d2.a = 2;
+ d2.b = 'b';
+
+ HLTQ_INIT(&d3, entries);
+ d3.a = 3;
+ d3.b = 'c';
+
+ HLTQ_CONCAT(&d1, &d2, entries);
+ HLTQ_CONCAT(&d1, &d3, entries);
+ hltq = &d1;
+
+ /*
+ * Verify that HLTQ_FIRST, HLTQ_LAST, HLTQ_NEXT, HLTQ_PREV
+ * work as expected.
+ */
+ if (HLTQ_FIRST(hltq) != &d1) {
+ warningx_nodebug("FAIL: HLTQ_FIRST(3 entries) doesn't return first element: got %p, expected %p", HLTQ_FIRST(hltq), &d1);
+ errors++;
+ }
+ if (HLTQ_LAST(hltq, test_data, entries) != &d3) {
+ warningx_nodebug("FAIL: HLTQ_LAST(3 entries) doesn't return third element: got %p, expected %p", HLTQ_LAST(hltq, test_data, entries), &d3);
+ errors++;
+ }
+
+ if (HLTQ_NEXT(&d1, entries) != &d2) {
+ warningx_nodebug("FAIL: HLTQ_NEXT(&d1) doesn't return &d2: got %p, expected %p", HLTQ_NEXT(&d1, entries), &d2);
+ errors++;
+ }
+ if (HLTQ_NEXT(&d2, entries) != &d3) {
+ warningx_nodebug("FAIL: HLTQ_NEXT(&d2) doesn't return &d3: got %p, expected %p", HLTQ_NEXT(&d2, entries), &d3);
+ errors++;
+ }
+ if (HLTQ_NEXT(&d3, entries) != NULL) {
+ warningx_nodebug("FAIL: HLTQ_NEXT(&d3) doesn't return NULL: got %p", HLTQ_NEXT(&d3, entries));
+ errors++;
+ }
+
+ if (HLTQ_PREV(&d1, test_data, entries) != NULL) {
+ warningx_nodebug("FAIL: HLTQ_PREV(&d1) doesn't return NULL: got %p", HLTQ_PREV(&d1, test_data, entries));
+ errors++;
+ }
+ if (HLTQ_PREV(&d2, test_data, entries) != &d1) {
+ warningx_nodebug("FAIL: HLTQ_PREV(&d2) doesn't return &d1: got %p, expected %p", HLTQ_PREV(&d2, test_data, entries), &d1);
+ errors++;
+ }
+ if (HLTQ_PREV(&d3, test_data, entries) != &d2) {
+ warningx_nodebug("FAIL: HLTQ_PREV(&d3) doesn't return &d2: got %p, expected %p", HLTQ_PREV(&d3, test_data, entries), &d2);
+ errors++;
+ }
+
+ /* Test conversion to TAILQ. */
+ HLTQ_TO_TAILQ(&tq, hltq, entries);
+
+ if (TAILQ_FIRST(&tq) != &d1) {
+ warningx_nodebug("FAIL: TAILQ_FIRST(&tq) doesn't return first element: got %p, expected %p", TAILQ_FIRST(&tq), &d1);
+ errors++;
+ }
+ if (TAILQ_LAST(&tq, test_data_list) != &d3) {
+ warningx_nodebug("FAIL: TAILQ_LAST(&tq) doesn't return third element: got %p, expected %p", TAILQ_LAST(&tq, test_data_list), &d3);
+ errors++;
+ }
+
+ if (TAILQ_NEXT(&d1, entries) != &d2) {
+ warningx_nodebug("FAIL: TAILQ_NEXT(&d1) doesn't return &d2: got %p, expected %p", TAILQ_NEXT(&d1, entries), &d2);
+ errors++;
+ }
+ if (TAILQ_NEXT(&d2, entries) != &d3) {
+ warningx_nodebug("FAIL: TAILQ_NEXT(&d2) doesn't return &d3: got %p, expected %p", TAILQ_NEXT(&d2, entries), &d3);
+ errors++;
+ }
+ if (TAILQ_NEXT(&d3, entries) != NULL) {
+ warningx_nodebug("FAIL: TAILQ_NEXT(&d3) doesn't return NULL: got %p", TAILQ_NEXT(&d3, entries));
+ errors++;
+ }
+
+ if (TAILQ_PREV(&d1, test_data_list, entries) != NULL) {
+ warningx_nodebug("FAIL: TAILQ_PREV(&d1) doesn't return NULL: got %p", TAILQ_PREV(&d1, test_data_list, entries));
+ errors++;
+ }
+ if (TAILQ_PREV(&d2, test_data_list, entries) != &d1) {
+ warningx_nodebug("FAIL: TAILQ_PREV(&d2) doesn't return &d1: got %p, expected %p", TAILQ_PREV(&d2, test_data_list, entries), &d1);
+ errors++;
+ }
+ if (TAILQ_PREV(&d3, test_data_list, entries) != &d2) {
+ warningx_nodebug("FAIL: TAILQ_PREV(&d3) doesn't return &d2: got %p, expected %p", TAILQ_PREV(&d3, test_data_list, entries), &d2);
+ errors++;
+ }
+
+ exit(errors);
+}
+
+/* STUB */
+void
+warning_set_locale(void)
+{
+ return;
+}
+
+/* STUB */
+void
+warning_restore_locale(void)
+{
+ return;
+}
+++ /dev/null
-/*
- * Copyright (c) 2007, 2010 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
- * 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 _SUDO_LIST_H
-#define _SUDO_LIST_H
-
-/*
- * Convenience macro for declaring a list head.
- */
-#define TQ_DECLARE(n) \
-struct n##_list { \
- struct n *first; \
- struct n *last; \
-};
-
-/*
- * Foreach loops: forward and reverse
- */
-#undef tq_foreach_fwd
-#define tq_foreach_fwd(h, v) \
- for ((v) = (h)->first; (v) != NULL; (v) = (v)->next)
-
-#undef tq_foreach_rev
-#define tq_foreach_rev(h, v) \
- for ((v) = (h)->last; (v) != NULL; (v) = (v)->prev)
-
-/*
- * Init a list head.
- */
-#undef tq_init
-#define tq_init(h) do { \
- (h)->first = NULL; \
- (h)->last = NULL; \
-} while (0)
-
-/*
- * Simple macros to avoid exposing first/last and prev/next.
- */
-#undef tq_empty
-#define tq_empty(h) ((h)->first == NULL)
-
-#undef tq_first
-#define tq_first(h) ((h)->first)
-
-#undef tq_last
-#define tq_last(h) ((h)->last)
-
-#undef list_next
-#define list_next(e) ((e)->next)
-
-#undef list_prev
-#define list_prev(e) ((e)->prev)
-
-/*
- * Prototypes for list.c
- */
-void *tq_pop(void *);
-void tq_append(void *, void *);
-void tq_remove(void *, void *);
-void list_append(void *, void *);
-void list2tq(void *, void *);
-
-#endif /* _SUDO_LIST_H */
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
+ * A headless tail queue lacks a head structure, The first element acts
+ * as a de facto list head. It uses the same entry struct as a regular
+ * tail queue for easy conversion from headless to headful.
+ * It is capable of concatenating queues as well as individual elements.
+ * Traversing in reverse is more expensive due to lack of a list head.
+ * Note: elements must be initialized before use.
+ *
* For details on the use of these macros, see the queue(3) manual page.
*
*
(head2)->tqh_last = &(head2)->tqh_first; \
} while (0)
+/*
+ * Headless Tail queue definitions.
+ */
+#undef HLTQ_ENTRY
+#define HLTQ_ENTRY(type) TAILQ_ENTRY(type)
+
+#undef HLTQ_INIT
+#define HLTQ_INIT(entry, field) do { \
+ (entry)->field.tqe_next = NULL; \
+ (entry)->field.tqe_prev = &(entry)->field.tqe_next; \
+} while (0)
+
+#undef HLTQ_INITIALIZER
+#define HLTQ_INITIALIZER(entry, field) \
+ { NULL, &(entry)->field.tqe_next }
+
+#undef HLTQ_FIRST
+#define HLTQ_FIRST(elm) (elm)
+
+#undef HLTQ_END
+#define HLTQ_END(elm) NULL
+
+#undef HLTQ_NEXT
+#define HLTQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#undef HLTQ_LAST
+#define HLTQ_LAST(elm, type, field) \
+ ((elm)->field.tqe_next == NULL ? (elm) : \
+ __containerof((elm)->field.tqe_prev, struct type, field.tqe_next))
+
+#undef HLTQ_PREV
+#define HLTQ_PREV(elm, type, field) \
+ (*(elm)->field.tqe_prev == NULL ? NULL : \
+ __containerof((elm)->field.tqe_prev, struct type, field.tqe_next))
+
+#undef HLTQ_FOREACH
+#define HLTQ_FOREACH(var, head, field) \
+ for ((var) = HLTQ_FIRST(head); \
+ (var) != HLTQ_END(head); \
+ (var) = HLTQ_NEXT(var, field))
+
+#undef HLTQ_FOREACH_SAFE
+#define HLTQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = HLTQ_FIRST(head); \
+ (var) != HLTQ_END(head) && \
+ ((tvar) = HLTQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+#undef HLTQ_FOREACH_REVERSE
+#define HLTQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = HLTQ_LAST(head, headname); \
+ (var) != HLTQ_END(head); \
+ (var) = HLTQ_PREV(var, headname, field))
+
+#undef HLTQ_FOREACH_REVERSE_SAFE
+#define HLTQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = HLTQ_LAST(head, headname); \
+ (var) != HLTQ_END(head) && \
+ ((tvar) = HLTQ_PREV(var, headname, field), 1); \
+ (var) = (tvar))
+
+/* Concatenate queue2 to the end of queue1. */
+#undef HLTQ_CONCAT
+#define HLTQ_CONCAT(queue1, queue2, field) do { \
+ (queue2)->field.tqe_prev = (queue1)->field.tqe_prev; \
+ *(queue1)->field.tqe_prev = (queue2); \
+ (queue1)->field.tqe_prev = &(queue2)->field.tqe_next; \
+} while (0)
+
+/* Convert a headless tailq to a headful one. */
+#define HLTQ_TO_TAILQ(head, hl, field) do { \
+ (head)->tqh_first = (hl); \
+ (head)->tqh_last = (hl)->field.tqe_prev; \
+ (hl)->field.tqe_prev = &(head)->tqh_first; \
+} while (0)
+
+/* Concatenate a headless tail queue to the end of a regular tail queue. */
+#define TAILQ_CONCAT_HLTQ(head, hl, field) do { \
+ void *last = (hl)->field.tqe_prev; \
+ (hl)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (hl); \
+ (head)->tqh_last = last; \
+} while (0)
+
#endif /* !_SUDO_QUEUE_H_ */
$(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.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 \
- $(devdir)/gram.h
+ $(srcdir)/parse.h $(srcdir)/redblack.h $(devdir)/gram.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/alias.c
audit.lo: $(srcdir)/audit.c $(top_builddir)/config.h \
$(top_srcdir)/compat/stdbool.h $(incdir)/missing.h \
$(incdir)/fileops.h $(srcdir)/defaults.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)/interfaces.h
+ $(srcdir)/interfaces.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/parser/check_addr.c
check_base64.o: $(srcdir)/regress/parser/check_base64.c \
$(top_builddir)/config.h $(incdir)/missing.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/parser/check_digest.c
check_fill.o: $(srcdir)/regress/parser/check_fill.c $(top_builddir)/config.h \
$(top_srcdir)/compat/stdbool.h $(incdir)/missing.h \
- $(incdir)/list.h $(srcdir)/parse.h $(incdir)/list.h \
- $(srcdir)/toke.h $(incdir)/sudo_plugin.h $(devdir)/gram.h
+ $(incdir)/queue.h $(srcdir)/parse.h $(srcdir)/toke.h \
+ $(incdir)/sudo_plugin.h $(devdir)/gram.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/parser/check_fill.c
check_iolog_path.o: $(srcdir)/regress/iolog_path/check_iolog_path.c \
$(top_builddir)/config.h $(srcdir)/sudoers.h \
$(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.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 \
- $(devdir)/gram.h $(devdir)/def_data.c
+ $(incdir)/gettext.h $(srcdir)/parse.h $(devdir)/gram.h \
+ $(devdir)/def_data.c
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/defaults.c
env.lo: $(srcdir)/env.c $(top_builddir)/config.h $(srcdir)/sudoers.h \
$(top_srcdir)/compat/stdbool.h $(top_builddir)/pathnames.h \
$(incdir)/alloc.h $(incdir)/queue.h $(incdir)/fileops.h \
$(srcdir)/defaults.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)/toke.h
+ $(incdir)/gettext.h $(srcdir)/parse.h $(srcdir)/toke.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(devdir)/gram.c
group_plugin.lo: $(srcdir)/group_plugin.c $(top_builddir)/config.h \
$(top_srcdir)/compat/dlfcn.h $(srcdir)/sudoers.h \
$(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.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 $(incdir)/lbuf.h
+ $(srcdir)/parse.h $(incdir)/lbuf.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/ldap.c
linux_audit.lo: $(srcdir)/linux_audit.c $(top_builddir)/config.h \
$(incdir)/missing.h $(incdir)/fatal.h $(incdir)/alloc.h \
$(incdir)/alloc.h $(incdir)/queue.h $(incdir)/fileops.h \
$(srcdir)/defaults.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)/sha2.h $(devdir)/gram.h
+ $(incdir)/gettext.h $(srcdir)/parse.h $(srcdir)/sha2.h \
+ $(devdir)/gram.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/match.c
match_addr.lo: $(srcdir)/match_addr.c $(top_builddir)/config.h \
$(srcdir)/sudoers.h $(top_srcdir)/compat/stdbool.h \
$(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.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 $(incdir)/lbuf.h $(devdir)/gram.h
+ $(srcdir)/parse.h $(incdir)/lbuf.h $(devdir)/gram.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/parse.c
passwd.lo: $(authdir)/passwd.c $(top_builddir)/config.h $(srcdir)/sudoers.h \
$(top_srcdir)/compat/stdbool.h $(top_builddir)/pathnames.h \
$(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.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 $(incdir)/lbuf.h \
- $(incdir)/sudo_debug.h
+ $(srcdir)/parse.h $(incdir)/lbuf.h $(incdir)/sudo_debug.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sssd.c
sudo_auth.lo: $(authdir)/sudo_auth.c $(top_builddir)/config.h \
$(srcdir)/sudoers.h $(top_srcdir)/compat/stdbool.h \
$(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \
$(incdir)/gettext.h $(srcdir)/interfaces.h $(srcdir)/parse.h \
- $(incdir)/list.h $(incdir)/sudo_conf.h $(incdir)/queue.h \
- $(incdir)/secure_path.h $(devdir)/gram.h
+ $(incdir)/sudo_conf.h $(incdir)/queue.h $(incdir)/secure_path.h \
+ $(devdir)/gram.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/testsudoers.c
timestamp.lo: $(srcdir)/timestamp.c $(top_builddir)/config.h \
$(srcdir)/sudoers.h $(top_srcdir)/compat/stdbool.h \
$(incdir)/alloc.h $(incdir)/queue.h $(incdir)/fileops.h \
$(srcdir)/defaults.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)/toke.h $(devdir)/gram.h $(incdir)/lbuf.h $(srcdir)/sha2.h \
+ $(incdir)/gettext.h $(srcdir)/parse.h $(srcdir)/toke.h \
+ $(devdir)/gram.h $(incdir)/lbuf.h $(srcdir)/sha2.h \
$(incdir)/secure_path.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(devdir)/toke.c
toke_util.lo: $(srcdir)/toke_util.c $(top_builddir)/config.h \
$(incdir)/fileops.h $(srcdir)/defaults.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)/toke.h $(devdir)/gram.h
+ $(srcdir)/toke.h $(devdir)/gram.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/toke_util.c
toke_util.o: toke_util.lo
tsgetgrpw.o: $(srcdir)/tsgetgrpw.c $(top_builddir)/config.h \
$(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.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)/gettext.h $(srcdir)/sudoers_version.h \
- $(incdir)/sudo_conf.h $(incdir)/queue.h $(devdir)/gram.h
+ $(srcdir)/parse.h $(srcdir)/redblack.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
a->name = name;
a->type = type;
/* a->used = false; */
- list2tq(&a->members, members);
+ HLTQ_TO_TAILQ(&a->members, members, entries);
if (rbinsert(aliases, a)) {
snprintf(errbuf, sizeof(errbuf), N_("Alias `%s' already defined"), name);
alias_free(a);
debug_decl(alias_free, SUDO_DEBUG_ALIAS)
efree(a->name);
- for (m = a->members.first; m != NULL; m = next) {
- next = m->next;
+ TAILQ_FOREACH_SAFE(m, &a->members, entries, next) {
if (m->type == COMMAND) {
c = (struct sudo_command *) m->name;
efree(c->cmnd);
bool rc = true;
debug_decl(update_defaults, SUDO_DEBUG_DEFAULTS)
- tq_foreach_fwd(&defaults, def) {
+ TAILQ_FOREACH(def, &defaults, entries) {
switch (def->type) {
case DEFAULTS:
if (ISSET(what, SETDEF_GENERIC) &&
#if 1
if (ISSET(what, SETDEF_USER)) {
int m;
- m = userlist_matches(sudo_user.pw, &def->binding);
+ m = userlist_matches(sudo_user.pw, def->binding);
if (m == ALLOW) {
if (!set_default(def->var, def->val, def->op))
rc = false;
}
#else
if (ISSET(what, SETDEF_USER) &&
- userlist_matches(sudo_user.pw, &def->binding) == ALLOW &&
+ userlist_matches(sudo_user.pw, def->binding) == ALLOW &&
!set_default(def->var, def->val, def->op))
rc = false;
#endif
break;
case DEFAULTS_RUNAS:
if (ISSET(what, SETDEF_RUNAS) &&
- runaslist_matches(&def->binding, NULL, NULL, NULL) == ALLOW &&
+ runaslist_matches(def->binding, NULL, NULL, NULL) == ALLOW &&
!set_default(def->var, def->val, def->op))
rc = false;
break;
case DEFAULTS_HOST:
if (ISSET(what, SETDEF_HOST) &&
- hostlist_matches(&def->binding) == ALLOW &&
+ hostlist_matches(def->binding) == ALLOW &&
!set_default(def->var, def->val, def->op))
rc = false;
break;
case DEFAULTS_CMND:
if (ISSET(what, SETDEF_CMND) &&
- cmndlist_matches(&def->binding) == ALLOW &&
+ cmndlist_matches(def->binding) == ALLOW &&
!set_default(def->var, def->val, def->op))
rc = false;
break;
bool rc = true;
debug_decl(check_defaults, SUDO_DEBUG_DEFAULTS)
- tq_foreach_fwd(&defaults, def) {
+ TAILQ_FOREACH(def, &defaults, entries) {
switch (def->type) {
case DEFAULTS:
if (!ISSET(what, SETDEF_GENERIC))
int errorlineno = -1;
char *errorfile = NULL;
-struct defaults_list defaults;
-struct userspec_list userspecs;
+struct defaults_list defaults = TAILQ_HEAD_INITIALIZER(defaults);
+struct userspec_list userspecs = TAILQ_HEAD_INITIALIZER(userspecs);
/*
* Local protoypes
short *yysslim;
YYSTYPE *yyvs;
int yystacksize;
-#line 681 "gram.y"
+#line 688 "gram.y"
void
sudoerserror(const char *s)
{
d = ecalloc(1, sizeof(struct defaults));
d->var = var;
d->val = val;
- tq_init(&d->binding);
/* d->type = 0; */
d->op = op;
- d->prev = d;
- /* d->next = NULL; */
+ /* d->binding = NULL */
+ HLTQ_INIT(d, entries);
debug_return_ptr(d);
}
m = ecalloc(1, sizeof(struct member));
m->name = name;
m->type = type;
- m->prev = m;
- /* m->next = NULL; */
+ HLTQ_INIT(m, entries);
debug_return_ptr(m);
}
add_defaults(int type, struct member *bmem, struct defaults *defs)
{
struct defaults *d;
- struct member_list binding;
+ struct member_list *binding;
debug_decl(add_defaults, SUDO_DEBUG_PARSER)
/*
- * We can only call list2tq once on bmem as it will zero
- * out the prev pointer when it consumes bmem.
+ * We use a single binding for each entry in defs.
*/
- list2tq(&binding, bmem);
+ binding = emalloc(sizeof(*binding));
+ if (bmem != NULL)
+ HLTQ_TO_TAILQ(binding, bmem, entries);
+ else
+ TAILQ_INIT(binding);
/*
* Set type and binding (who it applies to) for new entries.
+ * Then add to the global defaults list.
*/
- for (d = defs; d != NULL; d = d->next) {
+ HLTQ_FOREACH(d, defs, entries) {
d->type = type;
d->binding = binding;
}
- tq_append(&defaults, defs);
+ TAILQ_CONCAT_HLTQ(&defaults, defs, entries);
debug_return;
}
/*
* Allocate a new struct userspec, populate it, and insert it at the
- * and of the userspecs list.
+ * end of the userspecs list.
*/
static void
add_userspec(struct member *members, struct privilege *privs)
debug_decl(add_userspec, SUDO_DEBUG_PARSER)
u = ecalloc(1, sizeof(*u));
- list2tq(&u->users, members);
- list2tq(&u->privileges, privs);
- u->prev = u;
- /* u->next = NULL; */
- tq_append(&userspecs, u);
+ HLTQ_TO_TAILQ(&u->users, members, entries);
+ HLTQ_TO_TAILQ(&u->privileges, privs, entries);
+ TAILQ_INSERT_TAIL(&userspecs, u, entries);
debug_return;
}
void
init_parser(const char *path, bool quiet)
{
+ struct member_list *binding;
+ struct member *m;
struct defaults *d;
- struct member *m, *binding;
struct userspec *us;
struct privilege *priv;
struct cmndspec *cs;
struct sudo_command *c;
debug_decl(init_parser, SUDO_DEBUG_PARSER)
- while ((us = tq_pop(&userspecs)) != NULL) {
- while ((m = tq_pop(&us->users)) != NULL) {
+ while ((us = TAILQ_FIRST(&userspecs)) != NULL) {
+ TAILQ_REMOVE(&userspecs, us, entries);
+ while ((m = TAILQ_FIRST(&us->users)) != NULL) {
+ TAILQ_REMOVE(&us->users, m, entries);
efree(m->name);
efree(m);
}
- while ((priv = tq_pop(&us->privileges)) != NULL) {
- struct member *runasuser = NULL, *runasgroup = NULL;
+ while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) {
+ struct member_list *runasuserlist = NULL, *runasgrouplist = NULL;
#ifdef HAVE_SELINUX
char *role = NULL, *type = NULL;
#endif /* HAVE_SELINUX */
char *privs = NULL, *limitprivs = NULL;
#endif /* HAVE_PRIV_SET */
- while ((m = tq_pop(&priv->hostlist)) != NULL) {
+ TAILQ_REMOVE(&us->privileges, priv, entries);
+ while ((m = TAILQ_FIRST(&priv->hostlist)) != NULL) {
+ TAILQ_REMOVE(&priv->hostlist, m, entries);
efree(m->name);
efree(m);
}
- while ((cs = tq_pop(&priv->cmndlist)) != NULL) {
+ while ((cs = TAILQ_FIRST(&priv->cmndlist)) != NULL) {
+ TAILQ_REMOVE(&priv->cmndlist, cs, entries);
#ifdef HAVE_SELINUX
/* Only free the first instance of a role/type. */
if (cs->role != role) {
efree(cs->limitprivs);
}
#endif /* HAVE_PRIV_SET */
- if (tq_last(&cs->runasuserlist) != runasuser) {
- runasuser = tq_last(&cs->runasuserlist);
- while ((m = tq_pop(&cs->runasuserlist)) != NULL) {
+ /* Only free the first instance of runas user/group lists. */
+ if (cs->runasuserlist && cs->runasuserlist != runasuserlist) {
+ runasuserlist = cs->runasuserlist;
+ while ((m = TAILQ_FIRST(runasuserlist)) != NULL) {
+ TAILQ_REMOVE(runasuserlist, m, entries);
efree(m->name);
efree(m);
}
+ efree(runasuserlist);
}
- if (tq_last(&cs->runasgrouplist) != runasgroup) {
- runasgroup = tq_last(&cs->runasgrouplist);
- while ((m = tq_pop(&cs->runasgrouplist)) != NULL) {
+ if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) {
+ runasgrouplist = cs->runasgrouplist;
+ while ((m = TAILQ_FIRST(runasgrouplist)) != NULL) {
+ TAILQ_REMOVE(runasgrouplist, m, entries);
efree(m->name);
efree(m);
}
+ efree(runasgrouplist);
}
if (cs->cmnd->type == COMMAND) {
c = (struct sudo_command *) cs->cmnd->name;
}
efree(us);
}
- tq_init(&userspecs);
+ TAILQ_INIT(&userspecs);
binding = NULL;
- while ((d = tq_pop(&defaults)) != NULL) {
- if (tq_last(&d->binding) != binding) {
- binding = tq_last(&d->binding);
- while ((m = tq_pop(&d->binding)) != NULL) {
+ while ((d = TAILQ_FIRST(&defaults)) != NULL) {
+ TAILQ_REMOVE(&defaults, d, entries);
+ if (d->binding != binding) {
+ binding = d->binding;
+ while ((m = TAILQ_FIRST(d->binding)) != NULL) {
+ TAILQ_REMOVE(d->binding, m, entries);
if (m->type == COMMAND) {
c = (struct sudo_command *) m->name;
efree(c->cmnd);
efree(m->name);
efree(m);
}
+ efree(d->binding);
}
efree(d->var);
efree(d->val);
efree(d);
}
- tq_init(&defaults);
+ TAILQ_INIT(&defaults);
init_aliases();
debug_return;
}
-#line 898 "gram.c"
+#line 912 "gram.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
#if defined(__cplusplus) || defined(__STDC__)
static int yygrowstack(void)
case 18:
#line 232 "gram.y"
{
- list_append(yyvsp[-2].defaults, yyvsp[0].defaults);
+ HLTQ_CONCAT(yyvsp[-2].defaults, yyvsp[0].defaults, entries);
yyval.defaults = yyvsp[-2].defaults;
}
break;
case 25:
#line 256 "gram.y"
{
- list_append(yyvsp[-2].privilege, yyvsp[0].privilege);
+ HLTQ_CONCAT(yyvsp[-2].privilege, yyvsp[0].privilege, entries);
yyval.privilege = yyvsp[-2].privilege;
}
break;
#line 262 "gram.y"
{
struct privilege *p = ecalloc(1, sizeof(*p));
- list2tq(&p->hostlist, yyvsp[-2].member);
- list2tq(&p->cmndlist, yyvsp[0].cmndspec);
- p->prev = p;
- /* p->next = NULL; */
+ HLTQ_TO_TAILQ(&p->hostlist, yyvsp[-2].member, entries);
+ HLTQ_TO_TAILQ(&p->cmndlist, yyvsp[0].cmndspec, entries);
+ HLTQ_INIT(p, entries);
yyval.privilege = p;
}
break;
case 27:
-#line 272 "gram.y"
+#line 271 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 28:
-#line 276 "gram.y"
+#line 275 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 29:
-#line 282 "gram.y"
+#line 281 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
}
break;
case 30:
-#line 285 "gram.y"
+#line 284 "gram.y"
{
yyval.member = new_member(NULL, ALL);
}
break;
case 31:
-#line 288 "gram.y"
+#line 287 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NETGROUP);
}
break;
case 32:
-#line 291 "gram.y"
+#line 290 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NTWKADDR);
}
break;
case 33:
-#line 294 "gram.y"
+#line 293 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
}
break;
case 35:
-#line 300 "gram.y"
+#line 299 "gram.y"
{
- list_append(yyvsp[-2].cmndspec, yyvsp[0].cmndspec);
+ struct cmndspec *prev;
+ prev = HLTQ_LAST(yyvsp[-2].cmndspec, cmndspec, entries);
+ HLTQ_CONCAT(yyvsp[-2].cmndspec, yyvsp[0].cmndspec, entries);
#ifdef HAVE_SELINUX
/* propagate role and type */
if (yyvsp[0].cmndspec->role == NULL)
- yyvsp[0].cmndspec->role = yyvsp[0].cmndspec->prev->role;
+ yyvsp[0].cmndspec->role = prev->role;
if (yyvsp[0].cmndspec->type == NULL)
- yyvsp[0].cmndspec->type = yyvsp[0].cmndspec->prev->type;
+ yyvsp[0].cmndspec->type = prev->type;
#endif /* HAVE_SELINUX */
#ifdef HAVE_PRIV_SET
/* propagate privs & limitprivs */
if (yyvsp[0].cmndspec->privs == NULL)
- yyvsp[0].cmndspec->privs = yyvsp[0].cmndspec->prev->privs;
+ yyvsp[0].cmndspec->privs = prev->privs;
if (yyvsp[0].cmndspec->limitprivs == NULL)
- yyvsp[0].cmndspec->limitprivs = yyvsp[0].cmndspec->prev->limitprivs;
+ yyvsp[0].cmndspec->limitprivs = prev->limitprivs;
#endif /* HAVE_PRIV_SET */
/* propagate tags and runas list */
if (yyvsp[0].cmndspec->tags.nopasswd == UNSPEC)
- yyvsp[0].cmndspec->tags.nopasswd = yyvsp[0].cmndspec->prev->tags.nopasswd;
+ yyvsp[0].cmndspec->tags.nopasswd = prev->tags.nopasswd;
if (yyvsp[0].cmndspec->tags.noexec == UNSPEC)
- yyvsp[0].cmndspec->tags.noexec = yyvsp[0].cmndspec->prev->tags.noexec;
+ yyvsp[0].cmndspec->tags.noexec = prev->tags.noexec;
if (yyvsp[0].cmndspec->tags.setenv == UNSPEC &&
- yyvsp[0].cmndspec->prev->tags.setenv != IMPLIED)
- yyvsp[0].cmndspec->tags.setenv = yyvsp[0].cmndspec->prev->tags.setenv;
+ prev->tags.setenv != IMPLIED)
+ yyvsp[0].cmndspec->tags.setenv = prev->tags.setenv;
if (yyvsp[0].cmndspec->tags.log_input == UNSPEC)
- yyvsp[0].cmndspec->tags.log_input = yyvsp[0].cmndspec->prev->tags.log_input;
+ yyvsp[0].cmndspec->tags.log_input = prev->tags.log_input;
if (yyvsp[0].cmndspec->tags.log_output == UNSPEC)
- yyvsp[0].cmndspec->tags.log_output = yyvsp[0].cmndspec->prev->tags.log_output;
- if ((tq_empty(&yyvsp[0].cmndspec->runasuserlist) &&
- tq_empty(&yyvsp[0].cmndspec->runasgrouplist)) &&
- (!tq_empty(&yyvsp[0].cmndspec->prev->runasuserlist) ||
- !tq_empty(&yyvsp[0].cmndspec->prev->runasgrouplist))) {
- yyvsp[0].cmndspec->runasuserlist = yyvsp[0].cmndspec->prev->runasuserlist;
- yyvsp[0].cmndspec->runasgrouplist = yyvsp[0].cmndspec->prev->runasgrouplist;
+ yyvsp[0].cmndspec->tags.log_output = prev->tags.log_output;
+ if ((yyvsp[0].cmndspec->runasuserlist == NULL &&
+ yyvsp[0].cmndspec->runasgrouplist == NULL) &&
+ (prev->runasuserlist != NULL ||
+ prev->runasgrouplist != NULL)) {
+ yyvsp[0].cmndspec->runasuserlist = prev->runasuserlist;
+ yyvsp[0].cmndspec->runasgrouplist = prev->runasgrouplist;
}
yyval.cmndspec = yyvsp[-2].cmndspec;
}
break;
case 36:
-#line 339 "gram.y"
+#line 340 "gram.y"
{
struct cmndspec *cs = ecalloc(1, sizeof(*cs));
if (yyvsp[-4].runas != NULL) {
- list2tq(&cs->runasuserlist, yyvsp[-4].runas->runasusers);
- list2tq(&cs->runasgrouplist, yyvsp[-4].runas->runasgroups);
+ if (yyvsp[-4].runas->runasusers != NULL) {
+ cs->runasuserlist =
+ emalloc(sizeof(*cs->runasuserlist));
+ HLTQ_TO_TAILQ(cs->runasuserlist,
+ yyvsp[-4].runas->runasusers, entries);
+ }
+ if (yyvsp[-4].runas->runasgroups != NULL) {
+ cs->runasgrouplist =
+ emalloc(sizeof(*cs->runasgrouplist));
+ HLTQ_TO_TAILQ(cs->runasgrouplist,
+ yyvsp[-4].runas->runasgroups, entries);
+ }
efree(yyvsp[-4].runas);
- } else {
- tq_init(&cs->runasuserlist);
- tq_init(&cs->runasgrouplist);
}
#ifdef HAVE_SELINUX
cs->role = yyvsp[-3].seinfo.role;
#endif
cs->tags = yyvsp[-1].tag;
cs->cmnd = yyvsp[0].member;
- cs->prev = cs;
- cs->next = NULL;
+ HLTQ_INIT(cs, entries);
/* sudo "ALL" implies the SETENV tag */
if (cs->cmnd->type == ALL && !cs->cmnd->negated &&
cs->tags.setenv == UNSPEC)
}
break;
case 37:
-#line 369 "gram.y"
+#line 376 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA224, yyvsp[0].string);
}
break;
case 38:
-#line 372 "gram.y"
+#line 379 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA256, yyvsp[0].string);
}
break;
case 39:
-#line 375 "gram.y"
+#line 382 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA384, yyvsp[0].string);
}
break;
case 40:
-#line 378 "gram.y"
+#line 385 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA512, yyvsp[0].string);
}
break;
case 41:
-#line 383 "gram.y"
+#line 390 "gram.y"
{
yyval.member = yyvsp[0].member;
}
break;
case 42:
-#line 386 "gram.y"
+#line 393 "gram.y"
{
/* XXX - yuck */
struct sudo_command *c = (struct sudo_command *)(yyvsp[0].member->name);
}
break;
case 43:
-#line 394 "gram.y"
+#line 401 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 44:
-#line 398 "gram.y"
+#line 405 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 45:
-#line 404 "gram.y"
+#line 411 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 46:
-#line 409 "gram.y"
+#line 416 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 47:
-#line 414 "gram.y"
+#line 421 "gram.y"
{
yyval.seinfo.role = NULL;
yyval.seinfo.type = NULL;
}
break;
case 48:
-#line 418 "gram.y"
+#line 425 "gram.y"
{
yyval.seinfo.role = yyvsp[0].string;
yyval.seinfo.type = NULL;
}
break;
case 49:
-#line 422 "gram.y"
+#line 429 "gram.y"
{
yyval.seinfo.type = yyvsp[0].string;
yyval.seinfo.role = NULL;
}
break;
case 50:
-#line 426 "gram.y"
+#line 433 "gram.y"
{
yyval.seinfo.role = yyvsp[-1].string;
yyval.seinfo.type = yyvsp[0].string;
}
break;
case 51:
-#line 430 "gram.y"
+#line 437 "gram.y"
{
yyval.seinfo.type = yyvsp[-1].string;
yyval.seinfo.role = yyvsp[0].string;
}
break;
case 52:
-#line 436 "gram.y"
+#line 443 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 53:
-#line 440 "gram.y"
+#line 447 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 54:
-#line 445 "gram.y"
+#line 452 "gram.y"
{
yyval.privinfo.privs = NULL;
yyval.privinfo.limitprivs = NULL;
}
break;
case 55:
-#line 449 "gram.y"
+#line 456 "gram.y"
{
yyval.privinfo.privs = yyvsp[0].string;
yyval.privinfo.limitprivs = NULL;
}
break;
case 56:
-#line 453 "gram.y"
+#line 460 "gram.y"
{
yyval.privinfo.privs = NULL;
yyval.privinfo.limitprivs = yyvsp[0].string;
}
break;
case 57:
-#line 457 "gram.y"
+#line 464 "gram.y"
{
yyval.privinfo.privs = yyvsp[-1].string;
yyval.privinfo.limitprivs = yyvsp[0].string;
}
break;
case 58:
-#line 461 "gram.y"
+#line 468 "gram.y"
{
yyval.privinfo.limitprivs = yyvsp[-1].string;
yyval.privinfo.privs = yyvsp[0].string;
}
break;
case 59:
-#line 467 "gram.y"
+#line 474 "gram.y"
{
yyval.runas = NULL;
}
break;
case 60:
-#line 470 "gram.y"
+#line 477 "gram.y"
{
yyval.runas = yyvsp[-1].runas;
}
break;
case 61:
-#line 475 "gram.y"
+#line 482 "gram.y"
{
yyval.runas = ecalloc(1, sizeof(struct runascontainer));
yyval.runas->runasusers = new_member(NULL, MYSELF);
}
break;
case 62:
-#line 480 "gram.y"
+#line 487 "gram.y"
{
yyval.runas = ecalloc(1, sizeof(struct runascontainer));
yyval.runas->runasusers = yyvsp[0].member;
}
break;
case 63:
-#line 485 "gram.y"
+#line 492 "gram.y"
{
yyval.runas = ecalloc(1, sizeof(struct runascontainer));
yyval.runas->runasusers = yyvsp[-2].member;
}
break;
case 64:
-#line 490 "gram.y"
+#line 497 "gram.y"
{
yyval.runas = ecalloc(1, sizeof(struct runascontainer));
/* $$->runasusers = NULL; */
}
break;
case 65:
-#line 495 "gram.y"
+#line 502 "gram.y"
{
yyval.runas = ecalloc(1, sizeof(struct runascontainer));
yyval.runas->runasusers = new_member(NULL, MYSELF);
}
break;
case 66:
-#line 502 "gram.y"
+#line 509 "gram.y"
{
yyval.tag.nopasswd = yyval.tag.noexec = yyval.tag.setenv =
yyval.tag.log_input = yyval.tag.log_output = UNSPEC;
}
break;
case 67:
-#line 506 "gram.y"
+#line 513 "gram.y"
{
yyval.tag.nopasswd = true;
}
break;
case 68:
-#line 509 "gram.y"
+#line 516 "gram.y"
{
yyval.tag.nopasswd = false;
}
break;
case 69:
-#line 512 "gram.y"
+#line 519 "gram.y"
{
yyval.tag.noexec = true;
}
break;
case 70:
-#line 515 "gram.y"
+#line 522 "gram.y"
{
yyval.tag.noexec = false;
}
break;
case 71:
-#line 518 "gram.y"
+#line 525 "gram.y"
{
yyval.tag.setenv = true;
}
break;
case 72:
-#line 521 "gram.y"
+#line 528 "gram.y"
{
yyval.tag.setenv = false;
}
break;
case 73:
-#line 524 "gram.y"
+#line 531 "gram.y"
{
yyval.tag.log_input = true;
}
break;
case 74:
-#line 527 "gram.y"
+#line 534 "gram.y"
{
yyval.tag.log_input = false;
}
break;
case 75:
-#line 530 "gram.y"
+#line 537 "gram.y"
{
yyval.tag.log_output = true;
}
break;
case 76:
-#line 533 "gram.y"
+#line 540 "gram.y"
{
yyval.tag.log_output = false;
}
break;
case 77:
-#line 538 "gram.y"
+#line 545 "gram.y"
{
yyval.member = new_member(NULL, ALL);
}
break;
case 78:
-#line 541 "gram.y"
+#line 548 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
}
break;
case 79:
-#line 544 "gram.y"
+#line 551 "gram.y"
{
struct sudo_command *c = ecalloc(1, sizeof(*c));
c->cmnd = yyvsp[0].command.cmnd;
}
break;
case 82:
-#line 556 "gram.y"
+#line 563 "gram.y"
{
char *s;
if ((s = alias_add(yyvsp[-2].string, HOSTALIAS, yyvsp[0].member)) != NULL) {
}
break;
case 84:
-#line 566 "gram.y"
+#line 573 "gram.y"
{
- list_append(yyvsp[-2].member, yyvsp[0].member);
+ HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 87:
-#line 576 "gram.y"
+#line 583 "gram.y"
{
char *s;
if ((s = alias_add(yyvsp[-2].string, CMNDALIAS, yyvsp[0].member)) != NULL) {
}
break;
case 89:
-#line 586 "gram.y"
+#line 593 "gram.y"
{
- list_append(yyvsp[-2].member, yyvsp[0].member);
+ HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 92:
-#line 596 "gram.y"
+#line 603 "gram.y"
{
char *s;
if ((s = alias_add(yyvsp[-2].string, RUNASALIAS, yyvsp[0].member)) != NULL) {
}
break;
case 95:
-#line 609 "gram.y"
+#line 616 "gram.y"
{
char *s;
if ((s = alias_add(yyvsp[-2].string, USERALIAS, yyvsp[0].member)) != NULL) {
}
break;
case 97:
-#line 619 "gram.y"
+#line 626 "gram.y"
{
- list_append(yyvsp[-2].member, yyvsp[0].member);
+ HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 98:
-#line 625 "gram.y"
+#line 632 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 99:
-#line 629 "gram.y"
+#line 636 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 100:
-#line 635 "gram.y"
+#line 642 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
}
break;
case 101:
-#line 638 "gram.y"
+#line 645 "gram.y"
{
yyval.member = new_member(NULL, ALL);
}
break;
case 102:
-#line 641 "gram.y"
+#line 648 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NETGROUP);
}
break;
case 103:
-#line 644 "gram.y"
+#line 651 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, USERGROUP);
}
break;
case 104:
-#line 647 "gram.y"
+#line 654 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
}
break;
case 106:
-#line 653 "gram.y"
+#line 660 "gram.y"
{
- list_append(yyvsp[-2].member, yyvsp[0].member);
+ HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 107:
-#line 659 "gram.y"
+#line 666 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 108:
-#line 663 "gram.y"
+#line 670 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 109:
-#line 669 "gram.y"
+#line 676 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
}
break;
case 110:
-#line 672 "gram.y"
+#line 679 "gram.y"
{
yyval.member = new_member(NULL, ALL);
}
break;
case 111:
-#line 675 "gram.y"
+#line 682 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
}
break;
-#line 1777 "gram.c"
+#line 1798 "gram.c"
}
yyssp -= yym;
yystate = *yyssp;
int errorlineno = -1;
char *errorfile = NULL;
-struct defaults_list defaults;
-struct userspec_list userspecs;
+struct defaults_list defaults = TAILQ_HEAD_INITIALIZER(defaults);
+struct userspec_list userspecs = TAILQ_HEAD_INITIALIZER(userspecs);
/*
* Local protoypes
defaults_list : defaults_entry
| defaults_list ',' defaults_entry {
- list_append($1, $3);
+ HLTQ_CONCAT($1, $3, entries);
$$ = $1;
}
;
privileges : privilege
| privileges ':' privilege {
- list_append($1, $3);
+ HLTQ_CONCAT($1, $3, entries);
$$ = $1;
}
;
privilege : hostlist '=' cmndspeclist {
struct privilege *p = ecalloc(1, sizeof(*p));
- list2tq(&p->hostlist, $1);
- list2tq(&p->cmndlist, $3);
- p->prev = p;
- /* p->next = NULL; */
+ HLTQ_TO_TAILQ(&p->hostlist, $1, entries);
+ HLTQ_TO_TAILQ(&p->cmndlist, $3, entries);
+ HLTQ_INIT(p, entries);
$$ = p;
}
;
cmndspeclist : cmndspec
| cmndspeclist ',' cmndspec {
- list_append($1, $3);
+ struct cmndspec *prev;
+ prev = HLTQ_LAST($1, cmndspec, entries);
+ HLTQ_CONCAT($1, $3, entries);
#ifdef HAVE_SELINUX
/* propagate role and type */
if ($3->role == NULL)
- $3->role = $3->prev->role;
+ $3->role = prev->role;
if ($3->type == NULL)
- $3->type = $3->prev->type;
+ $3->type = prev->type;
#endif /* HAVE_SELINUX */
#ifdef HAVE_PRIV_SET
/* propagate privs & limitprivs */
if ($3->privs == NULL)
- $3->privs = $3->prev->privs;
+ $3->privs = prev->privs;
if ($3->limitprivs == NULL)
- $3->limitprivs = $3->prev->limitprivs;
+ $3->limitprivs = prev->limitprivs;
#endif /* HAVE_PRIV_SET */
/* propagate tags and runas list */
if ($3->tags.nopasswd == UNSPEC)
- $3->tags.nopasswd = $3->prev->tags.nopasswd;
+ $3->tags.nopasswd = prev->tags.nopasswd;
if ($3->tags.noexec == UNSPEC)
- $3->tags.noexec = $3->prev->tags.noexec;
+ $3->tags.noexec = prev->tags.noexec;
if ($3->tags.setenv == UNSPEC &&
- $3->prev->tags.setenv != IMPLIED)
- $3->tags.setenv = $3->prev->tags.setenv;
+ prev->tags.setenv != IMPLIED)
+ $3->tags.setenv = prev->tags.setenv;
if ($3->tags.log_input == UNSPEC)
- $3->tags.log_input = $3->prev->tags.log_input;
+ $3->tags.log_input = prev->tags.log_input;
if ($3->tags.log_output == UNSPEC)
- $3->tags.log_output = $3->prev->tags.log_output;
- if ((tq_empty(&$3->runasuserlist) &&
- tq_empty(&$3->runasgrouplist)) &&
- (!tq_empty(&$3->prev->runasuserlist) ||
- !tq_empty(&$3->prev->runasgrouplist))) {
- $3->runasuserlist = $3->prev->runasuserlist;
- $3->runasgrouplist = $3->prev->runasgrouplist;
+ $3->tags.log_output = prev->tags.log_output;
+ if (($3->runasuserlist == NULL &&
+ $3->runasgrouplist == NULL) &&
+ (prev->runasuserlist != NULL ||
+ prev->runasgrouplist != NULL)) {
+ $3->runasuserlist = prev->runasuserlist;
+ $3->runasgrouplist = prev->runasgrouplist;
}
$$ = $1;
}
cmndspec : runasspec selinux solarisprivs cmndtag digcmnd {
struct cmndspec *cs = ecalloc(1, sizeof(*cs));
if ($1 != NULL) {
- list2tq(&cs->runasuserlist, $1->runasusers);
- list2tq(&cs->runasgrouplist, $1->runasgroups);
+ if ($1->runasusers != NULL) {
+ cs->runasuserlist =
+ emalloc(sizeof(*cs->runasuserlist));
+ HLTQ_TO_TAILQ(cs->runasuserlist,
+ $1->runasusers, entries);
+ }
+ if ($1->runasgroups != NULL) {
+ cs->runasgrouplist =
+ emalloc(sizeof(*cs->runasgrouplist));
+ HLTQ_TO_TAILQ(cs->runasgrouplist,
+ $1->runasgroups, entries);
+ }
efree($1);
- } else {
- tq_init(&cs->runasuserlist);
- tq_init(&cs->runasgrouplist);
}
#ifdef HAVE_SELINUX
cs->role = $2.role;
#endif
cs->tags = $4;
cs->cmnd = $5;
- cs->prev = cs;
- cs->next = NULL;
+ HLTQ_INIT(cs, entries);
/* sudo "ALL" implies the SETENV tag */
if (cs->cmnd->type == ALL && !cs->cmnd->negated &&
cs->tags.setenv == UNSPEC)
hostlist : ophost
| hostlist ',' ophost {
- list_append($1, $3);
+ HLTQ_CONCAT($1, $3, entries);
$$ = $1;
}
;
cmndlist : digcmnd
| cmndlist ',' digcmnd {
- list_append($1, $3);
+ HLTQ_CONCAT($1, $3, entries);
$$ = $1;
}
;
userlist : opuser
| userlist ',' opuser {
- list_append($1, $3);
+ HLTQ_CONCAT($1, $3, entries);
$$ = $1;
}
;
grouplist : opgroup
| grouplist ',' opgroup {
- list_append($1, $3);
+ HLTQ_CONCAT($1, $3, entries);
$$ = $1;
}
;
d = ecalloc(1, sizeof(struct defaults));
d->var = var;
d->val = val;
- tq_init(&d->binding);
/* d->type = 0; */
d->op = op;
- d->prev = d;
- /* d->next = NULL; */
+ /* d->binding = NULL */
+ HLTQ_INIT(d, entries);
debug_return_ptr(d);
}
m = ecalloc(1, sizeof(struct member));
m->name = name;
m->type = type;
- m->prev = m;
- /* m->next = NULL; */
+ HLTQ_INIT(m, entries);
debug_return_ptr(m);
}
add_defaults(int type, struct member *bmem, struct defaults *defs)
{
struct defaults *d;
- struct member_list binding;
+ struct member_list *binding;
debug_decl(add_defaults, SUDO_DEBUG_PARSER)
/*
- * We can only call list2tq once on bmem as it will zero
- * out the prev pointer when it consumes bmem.
+ * We use a single binding for each entry in defs.
*/
- list2tq(&binding, bmem);
+ binding = emalloc(sizeof(*binding));
+ if (bmem != NULL)
+ HLTQ_TO_TAILQ(binding, bmem, entries);
+ else
+ TAILQ_INIT(binding);
/*
* Set type and binding (who it applies to) for new entries.
+ * Then add to the global defaults list.
*/
- for (d = defs; d != NULL; d = d->next) {
+ HLTQ_FOREACH(d, defs, entries) {
d->type = type;
d->binding = binding;
}
- tq_append(&defaults, defs);
+ TAILQ_CONCAT_HLTQ(&defaults, defs, entries);
debug_return;
}
/*
* Allocate a new struct userspec, populate it, and insert it at the
- * and of the userspecs list.
+ * end of the userspecs list.
*/
static void
add_userspec(struct member *members, struct privilege *privs)
debug_decl(add_userspec, SUDO_DEBUG_PARSER)
u = ecalloc(1, sizeof(*u));
- list2tq(&u->users, members);
- list2tq(&u->privileges, privs);
- u->prev = u;
- /* u->next = NULL; */
- tq_append(&userspecs, u);
+ HLTQ_TO_TAILQ(&u->users, members, entries);
+ HLTQ_TO_TAILQ(&u->privileges, privs, entries);
+ TAILQ_INSERT_TAIL(&userspecs, u, entries);
debug_return;
}
void
init_parser(const char *path, bool quiet)
{
+ struct member_list *binding;
+ struct member *m;
struct defaults *d;
- struct member *m, *binding;
struct userspec *us;
struct privilege *priv;
struct cmndspec *cs;
struct sudo_command *c;
debug_decl(init_parser, SUDO_DEBUG_PARSER)
- while ((us = tq_pop(&userspecs)) != NULL) {
- while ((m = tq_pop(&us->users)) != NULL) {
+ while ((us = TAILQ_FIRST(&userspecs)) != NULL) {
+ TAILQ_REMOVE(&userspecs, us, entries);
+ while ((m = TAILQ_FIRST(&us->users)) != NULL) {
+ TAILQ_REMOVE(&us->users, m, entries);
efree(m->name);
efree(m);
}
- while ((priv = tq_pop(&us->privileges)) != NULL) {
- struct member *runasuser = NULL, *runasgroup = NULL;
+ while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) {
+ struct member_list *runasuserlist = NULL, *runasgrouplist = NULL;
#ifdef HAVE_SELINUX
char *role = NULL, *type = NULL;
#endif /* HAVE_SELINUX */
char *privs = NULL, *limitprivs = NULL;
#endif /* HAVE_PRIV_SET */
- while ((m = tq_pop(&priv->hostlist)) != NULL) {
+ TAILQ_REMOVE(&us->privileges, priv, entries);
+ while ((m = TAILQ_FIRST(&priv->hostlist)) != NULL) {
+ TAILQ_REMOVE(&priv->hostlist, m, entries);
efree(m->name);
efree(m);
}
- while ((cs = tq_pop(&priv->cmndlist)) != NULL) {
+ while ((cs = TAILQ_FIRST(&priv->cmndlist)) != NULL) {
+ TAILQ_REMOVE(&priv->cmndlist, cs, entries);
#ifdef HAVE_SELINUX
/* Only free the first instance of a role/type. */
if (cs->role != role) {
efree(cs->limitprivs);
}
#endif /* HAVE_PRIV_SET */
- if (tq_last(&cs->runasuserlist) != runasuser) {
- runasuser = tq_last(&cs->runasuserlist);
- while ((m = tq_pop(&cs->runasuserlist)) != NULL) {
+ /* Only free the first instance of runas user/group lists. */
+ if (cs->runasuserlist && cs->runasuserlist != runasuserlist) {
+ runasuserlist = cs->runasuserlist;
+ while ((m = TAILQ_FIRST(runasuserlist)) != NULL) {
+ TAILQ_REMOVE(runasuserlist, m, entries);
efree(m->name);
efree(m);
}
+ efree(runasuserlist);
}
- if (tq_last(&cs->runasgrouplist) != runasgroup) {
- runasgroup = tq_last(&cs->runasgrouplist);
- while ((m = tq_pop(&cs->runasgrouplist)) != NULL) {
+ if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) {
+ runasgrouplist = cs->runasgrouplist;
+ while ((m = TAILQ_FIRST(runasgrouplist)) != NULL) {
+ TAILQ_REMOVE(runasgrouplist, m, entries);
efree(m->name);
efree(m);
}
+ efree(runasgrouplist);
}
if (cs->cmnd->type == COMMAND) {
c = (struct sudo_command *) cs->cmnd->name;
}
efree(us);
}
- tq_init(&userspecs);
+ TAILQ_INIT(&userspecs);
binding = NULL;
- while ((d = tq_pop(&defaults)) != NULL) {
- if (tq_last(&d->binding) != binding) {
- binding = tq_last(&d->binding);
- while ((m = tq_pop(&d->binding)) != NULL) {
+ while ((d = TAILQ_FIRST(&defaults)) != NULL) {
+ TAILQ_REMOVE(&defaults, d, entries);
+ if (d->binding != binding) {
+ binding = d->binding;
+ while ((m = TAILQ_FIRST(d->binding)) != NULL) {
+ TAILQ_REMOVE(d->binding, m, entries);
if (m->type == COMMAND) {
c = (struct sudo_command *) m->name;
efree(c->cmnd);
efree(m->name);
efree(m);
}
+ efree(d->binding);
}
efree(d->var);
efree(d->val);
efree(d);
}
- tq_init(&defaults);
+ TAILQ_INIT(&defaults);
init_aliases();
#include "sha2.h"
#include <gram.h>
-static struct member_list empty;
+static struct member_list empty = TAILQ_HEAD_INITIALIZER(empty);
static bool command_matches_dir(char *, size_t);
#ifndef SUDOERS_NAME_MATCH
int rval, matched = UNSPEC;
debug_decl(userlist_matches, SUDO_DEBUG_MATCH)
- tq_foreach_rev(list, m) {
+ TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
switch (m->type) {
case ALL:
matched = !m->negated;
if (runas_pw != NULL) {
/* If no runas user or runas group listed in sudoers, use default. */
- if (tq_empty(user_list) && tq_empty(group_list))
+ if (user_list == NULL && group_list == NULL)
debug_return_int(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw));
- tq_foreach_rev(user_list, m) {
- switch (m->type) {
- case ALL:
- user_matched = !m->negated;
- break;
- case NETGROUP:
- if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name))
- user_matched = !m->negated;
- break;
- case USERGROUP:
- if (usergr_matches(m->name, runas_pw->pw_name, runas_pw))
+ if (user_list != NULL) {
+ TAILQ_FOREACH_REVERSE(m, user_list, member_list, entries) {
+ switch (m->type) {
+ case ALL:
user_matched = !m->negated;
- break;
- case ALIAS:
- if ((a = alias_get(m->name, RUNASALIAS)) != NULL) {
- rval = runaslist_matches(&a->members, &empty,
- matching_user, NULL);
- if (rval != UNSPEC)
- user_matched = m->negated ? !rval : rval;
- alias_put(a);
break;
- }
- /* FALLTHROUGH */
- case WORD:
- if (userpw_matches(m->name, runas_pw->pw_name, runas_pw))
- user_matched = !m->negated;
- break;
- case MYSELF:
- if (!ISSET(sudo_user.flags, RUNAS_USER_SPECIFIED) ||
- strcmp(user_name, runas_pw->pw_name) == 0)
- user_matched = !m->negated;
+ case NETGROUP:
+ if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name))
+ user_matched = !m->negated;
+ break;
+ case USERGROUP:
+ if (usergr_matches(m->name, runas_pw->pw_name, runas_pw))
+ user_matched = !m->negated;
+ break;
+ case ALIAS:
+ if ((a = alias_get(m->name, RUNASALIAS)) != NULL) {
+ rval = runaslist_matches(&a->members, &empty,
+ matching_user, NULL);
+ if (rval != UNSPEC)
+ user_matched = m->negated ? !rval : rval;
+ alias_put(a);
+ break;
+ }
+ /* FALLTHROUGH */
+ case WORD:
+ if (userpw_matches(m->name, runas_pw->pw_name, runas_pw))
+ user_matched = !m->negated;
+ break;
+ case MYSELF:
+ if (!ISSET(sudo_user.flags, RUNAS_USER_SPECIFIED) ||
+ strcmp(user_name, runas_pw->pw_name) == 0)
+ user_matched = !m->negated;
+ break;
+ }
+ if (user_matched != UNSPEC) {
+ if (matching_user != NULL && m->type != ALIAS)
+ *matching_user = m;
break;
- }
- if (user_matched != UNSPEC) {
- if (matching_user != NULL && m->type != ALIAS)
- *matching_user = m;
- break;
+ }
}
}
}
if (runas_pw == NULL || strcmp(runas_pw->pw_name, user_name) == 0)
user_matched = ALLOW; /* only changing group */
}
- tq_foreach_rev(group_list, m) {
- switch (m->type) {
- case ALL:
- group_matched = !m->negated;
- break;
- case ALIAS:
- if ((a = alias_get(m->name, RUNASALIAS)) != NULL) {
- rval = runaslist_matches(&empty, &a->members,
- NULL, matching_group);
- if (rval != UNSPEC)
- group_matched = m->negated ? !rval : rval;
- alias_put(a);
- break;
- }
- /* FALLTHROUGH */
- case WORD:
- if (group_matches(m->name, runas_gr))
+ if (group_list != NULL) {
+ TAILQ_FOREACH_REVERSE(m, group_list, member_list, entries) {
+ switch (m->type) {
+ case ALL:
group_matched = !m->negated;
+ break;
+ case ALIAS:
+ if ((a = alias_get(m->name, RUNASALIAS)) != NULL) {
+ rval = runaslist_matches(&empty, &a->members,
+ NULL, matching_group);
+ if (rval != UNSPEC)
+ group_matched = m->negated ? !rval : rval;
+ alias_put(a);
+ break;
+ }
+ /* FALLTHROUGH */
+ case WORD:
+ if (group_matches(m->name, runas_gr))
+ group_matched = !m->negated;
+ break;
+ }
+ if (group_matched != UNSPEC) {
+ if (matching_group != NULL && m->type != ALIAS)
+ *matching_group = m;
break;
- }
- if (group_matched != UNSPEC) {
- if (matching_group != NULL && m->type != ALIAS)
- *matching_group = m;
- break;
+ }
}
}
if (group_matched == UNSPEC) {
int rval, matched = UNSPEC;
debug_decl(hostlist_matches, SUDO_DEBUG_MATCH)
- tq_foreach_rev(list, m) {
+ TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
switch (m->type) {
case ALL:
matched = !m->negated;
int matched = UNSPEC;
debug_decl(cmndlist_matches, SUDO_DEBUG_MATCH)
- tq_foreach_rev(list, m) {
+ TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
matched = cmnd_matches(m);
if (matched != UNSPEC)
break;
CLR(validated, FLAG_NO_USER);
CLR(validated, FLAG_NO_HOST);
match = DENY;
- tq_foreach_fwd(&userspecs, us) {
+ TAILQ_FOREACH(us, &userspecs, entries) {
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
continue;
- tq_foreach_fwd(&us->privileges, priv) {
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
if (hostlist_matches(&priv->hostlist) != ALLOW)
continue;
- tq_foreach_fwd(&priv->cmndlist, cs) {
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
/* Only check the command when listing another user. */
if (user_uid == 0 || list_pw == NULL ||
user_uid == list_pw->pw_uid ||
set_perms(PERM_RUNAS);
match = UNSPEC;
- tq_foreach_rev(&userspecs, us) {
+ TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) {
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
continue;
CLR(validated, FLAG_NO_USER);
- tq_foreach_rev(&us->privileges, priv) {
+ TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
host_match = hostlist_matches(&priv->hostlist);
if (host_match == ALLOW)
CLR(validated, FLAG_NO_HOST);
else
continue;
- tq_foreach_rev(&priv->cmndlist, cs) {
+ TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
matching_user = NULL;
- runas_match = runaslist_matches(&cs->runasuserlist,
- &cs->runasgrouplist, &matching_user, NULL);
+ runas_match = runaslist_matches(cs->runasuserlist,
+ cs->runasgrouplist, &matching_user, NULL);
if (runas_match == ALLOW) {
cmnd_match = cmnd_matches(cs->cmnd);
if (cmnd_match != UNSPEC) {
#define RUNAS_CHANGED(cs1, cs2) \
(cs1 == NULL || cs2 == NULL || \
- cs1->runasuserlist.first != cs2->runasuserlist.first || \
- cs1->runasuserlist.last != cs2->runasuserlist.last || \
- cs1->runasgrouplist.first != cs2->runasgrouplist.first || \
- cs1->runasgrouplist.last != cs2->runasgrouplist.last)
+ cs1->runasuserlist != cs2->runasuserlist || \
+ cs1->runasgrouplist != cs2->runasgrouplist)
static int
sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,
tags.nopasswd = UNSPEC;
tags.log_input = UNSPEC;
tags.log_output = UNSPEC;
- tq_foreach_fwd(&us->privileges, priv) {
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
if (hostlist_matches(&priv->hostlist) != ALLOW)
continue;
prev_cs = NULL;
- tq_foreach_fwd(&priv->cmndlist, cs) {
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
if (RUNAS_CHANGED(cs, prev_cs)) {
- if (cs != tq_first(&priv->cmndlist))
+ if (cs != TAILQ_FIRST(&priv->cmndlist))
lbuf_append(lbuf, "\n");
lbuf_append(lbuf, " (");
- if (!tq_empty(&cs->runasuserlist)) {
- tq_foreach_fwd(&cs->runasuserlist, m) {
- if (m != tq_first(&cs->runasuserlist))
+ if (cs->runasuserlist != NULL) {
+ TAILQ_FOREACH(m, cs->runasuserlist, entries) {
+ if (m != TAILQ_FIRST(cs->runasuserlist))
lbuf_append(lbuf, ", ");
print_member(lbuf, m, RUNASALIAS);
}
- } else if (tq_empty(&cs->runasgrouplist)) {
+ } else if (cs->runasgrouplist == NULL) {
lbuf_append(lbuf, "%s", def_runas_default);
} else {
lbuf_append(lbuf, "%s", pw->pw_name);
}
- if (!tq_empty(&cs->runasgrouplist)) {
+ if (cs->runasgrouplist != NULL) {
lbuf_append(lbuf, " : ");
- tq_foreach_fwd(&cs->runasgrouplist, m) {
- if (m != tq_first(&cs->runasgrouplist))
+ TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
+ if (m != TAILQ_FIRST(cs->runasgrouplist))
lbuf_append(lbuf, ", ");
print_member(lbuf, m, RUNASALIAS);
}
tags.nopasswd = UNSPEC;
tags.log_input = UNSPEC;
tags.log_output = UNSPEC;
- } else if (cs != tq_first(&priv->cmndlist)) {
+ } else if (cs != TAILQ_FIRST(&priv->cmndlist)) {
lbuf_append(lbuf, ", ");
}
sudo_file_append_cmnd(cs, &tags, lbuf);
int nfound = 0, olen;
debug_decl(sudo_file_display_priv_long, SUDO_DEBUG_NSS)
- tq_foreach_fwd(&us->privileges, priv) {
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
if (hostlist_matches(&priv->hostlist) != ALLOW)
continue;
prev_cs = NULL;
- tq_foreach_fwd(&priv->cmndlist, cs) {
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
if (new_long_entry(cs, prev_cs)) {
lbuf_append(lbuf, _("\nSudoers entry:\n"));
lbuf_append(lbuf, _(" RunAsUsers: "));
- if (!tq_empty(&cs->runasuserlist)) {
- tq_foreach_fwd(&cs->runasuserlist, m) {
- if (m != tq_first(&cs->runasuserlist))
+ if (cs->runasuserlist != NULL) {
+ TAILQ_FOREACH(m, cs->runasuserlist, entries) {
+ if (m != TAILQ_FIRST(cs->runasuserlist))
lbuf_append(lbuf, ", ");
print_member(lbuf, m, RUNASALIAS);
}
- } else if (tq_empty(&cs->runasgrouplist)) {
+ } else if (cs->runasgrouplist == NULL) {
lbuf_append(lbuf, "%s", def_runas_default);
} else {
lbuf_append(lbuf, "%s", pw->pw_name);
}
lbuf_append(lbuf, "\n");
- if (!tq_empty(&cs->runasgrouplist)) {
+ if (cs->runasgrouplist != NULL) {
lbuf_append(lbuf, _(" RunAsGroups: "));
- tq_foreach_fwd(&cs->runasgrouplist, m) {
- if (m != tq_first(&cs->runasgrouplist))
+ TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
+ if (m != TAILQ_FIRST(cs->runasgrouplist))
lbuf_append(lbuf, ", ");
print_member(lbuf, m, RUNASALIAS);
}
if (nss->handle == NULL)
goto done;
- tq_foreach_fwd(&userspecs, us) {
+ TAILQ_FOREACH(us, &userspecs, entries) {
if (userlist_matches(pw, &us->users) != ALLOW)
continue;
else
prefix = ", ";
- tq_foreach_fwd(&defaults, d) {
+ TAILQ_FOREACH(d, &defaults, entries) {
switch (d->type) {
case DEFAULTS_HOST:
- if (hostlist_matches(&d->binding) != ALLOW)
+ if (hostlist_matches(d->binding) != ALLOW)
continue;
break;
case DEFAULTS_USER:
- if (userlist_matches(pw, &d->binding) != ALLOW)
+ if (userlist_matches(pw, d->binding) != ALLOW)
continue;
break;
case DEFAULTS_RUNAS:
display_bound_defaults(int dtype, struct lbuf *lbuf)
{
struct defaults *d;
- struct member *m, *binding = NULL;
+ struct member_list *binding = NULL;
+ struct member *m;
char *dsep;
int atype, nfound = 0;
debug_decl(display_bound_defaults, SUDO_DEBUG_NSS)
default:
debug_return_int(-1);
}
- tq_foreach_fwd(&defaults, d) {
+ TAILQ_FOREACH(d, &defaults, entries) {
if (d->type != dtype)
continue;
nfound++;
- if (binding != tq_first(&d->binding)) {
- binding = tq_first(&d->binding);
+ if (binding != d->binding) {
+ binding = d->binding;
if (nfound != 1)
lbuf_append(lbuf, "\n");
lbuf_append(lbuf, " Defaults%s", dsep);
- for (m = binding; m != NULL; m = m->next) {
- if (m != binding)
+ TAILQ_FOREACH(m, binding, entries) {
+ if (m != TAILQ_FIRST(binding))
lbuf_append(lbuf, ",");
print_member(lbuf, m, atype);
lbuf_append(lbuf, " ");
goto done;
match = NULL;
- tq_foreach_rev(&userspecs, us) {
+ TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) {
if (userlist_matches(pw, &us->users) != ALLOW)
continue;
- tq_foreach_rev(&us->privileges, priv) {
+ TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
host_match = hostlist_matches(&priv->hostlist);
if (host_match != ALLOW)
continue;
- tq_foreach_rev(&priv->cmndlist, cs) {
- runas_match = runaslist_matches(&cs->runasuserlist,
- &cs->runasgrouplist, NULL, NULL);
+ TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
+ runas_match = runaslist_matches(cs->runasuserlist,
+ cs->runasgrouplist, NULL, NULL);
if (runas_match == ALLOW) {
cmnd_match = cmnd_matches(cs->cmnd);
if (cmnd_match != UNSPEC) {
break;
case ALIAS:
if ((a = alias_get(name, alias_type)) != NULL) {
- tq_foreach_fwd(&a->members, m) {
- if (m != tq_first(&a->members))
+ TAILQ_FOREACH(m, &a->members, entries) {
+ if (m != TAILQ_FIRST(&a->members))
lbuf_append(lbuf, "%s", separator);
_print_member(lbuf, m->name, m->type,
negated ? !m->negated : m->negated, separator,
#ifndef _SUDOERS_PARSE_H
#define _SUDOERS_PARSE_H
-#include "list.h" /* XXX */
-
#undef UNSPEC
#define UNSPEC -1
#undef DENY
* modelled after the yacc grammar.
*
* Other than the alias struct, which is stored in a red-black tree,
- * the data structure used is basically a doubly-linked tail queue without
- * a separate head struct--the first entry acts as the head where the prev
- * pointer does double duty as the tail pointer. This makes it possible
- * to trivally append sub-lists. In addition, the prev pointer is always
- * valid (even if it points to itself). Unlike a circle queue, the next
- * pointer of the last entry is NULL and does not point back to the head.
- *
- * Note that each list struct must contain a "prev" and "next" pointer as
- * the first two members of the struct (in that order).
+ * the data structure used is a doubly-linked tail queue. While sudoers
+ * is being parsed, a headless tail queue is used where the first entry
+ * acts as the head and the prev pointer does double duty as the tail pointer.
+ * This makes it possible to trivally append sub-lists. In addition, the prev
+ * pointer is always valid (even if it points to itself). Unlike a circle
+ * queue, the next pointer of the last entry is NULL and does not point back
+ * to the head. When the tail queue is finalized, it is converted to a
+ * normal BSD tail queue.
*/
/*
* Tail queue list head structure.
*/
-TQ_DECLARE(defaults)
-TQ_DECLARE(userspec)
-TQ_DECLARE(member)
-TQ_DECLARE(privilege)
-TQ_DECLARE(cmndspec)
+TAILQ_HEAD(defaults_list, defaults);
+TAILQ_HEAD(userspec_list, userspec);
+TAILQ_HEAD(member_list, member);
+TAILQ_HEAD(privilege_list, privilege);
+TAILQ_HEAD(cmndspec_list, cmndspec);
/*
* Structure describing a user specification and list thereof.
*/
struct userspec {
- struct userspec *prev, *next;
+ TAILQ_ENTRY(userspec) entries;
struct member_list users; /* list of users */
struct privilege_list privileges; /* list of privileges */
};
* Structure describing a privilege specification.
*/
struct privilege {
- struct privilege *prev, *next;
+ TAILQ_ENTRY(privilege) entries;
struct member_list hostlist; /* list of hosts */
struct cmndspec_list cmndlist; /* list of Cmnd_Specs */
};
* Structure describing a linked list of Cmnd_Specs.
*/
struct cmndspec {
- struct cmndspec *prev, *next;
- struct member_list runasuserlist; /* list of runas users */
- struct member_list runasgrouplist; /* list of runas groups */
+ TAILQ_ENTRY(cmndspec) entries;
+ struct member_list *runasuserlist; /* list of runas users */
+ struct member_list *runasgrouplist; /* list of runas groups */
struct member *cmnd; /* command to allow/deny */
char *digest; /* optional command digest */
struct cmndtag tags; /* tag specificaion */
* Generic structure to hold users, hosts, commands.
*/
struct member {
- struct member *prev, *next;
+ TAILQ_ENTRY(member) entries;
char *name; /* member name */
short type; /* type (see gram.h) */
short negated; /* negated via '!'? */
* Structure describing a Defaults entry and a list thereof.
*/
struct defaults {
- struct defaults *prev, *next;
+ TAILQ_ENTRY(defaults) entries;
char *var; /* variable name */
char *val; /* variable value */
- struct member_list binding; /* user/host/runas binding */
+ struct member_list *binding; /* user/host/runas binding */
int type; /* DEFAULTS{,_USER,_RUNAS,_HOST} */
int op; /* true, false, '+', '-' */
};
#define SUDO_ERROR_WRAP 0
#include "missing.h"
-#include "list.h"
+#include "queue.h"
#include "parse.h"
#include "toke.h"
#include "sudo_plugin.h"
/* This loop must match the one in sudo_file_lookup() */
printf("\nEntries for user %s:\n", user_name);
match = UNSPEC;
- tq_foreach_rev(&userspecs, us) {
+ TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) {
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
continue;
- tq_foreach_rev(&us->privileges, priv) {
+ TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
putchar('\n');
- print_privilege(priv); /* XXX */
+ print_privilege(priv);
putchar('\n');
host_match = hostlist_matches(&priv->hostlist);
if (host_match == ALLOW) {
puts("\thost matched");
- tq_foreach_rev(&priv->cmndlist, cs) {
- runas_match = runaslist_matches(&cs->runasuserlist,
- &cs->runasgrouplist, NULL, NULL);
+ TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
+ runas_match = runaslist_matches(cs->runasuserlist,
+ cs->runasgrouplist, NULL, NULL);
if (runas_match == ALLOW) {
puts("\trunas matched");
cmnd_match = cmnd_matches(cs->cmnd);
*/
exitcode = parse_error ? 1 : (match == ALLOW ? 0 : match + 3);
done:
+ sudo_endpwent();
+ sudo_endgrent();
sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode);
exit(exitcode);
}
struct member *m;
debug_decl(print_member, SUDO_DEBUG_UTIL)
- tq_foreach_fwd(&defaults, d) {
+ TAILQ_FOREACH(d, &defaults, entries) {
(void) fputs("Defaults", stdout);
switch (d->type) {
case DEFAULTS_HOST:
putchar('!');
break;
}
- tq_foreach_fwd(&d->binding, m) {
- if (m != tq_first(&d->binding))
+ TAILQ_FOREACH(m, d->binding, entries) {
+ if (m != TAILQ_FIRST(d->binding))
putchar(',');
print_member(m);
}
(void) printf("Runas_Alias\t%s = ", a->name);
break;
}
- tq_foreach_fwd(&a->members, m) {
- if (m != tq_first(&a->members))
+ TAILQ_FOREACH(m, &a->members, entries) {
+ if (m != TAILQ_FIRST(&a->members))
fputs(", ", stdout);
if (m->type == COMMAND) {
c = (struct sudo_command *) m->name;
{
struct cmndspec *cs;
struct member *m;
- struct privilege *p;
struct cmndtag tags;
debug_decl(print_privilege, SUDO_DEBUG_UTIL)
- for (p = priv; p != NULL; p = p->next) {
- if (p != priv)
- fputs(" : ", stdout);
- tq_foreach_fwd(&p->hostlist, m) {
- if (m != tq_first(&p->hostlist))
- fputs(", ", stdout);
- print_member(m);
- }
- fputs(" = ", stdout);
- tags.nopasswd = UNSPEC;
- tags.noexec = UNSPEC;
- tq_foreach_fwd(&p->cmndlist, cs) {
- if (cs != tq_first(&p->cmndlist))
- fputs(", ", stdout);
- if (!tq_empty(&cs->runasuserlist) || !tq_empty(&cs->runasgrouplist)) {
- fputs("(", stdout);
- if (!tq_empty(&cs->runasuserlist)) {
- tq_foreach_fwd(&cs->runasuserlist, m) {
- if (m != tq_first(&cs->runasuserlist))
- fputs(", ", stdout);
- print_member(m);
- }
- } else if (tq_empty(&cs->runasgrouplist)) {
- fputs(def_runas_default, stdout);
- } else {
- fputs(sudo_user.pw->pw_name, stdout);
- }
- if (!tq_empty(&cs->runasgrouplist)) {
- fputs(" : ", stdout);
- tq_foreach_fwd(&cs->runasgrouplist, m) {
- if (m != tq_first(&cs->runasgrouplist))
- fputs(", ", stdout);
- print_member(m);
- }
+ TAILQ_FOREACH(m, &priv->hostlist, entries) {
+ if (m != TAILQ_FIRST(&priv->hostlist))
+ fputs(", ", stdout);
+ print_member(m);
+ }
+ fputs(" = ", stdout);
+ tags.nopasswd = UNSPEC;
+ tags.noexec = UNSPEC;
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
+ if (cs != TAILQ_FIRST(&priv->cmndlist))
+ fputs(", ", stdout);
+ if (cs->runasuserlist != NULL || cs->runasgrouplist != NULL) {
+ fputs("(", stdout);
+ if (cs->runasuserlist != NULL) {
+ TAILQ_FOREACH(m, cs->runasuserlist, entries) {
+ if (m != TAILQ_FIRST(cs->runasuserlist))
+ fputs(", ", stdout);
+ print_member(m);
+ }
+ } else if (cs->runasgrouplist == NULL) {
+ fputs(def_runas_default, stdout);
+ } else {
+ fputs(sudo_user.pw->pw_name, stdout);
+ }
+ if (cs->runasgrouplist != NULL) {
+ fputs(" : ", stdout);
+ TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
+ if (m != TAILQ_FIRST(cs->runasgrouplist))
+ fputs(", ", stdout);
+ print_member(m);
}
- fputs(") ", stdout);
}
+ fputs(") ", stdout);
+ }
#ifdef HAVE_SELINUX
- if (cs->role)
- printf("ROLE=%s ", cs->role);
- if (cs->type)
- printf("TYPE=%s ", cs->type);
+ if (cs->role)
+ printf("ROLE=%s ", cs->role);
+ if (cs->type)
+ printf("TYPE=%s ", cs->type);
#endif /* HAVE_SELINUX */
#ifdef HAVE_PRIV_SET
- if (cs->privs)
- printf("PRIVS=%s ", cs->privs);
- if (cs->limitprivs)
- printf("LIMITPRIVS=%s ", cs->limitprivs);
+ if (cs->privs)
+ printf("PRIVS=%s ", cs->privs);
+ if (cs->limitprivs)
+ printf("LIMITPRIVS=%s ", cs->limitprivs);
#endif /* HAVE_PRIV_SET */
- if (cs->tags.nopasswd != UNSPEC && cs->tags.nopasswd != tags.nopasswd)
- printf("%sPASSWD: ", cs->tags.nopasswd ? "NO" : "");
- if (cs->tags.noexec != UNSPEC && cs->tags.noexec != tags.noexec)
- printf("%sEXEC: ", cs->tags.noexec ? "NO" : "");
- print_member(cs->cmnd);
- memcpy(&tags, &cs->tags, sizeof(tags));
- }
+ if (cs->tags.nopasswd != UNSPEC && cs->tags.nopasswd != tags.nopasswd)
+ printf("%sPASSWD: ", cs->tags.nopasswd ? "NO" : "");
+ if (cs->tags.noexec != UNSPEC && cs->tags.noexec != tags.noexec)
+ printf("%sEXEC: ", cs->tags.noexec ? "NO" : "");
+ print_member(cs->cmnd);
+ memcpy(&tags, &cs->tags, sizeof(tags));
}
debug_return;
}
{
struct member *m;
struct userspec *us;
+ struct privilege *priv;
debug_decl(print_userspecs, SUDO_DEBUG_UTIL)
- tq_foreach_fwd(&userspecs, us) {
- tq_foreach_fwd(&us->users, m) {
- if (m != tq_first(&us->users))
+ TAILQ_FOREACH(us, &userspecs, entries) {
+ TAILQ_FOREACH(m, &us->users, entries) {
+ if (m != TAILQ_FIRST(&us->users))
fputs(", ", stdout);
print_member(m);
}
putchar('\t');
- print_privilege(us->privileges.first); /* XXX */
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ if (priv != TAILQ_FIRST(&us->privileges))
+ fputs(" : ", stdout);
+ print_privilege(priv);
+ }
putchar('\n');
}
debug_return;
debug_decl(alias_remove_recursive, SUDO_DEBUG_ALIAS)
if ((a = alias_remove(name, type)) != NULL) {
- tq_foreach_fwd(&a->members, m) {
+ TAILQ_FOREACH(m, &a->members, entries) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, type))
rval = false;
if ((a = alias_get(name, type)) != NULL) {
/* check alias contents */
- tq_foreach_fwd(&a->members, m) {
+ TAILQ_FOREACH(m, &a->members, entries) {
if (m->type == ALIAS)
errors += check_alias(m->name, type, strict, quiet);
}
check_aliases(bool strict, bool quiet)
{
struct cmndspec *cs;
- struct member *m, *binding;
+ struct member *m;
struct privilege *priv;
struct userspec *us;
struct defaults *d;
alias_freelist = rbcreate(alias_compare);
/* Forward check. */
- tq_foreach_fwd(&userspecs, us) {
- tq_foreach_fwd(&us->users, m) {
+ TAILQ_FOREACH(us, &userspecs, entries) {
+ TAILQ_FOREACH(m, &us->users, entries) {
if (m->type == ALIAS) {
errors += check_alias(m->name, USERALIAS, strict, quiet);
}
}
- tq_foreach_fwd(&us->privileges, priv) {
- tq_foreach_fwd(&priv->hostlist, m) {
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ TAILQ_FOREACH(m, &priv->hostlist, entries) {
if (m->type == ALIAS) {
errors += check_alias(m->name, HOSTALIAS, strict, quiet);
}
}
- tq_foreach_fwd(&priv->cmndlist, cs) {
- tq_foreach_fwd(&cs->runasuserlist, m) {
- if (m->type == ALIAS) {
- errors += check_alias(m->name, RUNASALIAS, strict, quiet);
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
+ if (cs->runasuserlist != NULL) {
+ TAILQ_FOREACH(m, cs->runasuserlist, entries) {
+ if (m->type == ALIAS) {
+ errors += check_alias(m->name, RUNASALIAS, strict, quiet);
+ }
+ }
+ }
+ if (cs->runasgrouplist != NULL) {
+ TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
+ if (m->type == ALIAS) {
+ errors += check_alias(m->name, RUNASALIAS, strict, quiet);
+ }
}
}
if ((m = cs->cmnd)->type == ALIAS) {
}
/* Reverse check (destructive) */
- tq_foreach_fwd(&userspecs, us) {
- tq_foreach_fwd(&us->users, m) {
+ TAILQ_FOREACH(us, &userspecs, entries) {
+ TAILQ_FOREACH(m, &us->users, entries) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, USERALIAS))
errors++;
}
}
- tq_foreach_fwd(&us->privileges, priv) {
- tq_foreach_fwd(&priv->hostlist, m) {
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ TAILQ_FOREACH(m, &priv->hostlist, entries) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, HOSTALIAS))
errors++;
}
}
- tq_foreach_fwd(&priv->cmndlist, cs) {
- tq_foreach_fwd(&cs->runasuserlist, m) {
- if (m->type == ALIAS) {
- if (!alias_remove_recursive(m->name, RUNASALIAS))
- errors++;
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
+ if (cs->runasuserlist != NULL) {
+ TAILQ_FOREACH(m, cs->runasuserlist, entries) {
+ if (m->type == ALIAS) {
+ if (!alias_remove_recursive(m->name, RUNASALIAS))
+ errors++;
+ }
}
}
- tq_foreach_fwd(&cs->runasgrouplist, m) {
- if (m->type == ALIAS) {
- if (!alias_remove_recursive(m->name, RUNASALIAS))
- errors++;
+ if (cs->runasgrouplist != NULL) {
+ TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
+ if (m->type == ALIAS) {
+ if (!alias_remove_recursive(m->name, RUNASALIAS))
+ errors++;
+ }
}
}
if ((m = cs->cmnd)->type == ALIAS) {
}
}
}
- tq_foreach_fwd(&defaults, d) {
+ TAILQ_FOREACH(d, &defaults, entries) {
switch (d->type) {
case DEFAULTS_HOST:
atype = HOSTALIAS;
default:
continue; /* not an alias */
}
- tq_foreach_fwd(&d->binding, binding) {
- for (m = binding; m != NULL; m = m->next) {
- if (m->type == ALIAS) {
- if (!alias_remove_recursive(m->name, atype))
- errors++;
- }
+ TAILQ_FOREACH(m, d->binding, entries) {
+ if (m->type == ALIAS) {
+ if (!alias_remove_recursive(m->name, atype))
+ errors++;
}
}
}