version 1.1, 2012/02/21 16:23:02
|
version 1.1.1.4, 2014/06/15 16:12:54
|
Line 1
|
Line 1
|
/* |
/* |
* Copyright (c) 2004-2005, 2007-2011 | * Copyright (c) 2004-2005, 2007-2013 |
* Todd C. Miller <Todd.Miller@courtesan.com> |
* Todd C. Miller <Todd.Miller@courtesan.com> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
Line 20
|
Line 20
|
#include <config.h> |
#include <config.h> |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/param.h> |
|
#include <stdio.h> |
#include <stdio.h> |
#ifdef STDC_HEADERS |
#ifdef STDC_HEADERS |
# include <stdlib.h> |
# include <stdlib.h> |
Line 50
|
Line 49
|
* Globals |
* Globals |
*/ |
*/ |
struct rbtree *aliases; |
struct rbtree *aliases; |
unsigned int alias_seqno; |
|
|
|
/* |
/* |
* Comparison function for the red-black tree. |
* Comparison function for the red-black tree. |
Line 62 alias_compare(const void *v1, const void *v2)
|
Line 60 alias_compare(const void *v1, const void *v2)
|
const struct alias *a1 = (const struct alias *)v1; |
const struct alias *a1 = (const struct alias *)v1; |
const struct alias *a2 = (const struct alias *)v2; |
const struct alias *a2 = (const struct alias *)v2; |
int res; |
int res; |
|
debug_decl(alias_compare, SUDO_DEBUG_ALIAS) |
|
|
if (v1 == NULL) |
if (v1 == NULL) |
res = -1; |
res = -1; |
Line 69 alias_compare(const void *v1, const void *v2)
|
Line 68 alias_compare(const void *v1, const void *v2)
|
res = 1; |
res = 1; |
else if ((res = strcmp(a1->name, a2->name)) == 0) |
else if ((res = strcmp(a1->name, a2->name)) == 0) |
res = a1->type - a2->type; |
res = a1->type - a2->type; |
return res; | debug_return_int(res); |
} |
} |
|
|
/* |
/* |
* Search the tree for an alias with the specified name and type. |
* Search the tree for an alias with the specified name and type. |
* Returns a pointer to the alias structure or NULL if not found. |
* Returns a pointer to the alias structure or NULL if not found. |
|
* Caller is responsible for calling alias_put() on the returned |
|
* alias to mark it as unused. |
*/ |
*/ |
struct alias * |
struct alias * |
alias_find(char *name, int type) | alias_get(char *name, int type) |
{ |
{ |
struct alias key; |
struct alias key; |
struct rbnode *node; |
struct rbnode *node; |
struct alias *a = NULL; |
struct alias *a = NULL; |
|
debug_decl(alias_get, SUDO_DEBUG_ALIAS) |
|
|
key.name = name; |
key.name = name; |
key.type = type; |
key.type = type; |
if ((node = rbfind(aliases, &key)) != NULL) { |
if ((node = rbfind(aliases, &key)) != NULL) { |
/* |
/* |
* Compare the global sequence number with the one stored | * Check whether this alias is already in use. |
* in the alias. If they match then we've seen this alias | * If so, we've detected a loop. If not, set the flag, |
* before and found a loop. | * which the caller should clear with a call to alias_put(). |
*/ |
*/ |
a = node->data; |
a = node->data; |
if (a->seqno == alias_seqno) { | if (a->used) { |
errno = ELOOP; |
errno = ELOOP; |
return NULL; | debug_return_ptr(NULL); |
} |
} |
a->seqno = alias_seqno; | a->used = true; |
} else { |
} else { |
errno = ENOENT; |
errno = ENOENT; |
} |
} |
return a; | debug_return_ptr(a); |
} |
} |
|
|
/* |
/* |
|
* Clear the "used" flag in an alias once the caller is done with it. |
|
*/ |
|
void |
|
alias_put(struct alias *a) |
|
{ |
|
debug_decl(alias_put, SUDO_DEBUG_ALIAS) |
|
a->used = false; |
|
debug_return; |
|
} |
|
|
|
/* |
* Add an alias to the aliases redblack tree. |
* Add an alias to the aliases redblack tree. |
* Returns NULL on success and an error string on failure. |
* Returns NULL on success and an error string on failure. |
*/ |
*/ |
Line 112 alias_add(char *name, int type, struct member *members
|
Line 125 alias_add(char *name, int type, struct member *members
|
{ |
{ |
static char errbuf[512]; |
static char errbuf[512]; |
struct alias *a; |
struct alias *a; |
|
debug_decl(alias_add, SUDO_DEBUG_ALIAS) |
|
|
a = emalloc(sizeof(*a)); | a = ecalloc(1, sizeof(*a)); |
a->name = name; |
a->name = name; |
a->type = type; |
a->type = type; |
a->seqno = 0; | /* a->used = false; */ |
list2tq(&a->members, members); | HLTQ_TO_TAILQ(&a->members, members, entries); |
if (rbinsert(aliases, a)) { |
if (rbinsert(aliases, a)) { |
snprintf(errbuf, sizeof(errbuf), _("Alias `%s' already defined"), name); | snprintf(errbuf, sizeof(errbuf), N_("Alias `%s' already defined"), name); |
alias_free(a); |
alias_free(a); |
return errbuf; | debug_return_str(errbuf); |
} |
} |
return NULL; | debug_return_str(NULL); |
} |
} |
|
|
/* |
/* |
Line 132 alias_add(char *name, int type, struct member *members
|
Line 146 alias_add(char *name, int type, struct member *members
|
void |
void |
alias_apply(int (*func)(void *, void *), void *cookie) |
alias_apply(int (*func)(void *, void *), void *cookie) |
{ |
{ |
|
debug_decl(alias_apply, SUDO_DEBUG_ALIAS) |
|
|
rbapply(aliases, func, cookie, inorder); |
rbapply(aliases, func, cookie, inorder); |
|
|
|
debug_return; |
} |
} |
|
|
/* |
/* |
* Returns TRUE if there are no aliases, else FALSE. | * Returns true if there are no aliases, else false. |
*/ |
*/ |
int | bool |
no_aliases(void) |
no_aliases(void) |
{ |
{ |
return rbisempty(aliases); | debug_decl(no_aliases, SUDO_DEBUG_ALIAS) |
| debug_return_bool(rbisempty(aliases)); |
} |
} |
|
|
/* |
/* |
Line 154 alias_free(void *v)
|
Line 173 alias_free(void *v)
|
struct member *m; |
struct member *m; |
struct sudo_command *c; |
struct sudo_command *c; |
void *next; |
void *next; |
|
debug_decl(alias_free, SUDO_DEBUG_ALIAS) |
|
|
efree(a->name); |
efree(a->name); |
for (m = a->members.first; m != NULL; m = next) { | TAILQ_FOREACH_SAFE(m, &a->members, entries, next) { |
next = m->next; | |
if (m->type == COMMAND) { |
if (m->type == COMMAND) { |
c = (struct sudo_command *) m->name; |
c = (struct sudo_command *) m->name; |
efree(c->cmnd); |
efree(c->cmnd); |
Line 167 alias_free(void *v)
|
Line 186 alias_free(void *v)
|
efree(m); |
efree(m); |
} |
} |
efree(a); |
efree(a); |
|
|
|
debug_return; |
} |
} |
|
|
/* |
/* |
Line 177 alias_remove(char *name, int type)
|
Line 198 alias_remove(char *name, int type)
|
{ |
{ |
struct rbnode *node; |
struct rbnode *node; |
struct alias key; |
struct alias key; |
|
debug_decl(alias_remove, SUDO_DEBUG_ALIAS) |
|
|
key.name = name; |
key.name = name; |
key.type = type; |
key.type = type; |
Line 184 alias_remove(char *name, int type)
|
Line 206 alias_remove(char *name, int type)
|
errno = ENOENT; |
errno = ENOENT; |
return NULL; |
return NULL; |
} |
} |
return rbdelete(aliases, node); | debug_return_ptr(rbdelete(aliases, node)); |
} |
} |
|
|
void |
void |
init_aliases(void) |
init_aliases(void) |
{ |
{ |
|
debug_decl(init_aliases, SUDO_DEBUG_ALIAS) |
|
|
if (aliases != NULL) |
if (aliases != NULL) |
rbdestroy(aliases, alias_free); |
rbdestroy(aliases, alias_free); |
aliases = rbcreate(alias_compare); |
aliases = rbcreate(alias_compare); |
|
|
|
debug_return; |
} |
} |