[BACK]Return to defaults.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sudo

Annotation of src/usr.bin/sudo/defaults.c, Revision 1.11

1.1       millert     1: /*
1.11    ! millert     2:  * Copyright (c) 1999-2001, 2003-2004 Todd C. Miller <Todd.Miller@courtesan.com>
1.1       millert     3:  *
1.11    ! millert     4:  * Permission to use, copy, modify, and distribute this software for any
        !             5:  * purpose with or without fee is hereby granted, provided that the above
        !             6:  * copyright notice and this permission notice appear in all copies.
1.1       millert     7:  *
1.11    ! millert     8:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !             9:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            10:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            11:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            12:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            13:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            14:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.10      millert    15:  *
                     16:  * Sponsored in part by the Defense Advanced Research Projects
                     17:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
                     18:  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
1.1       millert    19:  */
                     20:
                     21: #include "config.h"
                     22:
1.8       millert    23: #include <sys/types.h>
                     24: #include <sys/param.h>
1.1       millert    25: #include <stdio.h>
                     26: #ifdef STDC_HEADERS
1.8       millert    27: # include <stdlib.h>
                     28: # include <stddef.h>
                     29: #else
                     30: # ifdef HAVE_STDLIB_H
                     31: #  include <stdlib.h>
                     32: # endif
1.1       millert    33: #endif /* STDC_HEADERS */
1.8       millert    34: #ifdef HAVE_STRING_H
                     35: # include <string.h>
                     36: #else
                     37: # ifdef HAVE_STRINGS_H
                     38: #  include <strings.h>
                     39: # endif
                     40: #endif /* HAVE_STRING_H */
                     41: # ifdef HAVE_UNISTD_H
1.1       millert    42: #include <unistd.h>
                     43: #endif /* HAVE_UNISTD_H */
1.11    ! millert    44: #include <pwd.h>
1.9       millert    45: #ifdef HAVE_ERR_H
                     46: # include <err.h>
                     47: #else
                     48: # include "emul/err.h"
                     49: #endif /* HAVE_ERR_H */
1.8       millert    50: #include <ctype.h>
1.1       millert    51:
                     52: #include "sudo.h"
                     53:
                     54: #ifndef lint
1.11    ! millert    55: static const char rcsid[] = "$Sudo: defaults.c,v 1.48 2004/06/06 23:58:10 millert Exp $";
1.1       millert    56: #endif /* lint */
                     57:
                     58: /*
                     59:  * For converting between syslog numbers and strings.
                     60:  */
                     61: struct strmap {
                     62:     char *name;
                     63:     int num;
                     64: };
                     65:
                     66: #ifdef LOG_NFACILITIES
                     67: static struct strmap facilities[] = {
                     68: #ifdef LOG_AUTHPRIV
                     69:        { "authpriv",   LOG_AUTHPRIV },
                     70: #endif
                     71:        { "auth",       LOG_AUTH },
                     72:        { "daemon",     LOG_DAEMON },
                     73:        { "user",       LOG_USER },
                     74:        { "local0",     LOG_LOCAL0 },
                     75:        { "local1",     LOG_LOCAL1 },
                     76:        { "local2",     LOG_LOCAL2 },
                     77:        { "local3",     LOG_LOCAL3 },
                     78:        { "local4",     LOG_LOCAL4 },
                     79:        { "local5",     LOG_LOCAL5 },
                     80:        { "local6",     LOG_LOCAL6 },
                     81:        { "local7",     LOG_LOCAL7 },
                     82:        { NULL,         -1 }
                     83: };
                     84: #endif /* LOG_NFACILITIES */
                     85:
                     86: static struct strmap priorities[] = {
                     87:        { "alert",      LOG_ALERT },
                     88:        { "crit",       LOG_CRIT },
                     89:        { "debug",      LOG_DEBUG },
                     90:        { "emerg",      LOG_EMERG },
                     91:        { "err",        LOG_ERR },
                     92:        { "info",       LOG_INFO },
                     93:        { "notice",     LOG_NOTICE },
                     94:        { "warning",    LOG_WARNING },
                     95:        { NULL,         -1 }
                     96: };
                     97:
                     98: extern int sudolineno;
                     99:
                    100: /*
                    101:  * Local prototypes.
                    102:  */
                    103: static int store_int __P((char *, struct sudo_defs_types *, int));
1.11    ! millert   104: static int store_list __P((char *, struct sudo_defs_types *, int));
        !           105: static int store_mode __P((char *, struct sudo_defs_types *, int));
1.1       millert   106: static int store_str __P((char *, struct sudo_defs_types *, int));
                    107: static int store_syslogfac __P((char *, struct sudo_defs_types *, int));
                    108: static int store_syslogpri __P((char *, struct sudo_defs_types *, int));
1.11    ! millert   109: static int store_tuple __P((char *, struct sudo_defs_types *, int));
        !           110: static int store_uint __P((char *, struct sudo_defs_types *, int));
1.8       millert   111: static void list_op __P((char *, size_t, struct sudo_defs_types *, enum list_ops));
1.11    ! millert   112: static const char *logfac2str __P((int));
        !           113: static const char *logpri2str __P((int));
1.1       millert   114:
                    115: /*
                    116:  * Table describing compile-time and run-time options.
                    117:  */
1.8       millert   118: #include <def_data.c>
1.1       millert   119:
                    120: /*
                    121:  * Print version and configure info.
                    122:  */
                    123: void
                    124: dump_defaults()
                    125: {
                    126:     struct sudo_defs_types *cur;
1.8       millert   127:     struct list_member *item;
1.11    ! millert   128:     struct def_values *def;
1.1       millert   129:
                    130:     for (cur = sudo_defs_table; cur->name; cur++) {
                    131:        if (cur->desc) {
                    132:            switch (cur->type & T_MASK) {
                    133:                case T_FLAG:
                    134:                    if (cur->sd_un.flag)
                    135:                        puts(cur->desc);
                    136:                    break;
                    137:                case T_STR:
1.11    ! millert   138:                    if (cur->sd_un.str) {
        !           139:                        (void) printf(cur->desc, cur->sd_un.str);
        !           140:                        putchar('\n');
        !           141:                    }
        !           142:                    break;
1.1       millert   143:                case T_LOGFAC:
1.11    ! millert   144:                    if (cur->sd_un.ival) {
        !           145:                        (void) printf(cur->desc, logfac2str(cur->sd_un.ival));
        !           146:                        putchar('\n');
        !           147:                    }
        !           148:                    break;
1.1       millert   149:                case T_LOGPRI:
1.11    ! millert   150:                    if (cur->sd_un.ival) {
        !           151:                        (void) printf(cur->desc, logpri2str(cur->sd_un.ival));
1.1       millert   152:                        putchar('\n');
                    153:                    }
                    154:                    break;
1.8       millert   155:                case T_UINT:
1.1       millert   156:                case T_INT:
                    157:                    (void) printf(cur->desc, cur->sd_un.ival);
                    158:                    putchar('\n');
                    159:                    break;
                    160:                case T_MODE:
                    161:                    (void) printf(cur->desc, cur->sd_un.mode);
                    162:                    putchar('\n');
                    163:                    break;
1.8       millert   164:                case T_LIST:
                    165:                    if (cur->sd_un.list) {
                    166:                        puts(cur->desc);
                    167:                        for (item = cur->sd_un.list; item; item = item->next)
                    168:                            printf("\t%s\n", item->value);
                    169:                    }
                    170:                    break;
1.11    ! millert   171:                case T_TUPLE:
        !           172:                    for (def = cur->values; def->sval; def++) {
        !           173:                        if (cur->sd_un.ival == def->ival) {
        !           174:                            (void) printf(cur->desc, def->sval);
        !           175:                            break;
        !           176:                        }
        !           177:                    }
        !           178:                    putchar('\n');
        !           179:                    break;
1.1       millert   180:            }
                    181:        }
                    182:     }
                    183: }
                    184:
                    185: /*
                    186:  * List each option along with its description.
                    187:  */
                    188: void
                    189: list_options()
                    190: {
                    191:     struct sudo_defs_types *cur;
                    192:     char *p;
                    193:
                    194:     (void) puts("Available options in a sudoers ``Defaults'' line:\n");
                    195:     for (cur = sudo_defs_table; cur->name; cur++) {
                    196:        if (cur->name && cur->desc) {
                    197:            switch (cur->type & T_MASK) {
                    198:                case T_FLAG:
                    199:                    (void) printf("%s: %s\n", cur->name, cur->desc);
                    200:                    break;
                    201:                default:
                    202:                    p = strrchr(cur->desc, ':');
                    203:                    if (p)
1.8       millert   204:                        (void) printf("%s: %.*s\n", cur->name,
                    205:                            (int) (p - cur->desc), cur->desc);
1.1       millert   206:                    else
                    207:                        (void) printf("%s: %s\n", cur->name, cur->desc);
                    208:                    break;
                    209:            }
                    210:        }
                    211:     }
                    212: }
                    213:
                    214: /*
                    215:  * Sets/clears an entry in the defaults structure
                    216:  * If a variable that takes a value is used in a boolean
                    217:  * context with op == 0, disable that variable.
                    218:  * Eg. you may want to turn off logging to a file for some hosts.
                    219:  * This is only meaningful for variables that are *optional*.
                    220:  */
                    221: int
                    222: set_default(var, val, op)
                    223:     char *var;
                    224:     char *val;
                    225:     int op;     /* TRUE or FALSE */
                    226: {
                    227:     struct sudo_defs_types *cur;
1.2       millert   228:     int num;
1.1       millert   229:
1.2       millert   230:     for (cur = sudo_defs_table, num = 0; cur->name; cur++, num++) {
1.1       millert   231:        if (strcmp(var, cur->name) == 0)
                    232:            break;
                    233:     }
                    234:     if (!cur->name) {
1.9       millert   235:        warnx("unknown defaults entry `%s' referenced near line %d",
1.1       millert   236:            var, sudolineno);
                    237:        return(FALSE);
                    238:     }
                    239:
                    240:     switch (cur->type & T_MASK) {
                    241:        case T_LOGFAC:
                    242:            if (!store_syslogfac(val, cur, op)) {
                    243:                if (val)
1.9       millert   244:                    warnx("value `%s' is invalid for option `%s'", val, var);
1.1       millert   245:                else
1.9       millert   246:                    warnx("no value specified for `%s' on line %d",
1.1       millert   247:                        var, sudolineno);
                    248:                return(FALSE);
                    249:            }
                    250:            break;
                    251:        case T_LOGPRI:
                    252:            if (!store_syslogpri(val, cur, op)) {
                    253:                if (val)
1.9       millert   254:                    warnx("value `%s' is invalid for option `%s'", val, var);
1.1       millert   255:                else
1.9       millert   256:                    warnx("no value specified for `%s' on line %d",
1.1       millert   257:                        var, sudolineno);
                    258:                return(FALSE);
                    259:            }
                    260:            break;
                    261:        case T_STR:
                    262:            if (!val) {
                    263:                /* Check for bogus boolean usage or lack of a value. */
1.11    ! millert   264:                if (!ISSET(cur->type, T_BOOL) || op != FALSE) {
1.9       millert   265:                    warnx("no value specified for `%s' on line %d",
1.1       millert   266:                        var, sudolineno);
                    267:                    return(FALSE);
                    268:                }
                    269:            }
1.11    ! millert   270:            if (ISSET(cur->type, T_PATH) && val && *val != '/') {
1.9       millert   271:                warnx("values for `%s' must start with a '/'", var);
1.1       millert   272:                return(FALSE);
                    273:            }
                    274:            if (!store_str(val, cur, op)) {
1.9       millert   275:                warnx("value `%s' is invalid for option `%s'", val, var);
1.1       millert   276:                return(FALSE);
                    277:            }
                    278:            break;
                    279:        case T_INT:
                    280:            if (!val) {
                    281:                /* Check for bogus boolean usage or lack of a value. */
1.11    ! millert   282:                if (!ISSET(cur->type, T_BOOL) || op != FALSE) {
1.9       millert   283:                    warnx("no value specified for `%s' on line %d",
1.1       millert   284:                        var, sudolineno);
                    285:                    return(FALSE);
                    286:                }
                    287:            }
                    288:            if (!store_int(val, cur, op)) {
1.9       millert   289:                warnx("value `%s' is invalid for option `%s'", val, var);
1.1       millert   290:                return(FALSE);
                    291:            }
                    292:            break;
1.8       millert   293:        case T_UINT:
                    294:            if (!val) {
                    295:                /* Check for bogus boolean usage or lack of a value. */
1.11    ! millert   296:                if (!ISSET(cur->type, T_BOOL) || op != FALSE) {
1.9       millert   297:                    warnx("no value specified for `%s' on line %d",
1.8       millert   298:                        var, sudolineno);
                    299:                    return(FALSE);
                    300:                }
                    301:            }
                    302:            if (!store_uint(val, cur, op)) {
1.9       millert   303:                warnx("value `%s' is invalid for option `%s'", val, var);
1.8       millert   304:                return(FALSE);
                    305:            }
                    306:            break;
1.1       millert   307:        case T_MODE:
                    308:            if (!val) {
                    309:                /* Check for bogus boolean usage or lack of a value. */
1.11    ! millert   310:                if (!ISSET(cur->type, T_BOOL) || op != FALSE) {
1.9       millert   311:                    warnx("no value specified for `%s' on line %d",
1.1       millert   312:                        var, sudolineno);
                    313:                    return(FALSE);
                    314:                }
                    315:            }
                    316:            if (!store_mode(val, cur, op)) {
1.9       millert   317:                warnx("value `%s' is invalid for option `%s'", val, var);
1.1       millert   318:                return(FALSE);
                    319:            }
                    320:            break;
                    321:        case T_FLAG:
                    322:            if (val) {
1.9       millert   323:                warnx("option `%s' does not take a value on line %d",
                    324:                    var, sudolineno);
1.1       millert   325:                return(FALSE);
                    326:            }
                    327:            cur->sd_un.flag = op;
1.2       millert   328:
                    329:            /* Special action for I_FQDN.  Move to own switch if we get more */
                    330:            if (num == I_FQDN && op)
                    331:                set_fqdn();
1.1       millert   332:            break;
1.8       millert   333:        case T_LIST:
                    334:            if (!val) {
                    335:                /* Check for bogus boolean usage or lack of a value. */
1.11    ! millert   336:                if (!ISSET(cur->type, T_BOOL) || op != FALSE) {
1.9       millert   337:                    warnx("no value specified for `%s' on line %d",
1.8       millert   338:                        var, sudolineno);
                    339:                    return(FALSE);
                    340:                }
                    341:            }
                    342:            if (!store_list(val, cur, op)) {
1.9       millert   343:                warnx("value `%s' is invalid for option `%s'", val, var);
1.8       millert   344:                return(FALSE);
                    345:            }
1.11    ! millert   346:            break;
        !           347:        case T_TUPLE:
        !           348:            if (!val) {
        !           349:                /* Check for bogus boolean usage or lack of a value. */
        !           350:                if (!ISSET(cur->type, T_BOOL) || op != FALSE) {
        !           351:                    warnx("no value specified for `%s' on line %d",
        !           352:                        var, sudolineno);
        !           353:                    return(FALSE);
        !           354:                }
        !           355:            }
        !           356:            if (!store_tuple(val, cur, op)) {
        !           357:                warnx("value `%s' is invalid for option `%s'", val, var);
        !           358:                return(FALSE);
        !           359:            }
        !           360:            break;
1.1       millert   361:     }
                    362:
                    363:     return(TRUE);
                    364: }
                    365:
                    366: /*
                    367:  * Set default options to compiled-in values.
                    368:  * Any of these may be overridden at runtime by a "Defaults" file.
                    369:  */
                    370: void
                    371: init_defaults()
                    372: {
                    373:     static int firsttime = 1;
                    374:     struct sudo_defs_types *def;
                    375:
                    376:     /* Free any strings that were set. */
                    377:     if (!firsttime) {
                    378:        for (def = sudo_defs_table; def->name; def++)
                    379:            switch (def->type & T_MASK) {
                    380:                case T_STR:
                    381:                    if (def->sd_un.str) {
                    382:                        free(def->sd_un.str);
                    383:                        def->sd_un.str = NULL;
                    384:                    }
                    385:                    break;
1.8       millert   386:                case T_LIST:
                    387:                    list_op(NULL, 0, def, freeall);
                    388:                    break;
1.1       millert   389:            }
                    390:     }
                    391:
                    392:     /* First initialize the flags. */
                    393: #ifdef LONG_OTP_PROMPT
1.11    ! millert   394:     def_long_otp_prompt = TRUE;
1.1       millert   395: #endif
                    396: #ifdef IGNORE_DOT_PATH
1.11    ! millert   397:     def_ignore_dot = TRUE;
1.1       millert   398: #endif
                    399: #ifdef ALWAYS_SEND_MAIL
1.11    ! millert   400:     def_mail_always = TRUE;
1.1       millert   401: #endif
                    402: #ifdef SEND_MAIL_WHEN_NO_USER
1.11    ! millert   403:     def_mail_no_user = TRUE;
1.1       millert   404: #endif
                    405: #ifdef SEND_MAIL_WHEN_NO_HOST
1.11    ! millert   406:     def_mail_no_host = TRUE;
1.1       millert   407: #endif
                    408: #ifdef SEND_MAIL_WHEN_NOT_OK
1.11    ! millert   409:     def_mail_no_perms = TRUE;
1.1       millert   410: #endif
                    411: #ifdef USE_TTY_TICKETS
1.11    ! millert   412:     def_tty_tickets = TRUE;
1.1       millert   413: #endif
                    414: #ifndef NO_LECTURE
1.11    ! millert   415:     def_lecture = once;
1.1       millert   416: #endif
                    417: #ifndef NO_AUTHENTICATION
1.11    ! millert   418:     def_authenticate = TRUE;
1.1       millert   419: #endif
                    420: #ifndef NO_ROOT_SUDO
1.11    ! millert   421:     def_root_sudo = TRUE;
1.1       millert   422: #endif
                    423: #ifdef HOST_IN_LOG
1.11    ! millert   424:     def_log_host = TRUE;
1.1       millert   425: #endif
1.3       millert   426: #ifdef SHELL_IF_NO_ARGS
1.11    ! millert   427:     def_shell_noargs = TRUE;
1.3       millert   428: #endif
1.1       millert   429: #ifdef SHELL_SETS_HOME
1.11    ! millert   430:     def_set_home = TRUE;
1.1       millert   431: #endif
                    432: #ifndef DONT_LEAK_PATH_INFO
1.11    ! millert   433:     def_path_info = TRUE;
1.1       millert   434: #endif
                    435: #ifdef FQDN
1.11    ! millert   436:     def_fqdn = TRUE;
1.1       millert   437: #endif
                    438: #ifdef USE_INSULTS
1.11    ! millert   439:     def_insults = TRUE;
1.1       millert   440: #endif
1.4       millert   441: #ifdef ENV_EDITOR
1.11    ! millert   442:     def_env_editor = TRUE;
1.4       millert   443: #endif
1.11    ! millert   444:     def_set_logname = TRUE;
1.1       millert   445:
                    446:     /* Syslog options need special care since they both strings and ints */
                    447: #if (LOGGING & SLOG_SYSLOG)
1.8       millert   448:     (void) store_syslogfac(LOGFAC, &sudo_defs_table[I_SYSLOG], TRUE);
                    449:     (void) store_syslogpri(PRI_SUCCESS, &sudo_defs_table[I_SYSLOG_GOODPRI],
                    450:        TRUE);
                    451:     (void) store_syslogpri(PRI_FAILURE, &sudo_defs_table[I_SYSLOG_BADPRI],
                    452:        TRUE);
1.1       millert   453: #endif
                    454:
1.3       millert   455:     /* Password flags also have a string and integer component. */
1.11    ! millert   456:     (void) store_tuple("any", &sudo_defs_table[I_LISTPW], TRUE);
        !           457:     (void) store_tuple("all", &sudo_defs_table[I_VERIFYPW], TRUE);
1.3       millert   458:
1.1       millert   459:     /* Then initialize the int-like things. */
                    460: #ifdef SUDO_UMASK
1.11    ! millert   461:     def_umask = SUDO_UMASK;
1.1       millert   462: #else
1.11    ! millert   463:     def_umask = 0777;
1.1       millert   464: #endif
1.11    ! millert   465:     def_loglinelen = MAXLOGFILELEN;
        !           466:     def_timestamp_timeout = TIMEOUT;
        !           467:     def_passwd_timeout = PASSWORD_TIMEOUT;
        !           468:     def_passwd_tries = TRIES_FOR_PASSWORD;
1.1       millert   469:
1.8       millert   470:     /* Now do the strings */
1.11    ! millert   471:     def_mailto = estrdup(MAILTO);
        !           472:     def_mailsub = estrdup(MAILSUBJECT);
        !           473:     def_badpass_message = estrdup(INCORRECT_PASSWORD);
        !           474:     def_timestampdir = estrdup(_PATH_SUDO_TIMEDIR);
        !           475:     def_passprompt = estrdup(PASSPROMPT);
        !           476:     def_runas_default = estrdup(RUNAS_DEFAULT);
1.8       millert   477: #ifdef _PATH_SUDO_SENDMAIL
1.11    ! millert   478:     def_mailerpath = estrdup(_PATH_SUDO_SENDMAIL);
        !           479:     def_mailerflags = estrdup("-t");
1.1       millert   480: #endif
                    481: #if (LOGGING & SLOG_FILE)
1.11    ! millert   482:     def_logfile = estrdup(_PATH_SUDO_LOGFILE);
1.1       millert   483: #endif
                    484: #ifdef EXEMPTGROUP
1.11    ! millert   485:     def_exempt_group = estrdup(EXEMPTGROUP);
        !           486: #endif
        !           487:     def_editor = estrdup(EDITOR);
        !           488: #ifdef _PATH_SUDO_NOEXEC
        !           489:     def_noexec_file = estrdup(_PATH_SUDO_NOEXEC);
1.1       millert   490: #endif
                    491:
1.8       millert   492:     /* Finally do the lists (currently just environment tables). */
                    493:     init_envtables();
                    494:
1.1       millert   495:     /*
                    496:      * The following depend on the above values.
                    497:      * We use a pointer to the string so that if its
                    498:      * value changes we get the change.
                    499:      */
                    500:     if (user_runas == NULL)
1.11    ! millert   501:        user_runas = &def_runas_default;
1.1       millert   502:
                    503:     firsttime = 0;
                    504: }
                    505:
                    506: static int
                    507: store_int(val, def, op)
                    508:     char *val;
                    509:     struct sudo_defs_types *def;
                    510:     int op;
                    511: {
                    512:     char *endp;
                    513:     long l;
                    514:
                    515:     if (op == FALSE) {
                    516:        def->sd_un.ival = 0;
                    517:     } else {
                    518:        l = strtol(val, &endp, 10);
1.8       millert   519:        if (*endp != '\0')
                    520:            return(FALSE);
                    521:        /* XXX - should check against INT_MAX */
                    522:        def->sd_un.ival = (unsigned int)l;
                    523:     }
1.11    ! millert   524:     if (def->callback)
        !           525:        return(def->callback(val));
1.8       millert   526:     return(TRUE);
                    527: }
                    528:
                    529: static int
                    530: store_uint(val, def, op)
                    531:     char *val;
                    532:     struct sudo_defs_types *def;
                    533:     int op;
                    534: {
                    535:     char *endp;
                    536:     long l;
                    537:
                    538:     if (op == FALSE) {
                    539:        def->sd_un.ival = 0;
                    540:     } else {
                    541:        l = strtol(val, &endp, 10);
1.1       millert   542:        if (*endp != '\0' || l < 0)
                    543:            return(FALSE);
                    544:        /* XXX - should check against INT_MAX */
                    545:        def->sd_un.ival = (unsigned int)l;
                    546:     }
1.11    ! millert   547:     if (def->callback)
        !           548:        return(def->callback(val));
        !           549:     return(TRUE);
        !           550: }
        !           551:
        !           552: static int
        !           553: store_tuple(val, def, op)
        !           554:     char *val;
        !           555:     struct sudo_defs_types *def;
        !           556:     int op;
        !           557: {
        !           558:     struct def_values *v;
        !           559:
        !           560:     /*
        !           561:      * Since enums are really just ints we store the value as an ival.
        !           562:      * In the future, there may be multiple enums for different tuple
        !           563:      * types we want to avoid and special knowledge of the tuple type.
        !           564:      * This does assume that the first entry in the tuple enum will
        !           565:      * be the equivalent to a boolean "false".
        !           566:      */
        !           567:     if (op == FALSE) {
        !           568:        def->sd_un.ival = 0;
        !           569:     } else {
        !           570:        for (v = def->values; v != NULL; v++) {
        !           571:            if (strcmp(v->sval, val) == 0) {
        !           572:                def->sd_un.ival = v->ival;
        !           573:                break;
        !           574:            }
        !           575:        }
        !           576:        if (v == NULL)
        !           577:            return(FALSE);
        !           578:     }
        !           579:     if (def->callback)
        !           580:        return(def->callback(val));
1.1       millert   581:     return(TRUE);
                    582: }
                    583:
                    584: static int
                    585: store_str(val, def, op)
                    586:     char *val;
                    587:     struct sudo_defs_types *def;
                    588:     int op;
                    589: {
                    590:
                    591:     if (def->sd_un.str)
                    592:        free(def->sd_un.str);
                    593:     if (op == FALSE)
                    594:        def->sd_un.str = NULL;
                    595:     else
                    596:        def->sd_un.str = estrdup(val);
1.11    ! millert   597:     if (def->callback)
        !           598:        return(def->callback(val));
1.1       millert   599:     return(TRUE);
                    600: }
                    601:
                    602: static int
1.8       millert   603: store_list(str, def, op)
                    604:     char *str;
                    605:     struct sudo_defs_types *def;
                    606:     int op;
                    607: {
                    608:     char *start, *end;
                    609:
                    610:     /* Remove all old members. */
                    611:     if (op == FALSE || op == TRUE)
                    612:        list_op(NULL, 0, def, freeall);
                    613:
                    614:     /* Split str into multiple space-separated words and act on each one. */
                    615:     if (op != FALSE) {
                    616:        end = str;
                    617:        do {
                    618:            /* Remove leading blanks, if nothing but blanks we are done. */
                    619:            for (start = end; isblank(*start); start++)
                    620:                ;
                    621:            if (*start == '\0')
                    622:                break;
                    623:
                    624:            /* Find end position and perform operation. */
1.11    ! millert   625:            for (end = start; *end && !isblank(*end); end++)
1.8       millert   626:                ;
                    627:            list_op(start, end - start, def, op == '-' ? delete : add);
                    628:        } while (*end++ != '\0');
                    629:     }
                    630:     return(TRUE);
                    631: }
                    632:
                    633: static int
1.1       millert   634: store_syslogfac(val, def, op)
                    635:     char *val;
                    636:     struct sudo_defs_types *def;
                    637:     int op;
                    638: {
                    639:     struct strmap *fac;
                    640:
                    641:     if (op == FALSE) {
1.11    ! millert   642:        def->sd_un.ival = FALSE;
1.1       millert   643:        return(TRUE);
                    644:     }
                    645: #ifdef LOG_NFACILITIES
                    646:     if (!val)
                    647:        return(FALSE);
                    648:     for (fac = facilities; fac->name && strcmp(val, fac->name); fac++)
                    649:        ;
                    650:     if (fac->name == NULL)
                    651:        return(FALSE);                          /* not found */
                    652:
1.11    ! millert   653:     def->sd_un.ival = fac->num;
1.1       millert   654: #else
1.11    ! millert   655:     def->sd_un.ival = -1;
1.1       millert   656: #endif /* LOG_NFACILITIES */
                    657:     return(TRUE);
                    658: }
                    659:
1.11    ! millert   660: static const char *
        !           661: logfac2str(n)
        !           662:     int n;
        !           663: {
        !           664: #ifdef LOG_NFACILITIES
        !           665:     struct strmap *fac;
        !           666:
        !           667:     for (fac = facilities; fac->name && fac->num != n; fac++)
        !           668:        ;
        !           669:     return (fac->name);
        !           670: #else
        !           671:     return ("default");
        !           672: #endif /* LOG_NFACILITIES */
        !           673: }
        !           674:
1.1       millert   675: static int
                    676: store_syslogpri(val, def, op)
                    677:     char *val;
                    678:     struct sudo_defs_types *def;
                    679:     int op;
                    680: {
                    681:     struct strmap *pri;
                    682:
                    683:     if (op == FALSE || !val)
                    684:        return(FALSE);
                    685:
                    686:     for (pri = priorities; pri->name && strcmp(val, pri->name); pri++)
                    687:        ;
                    688:     if (pri->name == NULL)
                    689:        return(FALSE);                          /* not found */
                    690:
1.11    ! millert   691:     def->sd_un.ival = pri->num;
1.1       millert   692:     return(TRUE);
                    693: }
                    694:
1.11    ! millert   695: static const char *
        !           696: logpri2str(n)
        !           697:     int n;
        !           698: {
        !           699:     struct strmap *pri;
        !           700:
        !           701:     for (pri = priorities; pri->name && pri->num != n; pri++)
        !           702:        ;
        !           703:     return (pri->name);
        !           704: }
        !           705:
1.1       millert   706: static int
                    707: store_mode(val, def, op)
                    708:     char *val;
                    709:     struct sudo_defs_types *def;
                    710:     int op;
                    711: {
                    712:     char *endp;
                    713:     long l;
                    714:
                    715:     if (op == FALSE) {
                    716:        def->sd_un.mode = (mode_t)0777;
                    717:     } else {
                    718:        l = strtol(val, &endp, 8);
1.5       millert   719:        if (*endp != '\0' || l < 0 || l > 0777)
1.1       millert   720:            return(FALSE);
                    721:        def->sd_un.mode = (mode_t)l;
                    722:     }
1.11    ! millert   723:     if (def->callback)
        !           724:        return(def->callback(val));
1.1       millert   725:     return(TRUE);
1.8       millert   726: }
                    727:
                    728: static void
                    729: list_op(val, len, def, op)
                    730:     char *val;
                    731:     size_t len;
                    732:     struct sudo_defs_types *def;
                    733:     enum list_ops op;
                    734: {
                    735:     struct list_member *cur, *prev, *tmp;
                    736:
                    737:     if (op == freeall) {
                    738:        for (cur = def->sd_un.list; cur; ) {
                    739:            tmp = cur;
                    740:            cur = tmp->next;
                    741:            free(tmp->value);
                    742:            free(tmp);
                    743:        }
                    744:        def->sd_un.list = NULL;
                    745:        return;
                    746:     }
                    747:
                    748:     for (cur = def->sd_un.list, prev = NULL; cur; prev = cur, cur = cur->next) {
                    749:        if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) {
                    750:
                    751:            if (op == add)
                    752:                return;                 /* already exists */
                    753:
                    754:            /* Delete node */
                    755:            if (prev != NULL)
                    756:                prev->next = cur->next;
                    757:            else
                    758:                def->sd_un.list = cur->next;
                    759:            free(cur->value);
                    760:            free(cur);
                    761:            break;
                    762:        }
                    763:     }
                    764:
                    765:     /* Add new node to the head of the list. */
                    766:     if (op == add) {
                    767:        cur = emalloc(sizeof(struct list_member));
                    768:        cur->value = emalloc(len + 1);
                    769:        (void) memcpy(cur->value, val, len);
                    770:        cur->value[len] = '\0';
                    771:        cur->next = def->sd_un.list;
                    772:        def->sd_un.list = cur;
                    773:     }
1.1       millert   774: }