version 1.1.1.3, 2012/10/09 09:29:52
|
version 1.1.1.6, 2014/06/15 16:12:54
|
Line 1
|
Line 1
|
/* |
/* |
* Copyright (c) 1999-2005, 2007-2011 | * Copyright (c) 1999-2005, 2007-2014 |
* 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 22
|
Line 22
|
#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 149 dump_defaults(void)
|
Line 148 dump_defaults(void)
|
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); |
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); |
} |
} |
break; |
break; |
case T_UINT: |
|
case T_INT: |
case T_INT: |
sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.ival); |
sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.ival); |
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); |
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); |
break; |
break; |
|
case T_UINT: |
|
sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.uival); |
|
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); |
|
break; |
case T_FLOAT: |
case T_FLOAT: |
sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.fval); |
sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.fval); |
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); |
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); |
Line 163 dump_defaults(void)
|
Line 165 dump_defaults(void)
|
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); |
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); |
break; |
break; |
case T_LIST: |
case T_LIST: |
if (cur->sd_un.list) { | if (!SLIST_EMPTY(&cur->sd_un.list)) { |
sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc); |
sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc); |
for (item = cur->sd_un.list; item; item = item->next) { | SLIST_FOREACH(item, &cur->sd_un.list, entries) { |
sudo_printf(SUDO_CONV_INFO_MSG, |
sudo_printf(SUDO_CONV_INFO_MSG, |
"\t%s\n", item->value); |
"\t%s\n", item->value); |
} |
} |
Line 173 dump_defaults(void)
|
Line 175 dump_defaults(void)
|
break; |
break; |
case T_TUPLE: |
case T_TUPLE: |
for (def = cur->values; def->sval; def++) { |
for (def = cur->values; def->sval; def++) { |
if (cur->sd_un.ival == def->ival) { | if (cur->sd_un.tuple == def->nval) { |
sudo_printf(SUDO_CONV_INFO_MSG, desc, def->sval); |
sudo_printf(SUDO_CONV_INFO_MSG, desc, def->sval); |
break; |
break; |
} |
} |
Line 205 set_default(char *var, char *val, int op)
|
Line 207 set_default(char *var, char *val, int op)
|
break; |
break; |
} |
} |
if (!cur->name) { |
if (!cur->name) { |
warningx(_("unknown defaults entry `%s'"), var); | warningx(U_("unknown defaults entry `%s'"), var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
|
|
Line 213 set_default(char *var, char *val, int op)
|
Line 215 set_default(char *var, char *val, int op)
|
case T_LOGFAC: |
case T_LOGFAC: |
if (!store_syslogfac(val, cur, op)) { |
if (!store_syslogfac(val, cur, op)) { |
if (val) |
if (val) |
warningx(_("value `%s' is invalid for option `%s'"), | warningx(U_("value `%s' is invalid for option `%s'"), |
val, var); |
val, var); |
else |
else |
warningx(_("no value specified for `%s'"), var); | warningx(U_("no value specified for `%s'"), var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
break; |
break; |
case T_LOGPRI: |
case T_LOGPRI: |
if (!store_syslogpri(val, cur, op)) { |
if (!store_syslogpri(val, cur, op)) { |
if (val) |
if (val) |
warningx(_("value `%s' is invalid for option `%s'"), | warningx(U_("value `%s' is invalid for option `%s'"), |
val, var); |
val, var); |
else |
else |
warningx(_("no value specified for `%s'"), var); | warningx(U_("no value specified for `%s'"), var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
break; |
break; |
Line 234 set_default(char *var, char *val, int op)
|
Line 236 set_default(char *var, char *val, int op)
|
if (!val) { |
if (!val) { |
/* Check for bogus boolean usage or lack of a value. */ |
/* Check for bogus boolean usage or lack of a value. */ |
if (!ISSET(cur->type, T_BOOL) || op != false) { |
if (!ISSET(cur->type, T_BOOL) || op != false) { |
warningx(_("no value specified for `%s'"), var); | warningx(U_("no value specified for `%s'"), var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
} |
} |
if (ISSET(cur->type, T_PATH) && val && *val != '/') { |
if (ISSET(cur->type, T_PATH) && val && *val != '/') { |
warningx(_("values for `%s' must start with a '/'"), var); | warningx(U_("values for `%s' must start with a '/'"), var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
if (!store_str(val, cur, op)) { |
if (!store_str(val, cur, op)) { |
warningx(_("value `%s' is invalid for option `%s'"), val, var); | warningx(U_("value `%s' is invalid for option `%s'"), val, var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
break; |
break; |
Line 251 set_default(char *var, char *val, int op)
|
Line 253 set_default(char *var, char *val, int op)
|
if (!val) { |
if (!val) { |
/* Check for bogus boolean usage or lack of a value. */ |
/* Check for bogus boolean usage or lack of a value. */ |
if (!ISSET(cur->type, T_BOOL) || op != false) { |
if (!ISSET(cur->type, T_BOOL) || op != false) { |
warningx(_("no value specified for `%s'"), var); | warningx(U_("no value specified for `%s'"), var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
} |
} |
if (!store_int(val, cur, op)) { |
if (!store_int(val, cur, op)) { |
warningx(_("value `%s' is invalid for option `%s'"), val, var); | warningx(U_("value `%s' is invalid for option `%s'"), val, var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
break; |
break; |
Line 264 set_default(char *var, char *val, int op)
|
Line 266 set_default(char *var, char *val, int op)
|
if (!val) { |
if (!val) { |
/* Check for bogus boolean usage or lack of a value. */ |
/* Check for bogus boolean usage or lack of a value. */ |
if (!ISSET(cur->type, T_BOOL) || op != false) { |
if (!ISSET(cur->type, T_BOOL) || op != false) { |
warningx(_("no value specified for `%s'"), var); | warningx(U_("no value specified for `%s'"), var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
} |
} |
if (!store_uint(val, cur, op)) { |
if (!store_uint(val, cur, op)) { |
warningx(_("value `%s' is invalid for option `%s'"), val, var); | warningx(U_("value `%s' is invalid for option `%s'"), val, var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
break; |
break; |
Line 277 set_default(char *var, char *val, int op)
|
Line 279 set_default(char *var, char *val, int op)
|
if (!val) { |
if (!val) { |
/* Check for bogus boolean usage or lack of a value. */ |
/* Check for bogus boolean usage or lack of a value. */ |
if (!ISSET(cur->type, T_BOOL) || op != false) { |
if (!ISSET(cur->type, T_BOOL) || op != false) { |
warningx(_("no value specified for `%s'"), var); | warningx(U_("no value specified for `%s'"), var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
} |
} |
if (!store_float(val, cur, op)) { |
if (!store_float(val, cur, op)) { |
warningx(_("value `%s' is invalid for option `%s'"), val, var); | warningx(U_("value `%s' is invalid for option `%s'"), val, var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
break; |
break; |
Line 290 set_default(char *var, char *val, int op)
|
Line 292 set_default(char *var, char *val, int op)
|
if (!val) { |
if (!val) { |
/* Check for bogus boolean usage or lack of a value. */ |
/* Check for bogus boolean usage or lack of a value. */ |
if (!ISSET(cur->type, T_BOOL) || op != false) { |
if (!ISSET(cur->type, T_BOOL) || op != false) { |
warningx(_("no value specified for `%s'"), var); | warningx(U_("no value specified for `%s'"), var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
} |
} |
if (!store_mode(val, cur, op)) { |
if (!store_mode(val, cur, op)) { |
warningx(_("value `%s' is invalid for option `%s'"), val, var); | warningx(U_("value `%s' is invalid for option `%s'"), val, var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
break; |
break; |
case T_FLAG: |
case T_FLAG: |
if (val) { |
if (val) { |
warningx(_("option `%s' does not take a value"), var); | warningx(U_("option `%s' does not take a value"), var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
cur->sd_un.flag = op; |
cur->sd_un.flag = op; |
Line 310 set_default(char *var, char *val, int op)
|
Line 312 set_default(char *var, char *val, int op)
|
if (!val) { |
if (!val) { |
/* Check for bogus boolean usage or lack of a value. */ |
/* Check for bogus boolean usage or lack of a value. */ |
if (!ISSET(cur->type, T_BOOL) || op != false) { |
if (!ISSET(cur->type, T_BOOL) || op != false) { |
warningx(_("no value specified for `%s'"), var); | warningx(U_("no value specified for `%s'"), var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
} |
} |
if (!store_list(val, cur, op)) { |
if (!store_list(val, cur, op)) { |
warningx(_("value `%s' is invalid for option `%s'"), val, var); | warningx(U_("value `%s' is invalid for option `%s'"), val, var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
break; |
break; |
case T_TUPLE: |
case T_TUPLE: |
if (!val && !ISSET(cur->type, T_BOOL)) { |
if (!val && !ISSET(cur->type, T_BOOL)) { |
warningx(_("no value specified for `%s'"), var); | warningx(U_("no value specified for `%s'"), var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
if (!store_tuple(val, cur, op)) { |
if (!store_tuple(val, cur, op)) { |
warningx(_("value `%s' is invalid for option `%s'"), val, var); | warningx(U_("value `%s' is invalid for option `%s'"), val, var); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
break; |
break; |
Line 357 init_defaults(void)
|
Line 359 init_defaults(void)
|
list_op(NULL, 0, def, freeall); |
list_op(NULL, 0, def, freeall); |
break; |
break; |
} |
} |
zero_bytes(&def->sd_un, sizeof(def->sd_un)); | memset(&def->sd_un, 0, sizeof(def->sd_un)); |
} |
} |
} |
} |
|
|
Line 422 init_defaults(void)
|
Line 424 init_defaults(void)
|
def_env_reset = ENV_RESET; |
def_env_reset = ENV_RESET; |
def_set_logname = true; |
def_set_logname = true; |
def_closefrom = STDERR_FILENO + 1; |
def_closefrom = STDERR_FILENO + 1; |
|
def_pam_service = estrdup("sudo"); |
|
#ifdef HAVE_PAM_LOGIN |
|
def_pam_login_service = estrdup("sudo-i"); |
|
#else |
|
def_pam_login_service = estrdup("sudo"); |
|
#endif |
|
#ifdef NO_PAM_SESSION |
|
def_pam_session = false; |
|
#else |
|
def_pam_session = true; |
|
#endif |
|
#ifdef HAVE_INNETGR |
|
def_use_netgroups = true; |
|
#endif |
|
|
/* Syslog options need special care since they both strings and ints */ |
/* Syslog options need special care since they both strings and ints */ |
#if (LOGGING & SLOG_SYSLOG) |
#if (LOGGING & SLOG_SYSLOG) |
Line 452 init_defaults(void)
|
Line 468 init_defaults(void)
|
|
|
/* Now do the strings */ |
/* Now do the strings */ |
def_mailto = estrdup(MAILTO); |
def_mailto = estrdup(MAILTO); |
def_mailsub = estrdup(_(MAILSUBJECT)); | def_mailsub = estrdup(N_(MAILSUBJECT)); |
def_badpass_message = estrdup(_(INCORRECT_PASSWORD)); |
def_badpass_message = estrdup(_(INCORRECT_PASSWORD)); |
|
def_lecture_status_dir = estrdup(_PATH_SUDO_LECTURE_DIR); |
def_timestampdir = estrdup(_PATH_SUDO_TIMEDIR); |
def_timestampdir = estrdup(_PATH_SUDO_TIMEDIR); |
def_passprompt = estrdup(_(PASSPROMPT)); |
def_passprompt = estrdup(_(PASSPROMPT)); |
def_runas_default = estrdup(RUNAS_DEFAULT); |
def_runas_default = estrdup(RUNAS_DEFAULT); |
Line 472 init_defaults(void)
|
Line 489 init_defaults(void)
|
#endif |
#endif |
def_editor = estrdup(EDITOR); |
def_editor = estrdup(EDITOR); |
def_set_utmp = true; |
def_set_utmp = true; |
|
def_pam_setcred = true; |
|
|
/* Finally do the lists (currently just environment tables). */ |
/* Finally do the lists (currently just environment tables). */ |
init_envtables(); |
init_envtables(); |
Line 492 update_defaults(int what)
|
Line 510 update_defaults(int what)
|
bool rc = true; |
bool rc = true; |
debug_decl(update_defaults, SUDO_DEBUG_DEFAULTS) |
debug_decl(update_defaults, SUDO_DEBUG_DEFAULTS) |
|
|
tq_foreach_fwd(&defaults, def) { | TAILQ_FOREACH(def, &defaults, entries) { |
switch (def->type) { |
switch (def->type) { |
case DEFAULTS: |
case DEFAULTS: |
if (ISSET(what, SETDEF_GENERIC) && |
if (ISSET(what, SETDEF_GENERIC) && |
Line 500 update_defaults(int what)
|
Line 518 update_defaults(int what)
|
rc = false; |
rc = false; |
break; |
break; |
case DEFAULTS_USER: |
case DEFAULTS_USER: |
|
#if 1 |
|
if (ISSET(what, SETDEF_USER)) { |
|
int m; |
|
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) && |
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)) |
!set_default(def->var, def->val, def->op)) |
rc = false; |
rc = false; |
|
#endif |
break; |
break; |
case DEFAULTS_RUNAS: |
case DEFAULTS_RUNAS: |
if (ISSET(what, SETDEF_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)) |
!set_default(def->var, def->val, def->op)) |
rc = false; |
rc = false; |
break; |
break; |
case DEFAULTS_HOST: |
case DEFAULTS_HOST: |
if (ISSET(what, SETDEF_HOST) && |
if (ISSET(what, SETDEF_HOST) && |
hostlist_matches(&def->binding) == ALLOW && | hostlist_matches(def->binding) == ALLOW && |
!set_default(def->var, def->val, def->op)) |
!set_default(def->var, def->val, def->op)) |
rc = false; |
rc = false; |
break; |
break; |
case DEFAULTS_CMND: |
case DEFAULTS_CMND: |
if (ISSET(what, SETDEF_CMND) && |
if (ISSET(what, SETDEF_CMND) && |
cmndlist_matches(&def->binding) == ALLOW && | cmndlist_matches(def->binding) == ALLOW && |
!set_default(def->var, def->val, def->op)) |
!set_default(def->var, def->val, def->op)) |
rc = false; |
rc = false; |
break; |
break; |
Line 540 check_defaults(int what, bool quiet)
|
Line 569 check_defaults(int what, bool quiet)
|
bool rc = true; |
bool rc = true; |
debug_decl(check_defaults, SUDO_DEBUG_DEFAULTS) |
debug_decl(check_defaults, SUDO_DEBUG_DEFAULTS) |
|
|
tq_foreach_fwd(&defaults, def) { | TAILQ_FOREACH(def, &defaults, entries) { |
switch (def->type) { |
switch (def->type) { |
case DEFAULTS: |
case DEFAULTS: |
if (!ISSET(what, SETDEF_GENERIC)) |
if (!ISSET(what, SETDEF_GENERIC)) |
Line 569 check_defaults(int what, bool quiet)
|
Line 598 check_defaults(int what, bool quiet)
|
} |
} |
if (cur->name == NULL) { |
if (cur->name == NULL) { |
if (!quiet) |
if (!quiet) |
warningx(_("unknown defaults entry `%s'"), def->var); | warningx(U_("unknown defaults entry `%s'"), def->var); |
rc = false; |
rc = false; |
} |
} |
} |
} |
Line 579 check_defaults(int what, bool quiet)
|
Line 608 check_defaults(int what, bool quiet)
|
static bool |
static bool |
store_int(char *val, struct sudo_defs_types *def, int op) |
store_int(char *val, struct sudo_defs_types *def, int op) |
{ |
{ |
char *endp; | const char *errstr; |
long l; | int i; |
debug_decl(store_int, SUDO_DEBUG_DEFAULTS) |
debug_decl(store_int, SUDO_DEBUG_DEFAULTS) |
|
|
if (op == false) { |
if (op == false) { |
def->sd_un.ival = 0; |
def->sd_un.ival = 0; |
} else { |
} else { |
l = strtol(val, &endp, 10); | i = strtonum(val, INT_MIN, INT_MAX, &errstr); |
if (*endp != '\0') | if (errstr != NULL) { |
| sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, |
| "%s: %s", val, errstr); |
debug_return_bool(false); |
debug_return_bool(false); |
/* XXX - should check against INT_MAX */ | } |
def->sd_un.ival = (int)l; | def->sd_un.ival = i; |
} |
} |
if (def->callback) |
if (def->callback) |
debug_return_bool(def->callback(val)); |
debug_return_bool(def->callback(val)); |
Line 600 store_int(char *val, struct sudo_defs_types *def, int
|
Line 631 store_int(char *val, struct sudo_defs_types *def, int
|
static bool |
static bool |
store_uint(char *val, struct sudo_defs_types *def, int op) |
store_uint(char *val, struct sudo_defs_types *def, int op) |
{ |
{ |
char *endp; | const char *errstr; |
long l; | unsigned int u; |
debug_decl(store_uint, SUDO_DEBUG_DEFAULTS) |
debug_decl(store_uint, SUDO_DEBUG_DEFAULTS) |
|
|
if (op == false) { |
if (op == false) { |
def->sd_un.ival = 0; | def->sd_un.uival = 0; |
} else { |
} else { |
l = strtol(val, &endp, 10); | u = strtonum(val, 0, UINT_MAX, &errstr); |
if (*endp != '\0' || l < 0) | if (errstr != NULL) { |
| sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, |
| "%s: %s", val, errstr); |
debug_return_bool(false); |
debug_return_bool(false); |
/* XXX - should check against INT_MAX */ | } |
def->sd_un.ival = (unsigned int)l; | def->sd_un.uival = u; |
} |
} |
if (def->callback) |
if (def->callback) |
debug_return_bool(def->callback(val)); |
debug_return_bool(def->callback(val)); |
Line 646 store_tuple(char *val, struct sudo_defs_types *def, in
|
Line 679 store_tuple(char *val, struct sudo_defs_types *def, in
|
debug_decl(store_tuple, SUDO_DEBUG_DEFAULTS) |
debug_decl(store_tuple, SUDO_DEBUG_DEFAULTS) |
|
|
/* |
/* |
* Since enums are really just ints we store the value as an ival. | * Look up tuple value by name to find enum def_tuple value. |
* In the future, there may be multiple enums for different tuple | * For negation to work the first element of enum def_tuple |
* types we want to avoid and special knowledge of the tuple type. | * must be equivalent to boolean false. |
* This does assume that the first entry in the tuple enum will | |
* be the equivalent to a boolean "false". | |
*/ |
*/ |
if (!val) { |
if (!val) { |
def->sd_un.ival = (op == false) ? 0 : 1; |
def->sd_un.ival = (op == false) ? 0 : 1; |
} else { |
} else { |
for (v = def->values; v->sval != NULL; v++) { |
for (v = def->values; v->sval != NULL; v++) { |
if (strcmp(v->sval, val) == 0) { |
if (strcmp(v->sval, val) == 0) { |
def->sd_un.ival = v->ival; | def->sd_un.tuple = v->nval; |
break; |
break; |
} |
} |
} |
} |
Line 747 logfac2str(int n)
|
Line 778 logfac2str(int n)
|
|
|
for (fac = facilities; fac->name && fac->num != n; fac++) |
for (fac = facilities; fac->name && fac->num != n; fac++) |
; |
; |
debug_return_str(fac->name); | debug_return_const_str(fac->name); |
#else |
#else |
return "default"; |
return "default"; |
#endif /* LOG_NFACILITIES */ |
#endif /* LOG_NFACILITIES */ |
Line 779 logpri2str(int n)
|
Line 810 logpri2str(int n)
|
|
|
for (pri = priorities; pri->name && pri->num != n; pri++) |
for (pri = priorities; pri->name && pri->num != n; pri++) |
; |
; |
debug_return_str(pri->name); | debug_return_const_str(pri->name); |
} |
} |
|
|
static bool |
static bool |
store_mode(char *val, struct sudo_defs_types *def, int op) |
store_mode(char *val, struct sudo_defs_types *def, int op) |
{ |
{ |
char *endp; | mode_t mode; |
long l; | const char *errstr; |
debug_decl(store_mode, SUDO_DEBUG_DEFAULTS) |
debug_decl(store_mode, SUDO_DEBUG_DEFAULTS) |
|
|
if (op == false) { |
if (op == false) { |
def->sd_un.mode = (mode_t)0777; | def->sd_un.mode = 0777; |
} else { |
} else { |
l = strtol(val, &endp, 8); | mode = atomode(val, &errstr); |
if (*endp != '\0' || l < 0 || l > 0777) | if (errstr != NULL) { |
| sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, |
| "%s is %s", val, errstr); |
debug_return_bool(false); |
debug_return_bool(false); |
def->sd_un.mode = (mode_t)l; | } |
| def->sd_un.mode = mode; |
} |
} |
if (def->callback) |
if (def->callback) |
debug_return_bool(def->callback(val)); |
debug_return_bool(def->callback(val)); |
Line 805 store_mode(char *val, struct sudo_defs_types *def, int
|
Line 839 store_mode(char *val, struct sudo_defs_types *def, int
|
static void |
static void |
list_op(char *val, size_t len, struct sudo_defs_types *def, enum list_ops op) |
list_op(char *val, size_t len, struct sudo_defs_types *def, enum list_ops op) |
{ |
{ |
struct list_member *cur, *prev, *tmp; | struct list_member *cur, *prev = NULL; |
debug_decl(list_op, SUDO_DEBUG_DEFAULTS) |
debug_decl(list_op, SUDO_DEBUG_DEFAULTS) |
|
|
if (op == freeall) { |
if (op == freeall) { |
for (cur = def->sd_un.list; cur; ) { | while ((cur = SLIST_FIRST(&def->sd_un.list)) != NULL) { |
tmp = cur; | SLIST_REMOVE_HEAD(&def->sd_un.list, entries); |
cur = tmp->next; | efree(cur->value); |
efree(tmp->value); | efree(cur); |
efree(tmp); | |
} |
} |
def->sd_un.list = NULL; |
|
debug_return; |
debug_return; |
} |
} |
|
|
for (cur = def->sd_un.list, prev = NULL; cur; prev = cur, cur = cur->next) { | SLIST_FOREACH(cur, &def->sd_un.list, entries) { |
if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) { |
if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) { |
|
|
if (op == add) |
if (op == add) |
debug_return; /* already exists */ |
debug_return; /* already exists */ |
|
|
/* Delete node */ |
/* Delete node */ |
if (prev != NULL) | if (prev == NULL) |
prev->next = cur->next; | SLIST_REMOVE_HEAD(&def->sd_un.list, entries); |
else |
else |
def->sd_un.list = cur->next; | SLIST_REMOVE_AFTER(prev, entries); |
efree(cur->value); |
efree(cur->value); |
efree(cur); |
efree(cur); |
break; |
break; |
} |
} |
|
prev = cur; |
} |
} |
|
|
/* Add new node to the head of the list. */ |
/* Add new node to the head of the list. */ |
if (op == add) { |
if (op == add) { |
cur = ecalloc(1, sizeof(struct list_member)); |
cur = ecalloc(1, sizeof(struct list_member)); |
cur->value = estrndup(val, len); |
cur->value = estrndup(val, len); |
cur->next = def->sd_un.list; | SLIST_INSERT_HEAD(&def->sd_un.list, cur, entries); |
def->sd_un.list = cur; | |
} |
} |
debug_return; |
debug_return; |
} |
} |