From: Todd C. Miller Date: Fri, 31 Aug 2007 23:13:26 +0000 (+0000) Subject: Move list manipulation macros to list.h and create C versions of X-Git-Tag: SUDO_1_7_0~387 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d72778832c00f07f61dfe0b81f473881be1c0325;p=sudo Move list manipulation macros to list.h and create C versions of the more complex ones in list.c. The names have been down-cased so they appear more like normal functions. --- diff --git a/Makefile.in b/Makefile.in index 760e0fba5..f651fd0ac 100644 --- a/Makefile.in +++ b/Makefile.in @@ -113,15 +113,15 @@ AUTH_SRCS = auth/afs.c auth/aix_auth.c auth/bsdauth.c auth/dce.c auth/fwtk.c \ auth/sudo_auth.c HDRS = compat.h def_data.h defaults.h error.h ins_2001.h ins_classic.h \ - ins_csops.h ins_goons.h insults.h interfaces.h lbuf.h logging.h parse.h \ - sudo.h gram.h version.h auth/sudo_auth.h emul/fnmatch.h emul/utime.h \ - redblack.h + ins_csops.h ins_goons.h insults.h interfaces.h lbuf.h list.h \ + logging.h parse.h sudo.h gram.h version.h auth/sudo_auth.h \ + emul/fnmatch.h emul/utime.h redblack.h AUTH_OBJS = sudo_auth.o @AUTH_OBJS@ # Note: gram.o must come first here -COMMON_OBJS = gram.o alias.o alloc.o defaults.o error.o match.o toke.o \ - redblack.o zero_bytes.o +COMMON_OBJS = gram.o alias.o alloc.o defaults.o error.o list.o match.o \ + toke.o redblack.o zero_bytes.o SUDO_OBJS = $(COMMON_OBJS) $(AUTH_OBJS) @SUDO_OBJS@ check.o env.o \ getspwuid.o gettime.o goodpath.o fileops.o find_path.o \ @@ -214,7 +214,7 @@ $(devdir)/toke.c: $(srcdir)/toke.l @DEV@ perl $(srcdir)/mkdefaults -o def_data $(srcdir)/def_data.in # Dependencies (not counting auth functions) -alias.o: $(srcdir)/alias.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/redblack.h +alias.o: $(srcdir)/alias.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/redblack.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alias.c alloc.o: $(srcdir)/alloc.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alloc.c @@ -248,17 +248,19 @@ glob.o: $(srcdir)/glob.c $(srcdir)/emul/glob.h $(srcdir)/compat.h config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/glob.c goodpath.o: $(srcdir)/goodpath.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/goodpath.c -gram.o: $(devdir)/gram.c $(SUDODEP) $(srcdir)/parse.h $(devdir)/gram.h +gram.o: $(devdir)/gram.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(devdir)/gram.c interfaces.o: $(srcdir)/interfaces.c $(SUDODEP) $(srcdir)/interfaces.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/interfaces.c -ldap.o: $(srcdir)/ldap.c $(SUDODEP) $(srcdir)/parse.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/ldap.c lbuf.o: $(srcdir)/lbuf.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/lbuf.c +ldap.o: $(srcdir)/ldap.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/ldap.c +list.o: $(srcdir)/list.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/list.c logging.o: $(srcdir)/logging.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/logging.c -match.o: $(srcdir)/match.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/interfaces.h $(devdir)/gram.h +match.o: $(srcdir)/match.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/interfaces.h $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/match.c memrchr.o: $(srcdir)/memrchr.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/memrchr.c @@ -266,7 +268,7 @@ mkstemp.o: $(srcdir)/mkstemp.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/mkstemp.c mon_solaris.o: $(srcdir)/mon_solaris.c $(SUDODEP) $(srcdir)/mon_solaris.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/mon_solaris.c -parse.o: $(srcdir)/parse.c $(SUDODEP) $(srcdir)/parse.h $(devdir)/gram.h +parse.o: $(srcdir)/parse.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/parse.c pwutil.o: $(srcdir)/pwutil.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/pwutil.c @@ -292,11 +294,11 @@ sudo_edit.o: $(srcdir)/sudo_edit.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_edit.c sudo_noexec.o: $(srcdir)/sudo_noexec.c $(srcdir)/compat.h config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_noexec.c -testsudoers.o: $(srcdir)/testsudoers.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/interfaces.h $(devdir)/gram.h +testsudoers.o: $(srcdir)/testsudoers.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/interfaces.h $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/testsudoers.c tgetpass.o: $(srcdir)/tgetpass.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/tgetpass.c -toke.o: $(devdir)/toke.c $(SUDODEP) $(srcdir)/parse.h $(devdir)/gram.h +toke.o: $(devdir)/toke.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(devdir)/toke.c tsgetgrpw.o: $(srcdir)/tsgetgrpw.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/tsgetgrpw.c diff --git a/alias.c b/alias.c index 847131a54..067cbd534 100644 --- a/alias.c +++ b/alias.c @@ -114,7 +114,7 @@ alias_add(name, type, members) a = emalloc(sizeof(*a)); a->name = name; a->type = type; - LIST2HEAD(a->members, members); + list2head(&a->members, members); if (rbinsert(aliases, a)) { efree(a); snprintf(errbuf, sizeof(errbuf), "Alias `%s' already defined", name); diff --git a/defaults.c b/defaults.c index 27d17340c..d55a51272 100644 --- a/defaults.c +++ b/defaults.c @@ -501,7 +501,7 @@ update_defaults(skip_cmnd) { struct defaults *def; - LH_FOREACH_FWD(&defaults, def) { + lh_foreach_fwd(&defaults, def) { if (skip_cmnd == (def->type == DEFAULTS_CMND)) continue; switch (def->type) { diff --git a/gram.y b/gram.y index 5d1cad807..5699303fb 100644 --- a/gram.y +++ b/gram.y @@ -211,7 +211,7 @@ entry : COMMENT { defaults_list : defaults_entry | defaults_list ',' defaults_entry { - LIST_APPEND($1, $3); + list_append($1, $3); $$ = $1; } ; @@ -235,7 +235,7 @@ defaults_entry : DEFVAR { privileges : privilege | privileges ':' privilege { - LIST_APPEND($1, $3); + list_append($1, $3); $$ = $1; } ; @@ -248,8 +248,8 @@ privilege : hostlist '=' cmndspeclist { /* propagate tags and runas lists */ tags.nopasswd = tags.noexec = tags.setenv = UNSPEC; for (cs = $3; cs != NULL; cs = cs->next) { - if (LH_EMPTY(&cs->runaslist) && - !LH_EMPTY(&cs->prev->runaslist)) { + if (lh_empty(&cs->runaslist) && + !lh_empty(&cs->prev->runaslist)) { memcpy(&cs->runaslist, &cs->prev->runaslist, sizeof(cs->runaslist)); } @@ -261,8 +261,8 @@ privilege : hostlist '=' cmndspeclist { cs->tags.setenv = tags.setenv; memcpy(&tags, &cs->tags, sizeof(tags)); } - LIST2HEAD(p->hostlist, $1); - LIST2HEAD(p->cmndlist, $3); + list2head(&p->hostlist, $1); + list2head(&p->cmndlist, $3); p->prev = p; p->next = NULL; $$ = p; @@ -298,14 +298,14 @@ host : ALIAS { cmndspeclist : cmndspec | cmndspeclist ',' cmndspec { - LIST_APPEND($1, $3); + list_append($1, $3); $$ = $1; } ; cmndspec : runasspec cmndtag opcmnd { struct cmndspec *cs = emalloc(sizeof(*cs)); - LIST2HEAD(cs->runaslist, $1); + list2head(&cs->runaslist, $1); cs->tags = $2; cs->cmnd = $3; cs->prev = cs; @@ -334,7 +334,7 @@ runasspec : /* empty */ { runaslist : oprunasuser | runaslist ',' oprunasuser { - LIST_APPEND($1, $3); + list_append($1, $3); $$ = $1; } ; @@ -418,7 +418,7 @@ hostalias : ALIAS '=' hostlist { hostlist : ophost | hostlist ',' ophost { - LIST_APPEND($1, $3); + list_append($1, $3); $$ = $1; } ; @@ -438,7 +438,7 @@ cmndalias : ALIAS '=' cmndlist { cmndlist : opcmnd | cmndlist ',' opcmnd { - LIST_APPEND($1, $3); + list_append($1, $3); $$ = $1; } ; @@ -471,7 +471,7 @@ useralias : ALIAS '=' userlist { userlist : opuser | userlist ',' opuser { - LIST_APPEND($1, $3); + list_append($1, $3); $$ = $1; } ; @@ -515,7 +515,7 @@ new_default(var, val, op) d = emalloc(sizeof(struct defaults)); d->var = var; d->val = val; - LH_INIT(&d->binding); + lh_init(&d->binding); d->type = 0; d->op = op; d->prev = d; @@ -558,9 +558,9 @@ add_defaults(type, binding, defs) */ for (d = defs; d != NULL; d = d->next) { d->type = type; - LIST2HEAD(d->binding, binding); + list2head(&d->binding, binding); } - HEAD_APPEND(defaults, defs); + lh_append(&defaults, defs); } /* @@ -575,11 +575,11 @@ add_userspec(members, privs) struct userspec *u; u = emalloc(sizeof(*u)); - LIST2HEAD(u->users, members); - LIST2HEAD(u->privileges, privs); + list2head(&u->users, members); + list2head(&u->privileges, privs); u->prev = u; u->next = NULL; - HEAD_APPEND(userspecs, u); + lh_append(&userspecs, u); } /* @@ -597,24 +597,18 @@ init_parser(path, quiet) struct privilege *priv; struct cmndspec *cs; - while ((us = LH_LAST(&userspecs)) != NULL) { - LH_POP(&userspecs); - while ((m = LH_LAST(&us->users)) != NULL) { - LH_POP(&us->users); + while ((us = lh_pop(&userspecs)) != NULL) { + while ((m = lh_pop(&us->users)) != NULL) { efree(m->name); efree(m); } - while ((priv = LH_LAST(&us->privileges)) != NULL) { - LH_POP(&us->privileges); - while ((m = LH_LAST(&priv->hostlist)) != NULL) { - LH_POP(&priv->hostlist); + while ((priv = lh_pop(&us->privileges)) != NULL) { + while ((m = lh_pop(&priv->hostlist)) != NULL) { efree(m->name); efree(m); } - while ((cs = LH_LAST(&priv->cmndlist)) != NULL) { - LH_POP(&priv->cmndlist); - while ((m = LH_LAST(&cs->runaslist)) != NULL) { - LH_POP(&cs->runaslist); + while ((cs = lh_pop(&priv->cmndlist)) != NULL) { + while ((m = lh_pop(&cs->runaslist)) != NULL) { efree(m->name); efree(m); } @@ -625,15 +619,12 @@ init_parser(path, quiet) efree(priv); } } - LH_INIT(&userspecs); + lh_init(&userspecs); lastbinding = NULL; - while ((d = LH_LAST(&defaults)) != NULL) { - LH_POP(&defaults); - if (LH_FIRST(&d->binding) != lastbinding) { - lastbinding = LH_FIRST(&d->binding); - while ((m = LH_LAST(&d->binding)) != NULL) { - LH_POP(&d->binding); + while ((d = lh_pop(&defaults)) != NULL) { + if (lh_pop(&d->binding) != lastbinding) { + while ((m = lh_pop(&d->binding)) != NULL) { efree(m->name); efree(m); } @@ -642,7 +633,7 @@ init_parser(path, quiet) efree(d->val); efree(d); } - LH_INIT(&defaults); + lh_init(&defaults); init_aliases(); diff --git a/list.c b/list.c new file mode 100644 index 000000000..cba973e64 --- /dev/null +++ b/list.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2007 Todd C. Miller + * + * 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 + +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ + +#include "sudo.h" +#include "list.h" + +#ifndef lint +__unused static const char rcsid[] = "$Sudo$"; +#endif /* lint */ + +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 * +lh_pop(vh) + VOID *vh; +{ + struct list_head_proto *h = (struct list_head_proto *)vh; + VOID *last = NULL; + + if (!lh_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 +list2head(vh, vl) + 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) { + 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(vl1, vl2) + 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 + * e from a semi-circle queue to normal doubly-linked list. + */ +void +lh_append(vh, vl) + 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; +} diff --git a/list.h b/list.h new file mode 100644 index 000000000..a852971e5 --- /dev/null +++ b/list.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2007 Todd C. Miller + * + * 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. + * + * $Sudo$ + */ + +#ifndef _SUDO_LIST_H +#define _SUDO_LIST_H + +/* + * Convenience macro for declaring a list head. + */ +#ifdef __STDC__ +#define LH_DECLARE(n) \ +struct n##_list { \ + struct n *first; \ + struct n *last; \ +}; +#else +#define LH_DECLARE(n) \ +struct n/**/_list { \ + struct n *first; \ + struct n *last; \ +}; +#endif + +/* + * Foreach loops: forward and reverse + */ +#undef lh_foreach_fwd +#define lh_foreach_fwd(h, v) \ + for ((v) = (h)->first; (v) != NULL; (v) = (v)->next) + +#undef lh_foreach_rev +#define lh_foreach_rev(h, v) \ + for ((v) = (h)->last; (v) != NULL; (v) = (v)->prev) + +/* + * Init a list head. + */ +#undef lh_init +#define lh_init(h) do { \ + (h)->first = NULL; \ + (h)->last = NULL; \ +} while (0) + +/* + * Simple macros to avoid exposing first/last and prev/next. + */ +#undef lh_empty +#define lh_empty(h) ((h)->first == NULL) + +#undef lh_first +#define lh_first(h) ((h)->first) + +#undef lh_last +#define lh_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 *lh_pop __P((VOID *)); +void lh_append __P((VOID *, VOID *)); +void list_append __P((VOID *, VOID *)); +void list2head __P((VOID *, VOID *)); + +#endif /* _SUDO_LIST_H */ diff --git a/match.c b/match.c index 324e527ea..3b84e8472 100644 --- a/match.c +++ b/match.c @@ -111,7 +111,7 @@ userlist_matches(pw, list) struct alias *a; int rval, matched = UNSPEC; - LH_FOREACH_REV(list, m) { + lh_foreach_rev(list, m) { switch (m->type) { case ALL: matched = !m->negated; @@ -159,7 +159,7 @@ runaslist_matches(list) if (list == NULL) return(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw)); - LH_FOREACH_REV(list, m) { + lh_foreach_rev(list, m) { switch (m->type) { case ALL: matched = !m->negated; @@ -203,7 +203,7 @@ hostlist_matches(list) struct alias *a; int rval, matched = UNSPEC; - LH_FOREACH_REV(list, m) { + lh_foreach_rev(list, m) { switch (m->type) { case ALL: matched = !m->negated; @@ -278,7 +278,7 @@ cmndlist_matches(list) struct member *m; int rval, matched = UNSPEC; - LH_FOREACH_REV(list, m) { + lh_foreach_rev(list, m) { rval = cmnd_matches(m); if (rval != UNSPEC) { matched = m->negated ? !rval : rval; diff --git a/parse.c b/parse.c index 36c14a696..cd0f0a1ca 100644 --- a/parse.c +++ b/parse.c @@ -110,13 +110,13 @@ sudoers_lookup(pwflag) CLR(validated, FLAG_NO_USER); CLR(validated, FLAG_NO_HOST); match = DENY; - LH_FOREACH_REV(&userspecs, us) { + lh_foreach_rev(&userspecs, us) { if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) continue; - LH_FOREACH_REV(&us->privileges, priv) { + lh_foreach_rev(&us->privileges, priv) { if (hostlist_matches(&priv->hostlist) != ALLOW) continue; - LH_FOREACH_REV(&priv->cmndlist, cs) { + lh_foreach_rev(&priv->cmndlist, cs) { /* Only check the command when listing another user. */ if (user_uid == 0 || list_pw == NULL || user_uid == list_pw->pw_uid || @@ -147,19 +147,19 @@ sudoers_lookup(pwflag) set_perms(PERM_RUNAS); match = UNSPEC; - LH_FOREACH_REV(&userspecs, us) { + lh_foreach_rev(&userspecs, us) { if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) continue; CLR(validated, FLAG_NO_USER); - LH_FOREACH_REV(&us->privileges, priv) { + lh_foreach_rev(&us->privileges, priv) { host_match = hostlist_matches(&priv->hostlist); if (host_match == ALLOW) CLR(validated, FLAG_NO_HOST); else continue; runas = NULL; - LH_FOREACH_REV(&priv->cmndlist, cs) { - if (!LH_EMPTY(&cs->runaslist)) + lh_foreach_rev(&priv->cmndlist, cs) { + if (!lh_empty(&cs->runaslist)) runas = &cs->runaslist; runas_match = runaslist_matches(runas); if (runas_match == ALLOW) { @@ -228,24 +228,24 @@ display_privs(v, pw) printf("User %s may run the following commands on this host:\n", pw->pw_name); - LH_FOREACH_FWD(&userspecs, us) { + lh_foreach_fwd(&userspecs, us) { /* XXX - why only check the first privilege here? */ if (userlist_matches(pw, &us->users) != ALLOW || hostlist_matches(&us->privileges.first->hostlist) != ALLOW) continue; - LH_FOREACH_FWD(&us->privileges, priv) { + lh_foreach_fwd(&us->privileges, priv) { tags.noexec = def_noexec; tags.setenv = def_setenv; tags.nopasswd = !def_authenticate; lbuf_append(&lbuf, " ", NULL); - LH_FOREACH_FWD(&priv->cmndlist, cs) { - if (cs != LH_FIRST(&priv->cmndlist)) + lh_foreach_fwd(&priv->cmndlist, cs) { + if (cs != lh_first(&priv->cmndlist)) lbuf_append(&lbuf, ", ", NULL); lbuf_append(&lbuf, "(", NULL); - if (!LH_EMPTY(&cs->runaslist)) { - LH_FOREACH_FWD(&cs->runaslist, m) { - if (m != LH_FIRST(&cs->runaslist)) + if (!lh_empty(&cs->runaslist)) { + lh_foreach_fwd(&cs->runaslist, m) { + if (m != lh_first(&cs->runaslist)) lbuf_append(&lbuf, ", ", NULL); print_member(&lbuf, m->name, m->type, m->negated, RUNASALIAS); @@ -298,7 +298,7 @@ display_defaults(pw) lbuf_init(&lbuf, NULL, 4, 0); - LH_FOREACH_FWD(&defaults, d) { + lh_foreach_fwd(&defaults, d) { switch (d->type) { case DEFAULTS_HOST: if (hostlist_matches(&d->binding) != ALLOW) @@ -385,12 +385,12 @@ display_bound_defaults(dtype) } lbuf_init(&lbuf, NULL, 4, 0); printf("Per-%s Defaults entries:\n", dname); - LH_FOREACH_FWD(&defaults, d) { + lh_foreach_fwd(&defaults, d) { if (d->type != dtype) continue; - if (binding != LH_FIRST(&d->binding)) { - binding = LH_FIRST(&d->binding); + if (binding != lh_first(&d->binding)) { + binding = lh_first(&d->binding); lbuf_append(&lbuf, " Defaults", dsep, NULL); for (m = binding; m != NULL; m = m->next) { if (m != binding) @@ -434,17 +434,17 @@ display_cmnd(v, pw) #endif if (rval != 0 && !def_ignore_local_sudoers) { match = NULL; - LH_FOREACH_REV(&userspecs, us) { + lh_foreach_rev(&userspecs, us) { if (userlist_matches(pw, &us->users) != ALLOW) continue; - LH_FOREACH_REV(&us->privileges, priv) { + lh_foreach_rev(&us->privileges, priv) { host_match = hostlist_matches(&priv->hostlist); if (host_match != ALLOW) continue; runas = NULL; - LH_FOREACH_REV(&priv->cmndlist, cs) { - if (!LH_EMPTY(&cs->runaslist) != NULL) + lh_foreach_rev(&priv->cmndlist, cs) { + if (!lh_empty(&cs->runaslist) != NULL) runas = &cs->runaslist; runas_match = runaslist_matches(runas); if (runas_match == ALLOW) { @@ -497,8 +497,8 @@ print_member(lbuf, name, type, negated, alias_type) break; case ALIAS: if ((a = find_alias(name, alias_type)) != NULL) { - LH_FOREACH_FWD(&a->members, m) { - if (m != LH_FIRST(&a->members)) + lh_foreach_fwd(&a->members, m) { + if (m != lh_first(&a->members)) lbuf_append(lbuf, ", ", NULL); print_member(lbuf, m->name, m->type, negated ? !m->negated : m->negated, alias_type); diff --git a/parse.h b/parse.h index a6e6b464f..2d614dd81 100644 --- a/parse.h +++ b/parse.h @@ -20,6 +20,8 @@ #ifndef _SUDO_PARSE_H #define _SUDO_PARSE_H +#include "list.h" + #undef ALLOW #define ALLOW 1 #undef DENY @@ -58,72 +60,56 @@ struct cmndtag { * 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). */ /* * Tail queue list head structure. */ -struct defaults_list { - struct defaults *first; - struct defaults *last; -}; - -struct userspec_list { - struct userspec *first; - struct userspec *last; -}; - -struct member_list { - struct member *first; - struct member *last; -}; - -struct privilege_list { - struct privilege *first; - struct privilege *last; -}; - -struct cmndspec_list { - struct cmndspec *first; - struct cmndspec *last; -}; +LH_DECLARE(defaults) +LH_DECLARE(userspec) +LH_DECLARE(member) +LH_DECLARE(privilege) +LH_DECLARE(cmndspec) /* * Structure describing a user specification and list thereof. */ struct userspec { + struct userspec *prev, *next; struct member_list users; /* list of users */ struct privilege_list privileges; /* list of privileges */ - struct userspec *prev, *next; }; /* * Structure describing a privilege specification. */ struct privilege { + struct privilege *prev, *next; struct member_list hostlist; /* list of hosts */ struct cmndspec_list cmndlist; /* list of Cmnd_Specs */ - struct privilege *prev, *next; }; /* * Structure describing a linked list of Cmnd_Specs. */ struct cmndspec { + struct cmndspec *prev, *next; struct member_list runaslist; /* list of runas users */ struct member *cmnd; /* command to allow/deny */ struct cmndtag tags; /* tag specificaion */ - struct cmndspec *prev, *next; }; /* * Generic structure to hold users, hosts, commands. */ struct member { + struct member *prev, *next; char *name; /* member name */ short type; /* type (see gram.h) */ short negated; /* negated via '!'? */ - struct member *prev, *next; }; /* @@ -140,102 +126,14 @@ struct alias { * Structure describing a Defaults entry and a list thereof. */ struct defaults { + struct defaults *prev, *next; char *var; /* variable name */ char *val; /* variable value */ struct member_list binding; /* user/host/runas binding */ int type; /* DEFAULTS{,_USER,_RUNAS,_HOST} */ int op; /* TRUE, FALSE, '+', '-' */ - struct defaults *prev, *next; }; -/* - * Append one queue (or single entry) to another using the - * circular properties of the prev pointer to simplify the logic. - */ -#undef LIST_APPEND -#define LIST_APPEND(h, e) do { \ - void *_tail = (e)->prev; \ - (h)->prev->next = (e); \ - (e)->prev = (h)->prev; \ - (h)->prev = _tail; \ -} while (0) - -/* - * Append the list of entries to the head node and convert - * e from a semi-circle queue to normal doubly-linked list. - */ -#undef HEAD_APPEND -#define HEAD_APPEND(h, e) do { \ - void *_tail = (e)->prev; \ - if ((h).first == NULL) \ - (h).first = (e); \ - else \ - (h).last->next = (e); \ - (e)->prev = (h).last; \ - (h).last = _tail; \ -} while (0) - -/* - * Convert from a semi-circle queue to normal doubly-linked list - * with a head node. - */ -#undef LIST2HEAD -#define LIST2HEAD(h, e) do { \ - if ((e) != NULL) { \ - (h).first = (e); \ - (h).last = (e)->prev; \ - (e)->prev = NULL; \ - } else { \ - (h).first = NULL; \ - (h).last = NULL; \ - } \ -} while (0) - -#undef LH_FOREACH_FWD -#define LH_FOREACH_FWD(h, v) \ - for ((v) = (h)->first; (v) != NULL; (v) = (v)->next) - -#undef LH_FOREACH_REV -#define LH_FOREACH_REV(h, v) \ - for ((v) = (h)->last; (v) != NULL; (v) = (v)->prev) - -/* - * Pop the last element off the end of h. - * XXX - really should return the popped element. - */ -#undef LH_POP -#define LH_POP(h) do { \ - if (!LH_EMPTY(h)) { \ - if ((h)->first == (h)->last) \ - (h)->first = (h)->last = NULL; \ - else { \ - (h)->last = (h)->last->prev; \ - (h)->last->next = NULL; \ - } \ - } \ -} while (0) - -#undef LH_INIT -#define LH_INIT(h) do { \ - (h)->first = NULL; \ - (h)->last = NULL; \ -} while (0) - -#undef LH_EMPTY -#define LH_EMPTY(h) ((h)->first == NULL) - -#undef LH_FIRST -#define LH_FIRST(h) ((h)->first) - -#undef LH_LAST -#define LH_LAST(h) ((h)->last) - -#undef LIST_NEXT -#define LIST_NEXT(e) ((e)->next) - -#undef LIST_PREV -#define LIST_PREV(e) ((e)->prev) - /* * Parsed sudoers info. */ diff --git a/testsudoers.c b/testsudoers.c index 9cb5b63e4..e34da20bc 100644 --- a/testsudoers.c +++ b/testsudoers.c @@ -269,18 +269,18 @@ main(argc, argv) /* This loop must match the one in sudoers_lookup() */ printf("\nEntries for user %s:\n", user_name); matched = UNSPEC; - LH_FOREACH_REV(&userspecs, us) { + lh_foreach_rev(&userspecs, us) { if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) continue; - LH_FOREACH_REV(&us->privileges, priv) { + lh_foreach_rev(&us->privileges, priv) { putchar('\n'); print_privilege(priv); /* XXX */ putchar('\n'); if (hostlist_matches(&priv->hostlist) == ALLOW) { puts("\thost matched"); runas = NULL; - LH_FOREACH_REV(&priv->cmndlist, cs) { - if (!LH_EMPTY(&cs->runaslist)) + lh_foreach_rev(&priv->cmndlist, cs) { + if (!lh_empty(&cs->runaslist)) runas = &cs->runaslist; if (runaslist_matches(runas) == ALLOW) { puts("\trunas matched"); @@ -389,7 +389,7 @@ print_defaults() struct defaults *d; struct member *m; - LH_FOREACH_FWD(&defaults, d) { + lh_foreach_fwd(&defaults, d) { (void) fputs("Defaults", stdout); switch (d->type) { case DEFAULTS_HOST: @@ -405,8 +405,8 @@ print_defaults() putchar('!'); break; } - LH_FOREACH_FWD(&d->binding, m) { - if (m != LH_FIRST(&d->binding)) + lh_foreach_fwd(&d->binding, m) { + if (m != lh_first(&d->binding)) putchar(','); print_member(m); } @@ -440,8 +440,8 @@ print_alias(v1, v2) (void) printf("Runas_Alias\t%s = ", a->name); break; } - LH_FOREACH_FWD(&a->members, m) { - if (m != LH_FIRST(&a->members)) + lh_foreach_fwd(&a->members, m) { + if (m != lh_first(&a->members)) fputs(", ", stdout); if (m->type == COMMAND) { c = (struct sudo_command *) m->name; @@ -466,20 +466,20 @@ print_privilege(priv) for (p = priv; p != NULL; p = p->next) { if (p != priv) fputs(" : ", stdout); - LH_FOREACH_FWD(&p->hostlist, m) { - if (m != LH_FIRST(&p->hostlist)) + lh_foreach_fwd(&p->hostlist, m) { + if (m != lh_first(&p->hostlist)) fputs(", ", stdout); print_member(m); } fputs(" = ", stdout); tags.nopasswd = tags.noexec = UNSPEC; - LH_FOREACH_FWD(&p->cmndlist, cs) { - if (cs != LH_FIRST(&p->cmndlist)) + lh_foreach_fwd(&p->cmndlist, cs) { + if (cs != lh_first(&p->cmndlist)) fputs(", ", stdout); - if (!LH_EMPTY(&cs->runaslist)) { + if (!lh_empty(&cs->runaslist)) { fputs("(", stdout); - LH_FOREACH_FWD(&cs->runaslist, m) { - if (m != LH_FIRST(&cs->runaslist)) + lh_foreach_fwd(&cs->runaslist, m) { + if (m != lh_first(&cs->runaslist)) fputs(", ", stdout); print_member(m); } @@ -501,9 +501,9 @@ print_userspecs() struct member *m; struct userspec *us; - LH_FOREACH_FWD(&userspecs, us) { - LH_FOREACH_FWD(&us->users, m) { - if (m != LH_FIRST(&us->users)) + lh_foreach_fwd(&userspecs, us) { + lh_foreach_fwd(&us->users, m) { + if (m != lh_first(&us->users)) fputs(", ", stdout); print_member(m); } diff --git a/visudo.c b/visudo.c index 3e2bb4f75..81e1f5f12 100644 --- a/visudo.c +++ b/visudo.c @@ -212,8 +212,8 @@ main(argc, argv) setup_signals(); /* Edit the sudoers file(s) */ - LH_FOREACH_FWD(&sudoerslist, sp) { - if (sp != LH_FIRST(&sudoerslist)) { + lh_foreach_fwd(&sudoerslist, sp) { + if (sp != lh_first(&sudoerslist)) { printf("press return to edit %s: ", sp->path); while ((ch = getchar()) != EOF && ch != '\n') continue; @@ -225,7 +225,7 @@ main(argc, argv) reparse_sudoers(editor, args, strict, quiet); /* Install the sudoers temp files. */ - LH_FOREACH_FWD(&sudoerslist, sp) { + lh_foreach_fwd(&sudoerslist, sp) { if (!sp->modified) (void) unlink(sp->tpath); else @@ -400,8 +400,8 @@ reparse_sudoers(editor, args, strict, quiet) * Parse the edited sudoers files and do sanity checking */ do { - sp = LH_FIRST(&sudoerslist); - last = LH_LAST(&sudoerslist); + sp = lh_first(&sudoerslist); + last = lh_last(&sudoerslist); fp = fopen(sp->tpath, "r+"); if (fp == NULL) errorx(1, "can't re-open temporary file (%s), %s unchanged.", @@ -437,7 +437,7 @@ reparse_sudoers(editor, args, strict, quiet) } if (parse_error) { /* Edit file with the parse error */ - LH_FOREACH_FWD(&sudoerslist, sp) { + lh_foreach_fwd(&sudoerslist, sp) { if (errorfile == NULL || strcmp(sp->path, errorfile) == 0) { edit_sudoers(sp, editor, args, errorlineno); break; @@ -708,7 +708,7 @@ open_sudoers(path, keepopen) FILE *fp; /* Check for existing entry */ - LH_FOREACH_FWD(&sudoerslist, entry) { + lh_foreach_fwd(&sudoerslist, entry) { if (strcmp(path, entry->path) == 0) break; } @@ -886,8 +886,8 @@ check_aliases(strict) int error = 0; /* Forward check. */ - LH_FOREACH_FWD(&userspecs, us) { - LH_FOREACH_FWD(&us->users, m) { + lh_foreach_fwd(&userspecs, us) { + lh_foreach_fwd(&us->users, m) { if (m->type == USERALIAS) { if (find_alias(m->name, m->type) == NULL) { fprintf(stderr, @@ -897,8 +897,8 @@ check_aliases(strict) } } } - LH_FOREACH_FWD(&us->privileges, priv) { - LH_FOREACH_FWD(&priv->hostlist, m) { + lh_foreach_fwd(&us->privileges, priv) { + lh_foreach_fwd(&priv->hostlist, m) { if (m->type == HOSTALIAS) { if (find_alias(m->name, m->type) == NULL) { fprintf(stderr, @@ -908,8 +908,8 @@ check_aliases(strict) } } } - LH_FOREACH_FWD(&priv->cmndlist, cs) { - LH_FOREACH_FWD(&cs->runaslist, m) { + lh_foreach_fwd(&priv->cmndlist, cs) { + lh_foreach_fwd(&cs->runaslist, m) { if (m->type == RUNASALIAS) { if (find_alias(m->name, m->type) == NULL) { fprintf(stderr, @@ -932,18 +932,18 @@ check_aliases(strict) } /* Reverse check (destructive) */ - LH_FOREACH_FWD(&userspecs, us) { - LH_FOREACH_FWD(&us->users, m) { + lh_foreach_fwd(&userspecs, us) { + lh_foreach_fwd(&us->users, m) { if (m->type == USERALIAS) (void) alias_remove(m->name, m->type); } - LH_FOREACH_FWD(&us->privileges, priv) { - LH_FOREACH_FWD(&priv->hostlist, m) { + lh_foreach_fwd(&us->privileges, priv) { + lh_foreach_fwd(&priv->hostlist, m) { if (m->type == HOSTALIAS) (void) alias_remove(m->name, m->type); } - LH_FOREACH_FWD(&priv->cmndlist, cs) { - LH_FOREACH_FWD(&cs->runaslist, m) { + lh_foreach_fwd(&priv->cmndlist, cs) { + lh_foreach_fwd(&cs->runaslist, m) { if (m->type == RUNASALIAS) (void) alias_remove(m->name, m->type); } @@ -983,7 +983,7 @@ cleanup(gotsignal) { struct sudoersfile *sp; - LH_FOREACH_FWD(&sudoerslist, sp) { + lh_foreach_fwd(&sudoerslist, sp) { if (sp->tpath != NULL) (void) unlink(sp->tpath); }