version 1.1.1.2, 2012/05/29 12:26:49
|
version 1.1.1.3, 2013/07/22 10:46:12
|
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 76 alias_compare(const void *v1, const void *v2)
|
Line 74 alias_compare(const void *v1, const void *v2)
|
/* |
/* |
* 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_find, SUDO_DEBUG_ALIAS) | 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; |
debug_return_ptr(NULL); |
debug_return_ptr(NULL); |
} |
} |
a->seqno = alias_seqno; | a->used = true; |
} else { |
} else { |
errno = ENOENT; |
errno = ENOENT; |
} |
} |
Line 106 alias_find(char *name, int type)
|
Line 106 alias_find(char *name, int type)
|
} |
} |
|
|
/* |
/* |
|
* 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 119 alias_add(char *name, int type, struct member *members
|
Line 130 alias_add(char *name, int type, struct member *members
|
a = ecalloc(1, 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); |
list2tq(&a->members, members); |
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); |
debug_return_str(errbuf); |
debug_return_str(errbuf); |
} |
} |