version 1.1.1.3, 2013/07/22 10:46:13
|
version 1.1.1.4, 2014/06/15 16:12:55
|
Line 1
|
Line 1
|
/* |
/* |
* Copyright (c) 2012 Todd C. Miller <Todd.Miller@courtesan.com> | * Copyright (c) 2012-2013 Todd C. Miller <Todd.Miller@courtesan.com> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
Line 40
|
Line 40
|
#include "sudo_plugin.h" |
#include "sudo_plugin.h" |
#include "sudo_plugin_int.h" |
#include "sudo_plugin_int.h" |
#include "sudo_debug.h" |
#include "sudo_debug.h" |
|
#include "queue.h" |
|
|
/* Singly linked hook list. */ |
/* Singly linked hook list. */ |
struct sudo_hook_list { | struct sudo_hook_entry { |
struct sudo_hook_list *next; | SLIST_ENTRY(sudo_hook_entry) entries; |
union { |
union { |
sudo_hook_fn_t generic_fn; |
sudo_hook_fn_t generic_fn; |
sudo_hook_fn_setenv_t setenv_fn; |
sudo_hook_fn_setenv_t setenv_fn; |
Line 53 struct sudo_hook_list {
|
Line 54 struct sudo_hook_list {
|
} u; |
} u; |
void *closure; |
void *closure; |
}; |
}; |
|
SLIST_HEAD(sudo_hook_list, sudo_hook_entry); |
|
|
/* Each hook type gets own hook list. */ |
/* Each hook type gets own hook list. */ |
static struct sudo_hook_list *sudo_hook_setenv_list; | static struct sudo_hook_list sudo_hook_setenv_list = |
static struct sudo_hook_list *sudo_hook_unsetenv_list; | SLIST_HEAD_INITIALIZER(sudo_hook_setenv_list); |
static struct sudo_hook_list *sudo_hook_getenv_list; | static struct sudo_hook_list sudo_hook_unsetenv_list = |
static struct sudo_hook_list *sudo_hook_putenv_list; | SLIST_HEAD_INITIALIZER(sudo_hook_unsetenv_list); |
| static struct sudo_hook_list sudo_hook_getenv_list = |
| SLIST_HEAD_INITIALIZER(sudo_hook_getenv_list); |
| static struct sudo_hook_list sudo_hook_putenv_list = |
| SLIST_HEAD_INITIALIZER(sudo_hook_putenv_list); |
|
|
/* NOTE: must not anything that might call setenv() */ |
/* NOTE: must not anything that might call setenv() */ |
int |
int |
process_hooks_setenv(const char *name, const char *value, int overwrite) |
process_hooks_setenv(const char *name, const char *value, int overwrite) |
{ |
{ |
struct sudo_hook_list *hook; | struct sudo_hook_entry *hook; |
int rc = SUDO_HOOK_RET_NEXT; |
int rc = SUDO_HOOK_RET_NEXT; |
|
|
/* First process the hooks. */ |
/* First process the hooks. */ |
for (hook = sudo_hook_setenv_list; hook != NULL; hook = hook->next) { | SLIST_FOREACH(hook, &sudo_hook_setenv_list, entries) { |
rc = hook->u.setenv_fn(name, value, overwrite, hook->closure); |
rc = hook->u.setenv_fn(name, value, overwrite, hook->closure); |
switch (rc) { |
switch (rc) { |
case SUDO_HOOK_RET_NEXT: |
case SUDO_HOOK_RET_NEXT: |
Line 89 done:
|
Line 95 done:
|
int |
int |
process_hooks_putenv(char *string) |
process_hooks_putenv(char *string) |
{ |
{ |
struct sudo_hook_list *hook; | struct sudo_hook_entry *hook; |
int rc = SUDO_HOOK_RET_NEXT; |
int rc = SUDO_HOOK_RET_NEXT; |
|
|
/* First process the hooks. */ |
/* First process the hooks. */ |
for (hook = sudo_hook_putenv_list; hook != NULL; hook = hook->next) { | SLIST_FOREACH(hook, &sudo_hook_putenv_list, entries) { |
rc = hook->u.putenv_fn(string, hook->closure); |
rc = hook->u.putenv_fn(string, hook->closure); |
switch (rc) { |
switch (rc) { |
case SUDO_HOOK_RET_NEXT: |
case SUDO_HOOK_RET_NEXT: |
Line 114 done:
|
Line 120 done:
|
int |
int |
process_hooks_getenv(const char *name, char **value) |
process_hooks_getenv(const char *name, char **value) |
{ |
{ |
struct sudo_hook_list *hook; | struct sudo_hook_entry *hook; |
char *val = NULL; |
char *val = NULL; |
int rc = SUDO_HOOK_RET_NEXT; |
int rc = SUDO_HOOK_RET_NEXT; |
|
|
/* First process the hooks. */ |
/* First process the hooks. */ |
for (hook = sudo_hook_getenv_list; hook != NULL; hook = hook->next) { | SLIST_FOREACH(hook, &sudo_hook_getenv_list, entries) { |
rc = hook->u.getenv_fn(name, &val, hook->closure); |
rc = hook->u.getenv_fn(name, &val, hook->closure); |
switch (rc) { |
switch (rc) { |
case SUDO_HOOK_RET_NEXT: |
case SUDO_HOOK_RET_NEXT: |
Line 142 done:
|
Line 148 done:
|
int |
int |
process_hooks_unsetenv(const char *name) |
process_hooks_unsetenv(const char *name) |
{ |
{ |
struct sudo_hook_list *hook; | struct sudo_hook_entry *hook; |
int rc = SUDO_HOOK_RET_NEXT; |
int rc = SUDO_HOOK_RET_NEXT; |
|
|
/* First process the hooks. */ |
/* First process the hooks. */ |
for (hook = sudo_hook_unsetenv_list; hook != NULL; hook = hook->next) { | SLIST_FOREACH(hook, &sudo_hook_unsetenv_list, entries) { |
rc = hook->u.unsetenv_fn(name, hook->closure); |
rc = hook->u.unsetenv_fn(name, hook->closure); |
switch (rc) { |
switch (rc) { |
case SUDO_HOOK_RET_NEXT: |
case SUDO_HOOK_RET_NEXT: |
Line 165 done:
|
Line 171 done:
|
|
|
/* Hook registration internals. */ |
/* Hook registration internals. */ |
static void |
static void |
register_hook_internal(struct sudo_hook_list **head, | register_hook_internal(struct sudo_hook_list *head, |
int (*hook_fn)(), void *closure) |
int (*hook_fn)(), void *closure) |
{ |
{ |
struct sudo_hook_list *hook; | struct sudo_hook_entry *hook; |
debug_decl(register_hook_internal, SUDO_DEBUG_HOOKS) |
debug_decl(register_hook_internal, SUDO_DEBUG_HOOKS) |
|
|
hook = ecalloc(1, sizeof(*hook)); |
hook = ecalloc(1, sizeof(*hook)); |
hook->u.generic_fn = hook_fn; |
hook->u.generic_fn = hook_fn; |
hook->closure = closure; |
hook->closure = closure; |
hook->next = *head; | SLIST_INSERT_HEAD(head, hook, entries); |
*head = hook; | |
|
|
debug_return; |
debug_return; |
} |
} |
Line 220 register_hook(struct sudo_hook *hook)
|
Line 225 register_hook(struct sudo_hook *hook)
|
|
|
/* Hook deregistration internals. */ |
/* Hook deregistration internals. */ |
static void |
static void |
deregister_hook_internal(struct sudo_hook_list **head, | deregister_hook_internal(struct sudo_hook_list *head, |
int (*hook_fn)(), void *closure) |
int (*hook_fn)(), void *closure) |
{ |
{ |
struct sudo_hook_list *hook, *prev = NULL; | struct sudo_hook_entry *hook, *prev = NULL; |
debug_decl(deregister_hook_internal, SUDO_DEBUG_HOOKS) |
debug_decl(deregister_hook_internal, SUDO_DEBUG_HOOKS) |
|
|
for (hook = *head, prev = NULL; hook != NULL; prev = hook, hook = hook->next) { | SLIST_FOREACH(hook, head, entries) { |
if (hook->u.generic_fn == hook_fn && hook->closure == closure) { |
if (hook->u.generic_fn == hook_fn && hook->closure == closure) { |
/* Remove from list and free. */ |
/* Remove from list and free. */ |
if (prev == NULL) |
if (prev == NULL) |
*head = hook->next; | SLIST_REMOVE_HEAD(head, entries); |
else |
else |
prev->next = hook->next; | SLIST_REMOVE_AFTER(prev, entries); |
efree(hook); |
efree(hook); |
break; |
break; |
} |
} |
|
prev = hook; |
} |
} |
|
|
debug_return; |
debug_return; |