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