Imported Upstream version 1.6.9p9
[debian/sudo] / env.c
1 /*
2  * Copyright (c) 2000-2007 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
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.
7  *
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.
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.
19  */
20
21 #include <config.h>
22
23 #include <sys/types.h>
24 #include <sys/param.h>
25 #include <sys/stat.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 #ifdef HAVE_ERR_H
46 # include <err.h>
47 #else
48 # include "emul/err.h"
49 #endif /* HAVE_ERR_H */
50 #include <pwd.h>
51
52 #include "sudo.h"
53
54 #ifndef lint
55 __unused static const char rcsid[] = "$Sudo: env.c,v 1.39.2.17 2007/07/31 18:04:31 millert Exp $";
56 #endif /* lint */
57
58 /*
59  * Flags used in rebuild_env()
60  */
61 #undef DID_TERM
62 #define DID_TERM        0x0001
63 #undef DID_PATH
64 #define DID_PATH        0x0002
65 #undef DID_HOME
66 #define DID_HOME        0x0004
67 #undef DID_SHELL
68 #define DID_SHELL       0x0008
69 #undef DID_LOGNAME
70 #define DID_LOGNAME     0x0010
71 #undef DID_USER
72 #define DID_USER        0x0020
73 #undef DID_USERNAME
74 #define DID_USERNAME    0x0040
75 #undef DID_MAX
76 #define DID_MAX         0x00ff
77
78 #undef KEPT_TERM
79 #define KEPT_TERM       0x0100
80 #undef KEPT_PATH
81 #define KEPT_PATH       0x0200
82 #undef KEPT_HOME
83 #define KEPT_HOME       0x0400
84 #undef KEPT_SHELL
85 #define KEPT_SHELL      0x0800
86 #undef KEPT_LOGNAME
87 #define KEPT_LOGNAME    0x1000
88 #undef KEPT_USER
89 #define KEPT_USER       0x2000
90 #undef KEPT_USERNAME
91 #define KEPT_USERNAME   0x4000
92 #undef KEPT_MAX
93 #define KEPT_MAX        0xff00
94
95 #undef VNULL
96 #define VNULL   (VOID *)NULL
97
98 struct environment {
99     char **envp;                /* pointer to the new environment */
100     size_t env_size;            /* size of new_environ in char **'s */
101     size_t env_len;             /* number of slots used, not counting NULL */
102 };
103
104 /*
105  * Prototypes
106  */
107 char **rebuild_env              __P((char **, int, int));
108 static void insert_env          __P((char *, struct environment *, int));
109 static char *format_env         __P((char *, ...));
110
111 /*
112  * Copy of the sudo-managed environment.
113  */
114 static struct environment env;
115
116 /*
117  * Default table of "bad" variables to remove from the environment.
118  * XXX - how to omit TERMCAP if it starts with '/'?
119  */
120 static const char *initial_badenv_table[] = {
121     "IFS",
122     "CDPATH",
123     "LOCALDOMAIN",
124     "RES_OPTIONS",
125     "HOSTALIASES",
126     "NLSPATH",
127     "PATH_LOCALE",
128     "LD_*",
129     "_RLD*",
130 #ifdef __hpux
131     "SHLIB_PATH",
132 #endif /* __hpux */
133 #ifdef _AIX
134     "LDR_*",
135     "LIBPATH",
136 #endif
137 #ifdef __APPLE__
138     "DYLD_*",
139 #endif
140 #ifdef HAVE_KERB4
141     "KRB_CONF*",
142     "KRBCONFDIR",
143     "KRBTKFILE",
144 #endif /* HAVE_KERB4 */
145 #ifdef HAVE_KERB5
146     "KRB5_CONFIG*",
147     "KRB5_KTNAME",
148 #endif /* HAVE_KERB5 */
149 #ifdef HAVE_SECURID
150     "VAR_ACE",
151     "USR_ACE",
152     "DLC_ACE",
153 #endif /* HAVE_SECURID */
154     "TERMINFO",                 /* terminfo, exclusive path to terminfo files */
155     "TERMINFO_DIRS",            /* terminfo, path(s) to terminfo files */
156     "TERMPATH",                 /* termcap, path(s) to termcap files */
157     "TERMCAP",                  /* XXX - only if it starts with '/' */
158     "ENV",                      /* ksh, file to source before script runs */
159     "BASH_ENV",                 /* bash, file to source before script runs */
160     "PS4",                      /* bash, prefix for lines in xtrace mode */
161     "GLOBIGNORE",               /* bash, globbing patterns to ignore */
162     "SHELLOPTS",                /* bash, extra command line options */
163     "JAVA_TOOL_OPTIONS",        /* java, extra command line options */
164     "PERLIO_DEBUG ",            /* perl, debugging output file */
165     "PERLLIB",                  /* perl, search path for modules/includes */
166     "PERL5LIB",                 /* perl 5, search path for modules/includes */
167     "PERL5OPT",                 /* perl 5, extra command line options */
168     "PERL5DB",                  /* perl 5, command used to load debugger */
169     "FPATH",                    /* ksh, search path for functions */
170     "NULLCMD",                  /* zsh, command for null file redirection */
171     "READNULLCMD",              /* zsh, command for null file redirection */
172     "ZDOTDIR",                  /* zsh, search path for dot files */
173     "TMPPREFIX",                /* zsh, prefix for temporary files */
174     "PYTHONHOME",               /* python, module search path */
175     "PYTHONPATH",               /* python, search path */
176     "PYTHONINSPECT",            /* python, allow inspection */
177     "RUBYLIB",                  /* ruby, library load path */
178     "RUBYOPT",                  /* ruby, extra command line options */
179     NULL
180 };
181
182 /*
183  * Default table of variables to check for '%' and '/' characters.
184  */
185 static const char *initial_checkenv_table[] = {
186     "COLORTERM",
187     "LANG",
188     "LANGUAGE",
189     "LC_*",
190     "LINGUAS",
191     "TERM",
192     NULL
193 };
194
195 /*
196  * Default table of variables to preserve in the environment.
197  */
198 static const char *initial_keepenv_table[] = {
199     "COLORS",
200     "DISPLAY",
201     "HOSTNAME",
202     "KRB5CCNAME",
203     "LS_COLORS",
204     "MAIL",
205     "PATH",
206     "PS1",
207     "PS2",
208     "TZ",
209     "XAUTHORITY",
210     "XAUTHORIZATION",
211     NULL
212 };
213
214 /*
215  * Given a variable and value, allocate and format an environment string.
216  */
217 static char *
218 #ifdef __STDC__
219 format_env(char *var, ...)
220 #else
221 format_env(var, va_alist)
222     char *var;
223     va_dcl
224 #endif
225 {
226     char *estring;
227     char *val;
228     size_t esize;
229     va_list ap;
230
231 #ifdef __STDC__
232     va_start(ap, var);
233 #else
234     va_start(ap);
235 #endif
236     esize = strlen(var) + 2;
237     while ((val = va_arg(ap, char *)) != NULL)
238         esize += strlen(val);
239     va_end(ap);
240     estring = (char *) emalloc(esize);
241
242     /* Store variable name and the '=' separator.  */
243     if (strlcpy(estring, var, esize) >= esize ||
244         strlcat(estring, "=", esize) >= esize) {
245
246         errx(1, "internal error, format_env() overflow");
247     }
248
249     /* Now store the variable's value (if any) */
250 #ifdef __STDC__
251     va_start(ap, var);
252 #else
253     va_start(ap);
254 #endif
255     while ((val = va_arg(ap, char *)) != NULL) {
256         if (strlcat(estring, val, esize) >= esize)
257             errx(1, "internal error, format_env() overflow");
258     }
259     va_end(ap);
260
261     return(estring);
262 }
263
264 /*
265  * Insert str into e->envp, assumes str has an '=' in it.
266  */
267 static void
268 insert_env(str, e, dupcheck)
269     char *str;
270     struct environment *e;
271     int dupcheck;
272 {
273     char **nep;
274     size_t varlen;
275
276     /* Make sure there is room for the new entry plus a NULL. */
277     if (e->env_len + 2 > e->env_size) {
278         e->env_size += 128;
279         e->envp = erealloc3(e->envp, e->env_size, sizeof(char *));
280     }
281
282     if (dupcheck) {
283             varlen = (strchr(str, '=') - str) + 1;
284
285             for (nep = e->envp; *nep; nep++) {
286                 if (strncmp(str, *nep, varlen) == 0) {
287                     *nep = str;
288                     return;
289                 }
290             }
291     } else
292         nep = e->envp + e->env_len;
293
294     e->env_len++;
295     *nep++ = str;
296     *nep = NULL;
297 }
298
299 /*
300  * Check the env_delete blacklist.
301  * Returns TRUE if the variable was found, else false.
302  */
303 static int
304 matches_env_delete(var)
305     const char *var;
306 {
307     struct list_member *cur;
308     size_t len;
309     int iswild, match = FALSE;
310
311     /* Skip anything listed in env_delete. */
312     for (cur = def_env_delete; cur; cur = cur->next) {
313         len = strlen(cur->value);
314         /* Deal with '*' wildcard */
315         if (cur->value[len - 1] == '*') {
316             len--;
317             iswild = TRUE;
318         } else
319             iswild = FALSE;
320         if (strncmp(cur->value, var, len) == 0 &&
321             (iswild || var[len] == '=')) {
322             match = TRUE;
323             break;
324         }
325     }
326     return(match);
327 }
328
329 /*
330  * Apply the env_check list.
331  * Returns TRUE if the variable is allowed, FALSE if denied
332  * or -1 if no match.
333  */
334 static int
335 matches_env_check(var)
336     const char *var;
337 {
338     struct list_member *cur;
339     size_t len;
340     int iswild, keepit = -1;
341
342     for (cur = def_env_check; cur; cur = cur->next) {
343         len = strlen(cur->value);
344         /* Deal with '*' wildcard */
345         if (cur->value[len - 1] == '*') {
346             len--;
347             iswild = TRUE;
348         } else
349             iswild = FALSE;
350         if (strncmp(cur->value, var, len) == 0 &&
351             (iswild || var[len] == '=')) {
352             keepit = !strpbrk(var, "/%");
353             break;
354         }
355     }
356     return(keepit);
357 }
358
359 /*
360  * Check the env_keep list.
361  * Returns TRUE if the variable is allowed else FALSE.
362  */
363 static int
364 matches_env_keep(var)
365     const char *var;
366 {
367     struct list_member *cur;
368     size_t len;
369     int iswild, keepit = FALSE;
370
371     for (cur = def_env_keep; cur; cur = cur->next) {
372         len = strlen(cur->value);
373         /* Deal with '*' wildcard */
374         if (cur->value[len - 1] == '*') {
375             len--;
376             iswild = TRUE;
377         } else
378             iswild = FALSE;
379         if (strncmp(cur->value, var, len) == 0 &&
380             (iswild || var[len] == '=')) {
381             keepit = TRUE;
382             break;
383         }
384     }
385     return(keepit);
386 }
387
388 /*
389  * Build a new environment and ether clear potentially dangerous
390  * variables from the old one or start with a clean slate.
391  * Also adds sudo-specific variables (SUDO_*).
392  */
393 char **
394 rebuild_env(envp, sudo_mode, noexec)
395     char **envp;
396     int sudo_mode;
397     int noexec;
398 {
399     char **ep, *cp, *ps1;
400     unsigned int didvar;
401
402     /*
403      * Either clean out the environment or reset to a safe default.
404      */
405     ps1 = NULL;
406     didvar = 0;
407     memset(&env, 0, sizeof(env));
408     if (def_env_reset) {
409         /* Pull in vars we want to keep from the old environment. */
410         for (ep = envp; *ep; ep++) {
411             int keepit;
412
413             /* Skip variables with values beginning with () (bash functions) */
414             if ((cp = strchr(*ep, '=')) != NULL) {
415                 if (strncmp(cp, "=() ", 3) == 0)
416                     continue;
417             }
418
419             /*
420              * First check certain variables for '%' and '/' characters.
421              * If no match there, check the keep list.
422              * If nothing matched, we remove it from the environment.
423              */
424             keepit = matches_env_check(*ep);
425             if (keepit == -1)
426                 keepit = matches_env_keep(*ep);
427
428             /* For SUDO_PS1 -> PS1 conversion. */
429             if (strncmp(*ep, "SUDO_PS1=", 8) == 0)
430                 ps1 = *ep + 5;
431
432             if (keepit) {
433                 /* Preserve variable. */
434                 switch (**ep) {
435                     case 'H':
436                         if (strncmp(*ep, "HOME=", 5) == 0)
437                             SET(didvar, DID_HOME);
438                         break;
439                     case 'L':
440                         if (strncmp(*ep, "LOGNAME=", 8) == 0)
441                             SET(didvar, DID_LOGNAME);
442                         break;
443                     case 'P':
444                         if (strncmp(*ep, "PATH=", 5) == 0)
445                             SET(didvar, DID_PATH);
446                         break;
447                     case 'S':
448                         if (strncmp(*ep, "SHELL=", 6) == 0)
449                             SET(didvar, DID_SHELL);
450                         break;
451                     case 'T':
452                         if (strncmp(*ep, "TERM=", 5) == 0)
453                             SET(didvar, DID_TERM);
454                         break;
455                     case 'U':
456                         if (strncmp(*ep, "USER=", 5) == 0)
457                             SET(didvar, DID_USER);
458                         if (strncmp(*ep, "USERNAME=", 5) == 0)
459                             SET(didvar, DID_USERNAME);
460                         break;
461                 }
462                 insert_env(*ep, &env, 0);
463             }
464         }
465         didvar |= didvar << 8;          /* convert DID_* to KEPT_* */
466
467         /*
468          * Add in defaults.  In -i mode these come from the runas user,
469          * otherwise they may be from the user's environment (depends
470          * on sudoers options).
471          */
472         if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
473             insert_env(format_env("HOME", runas_pw->pw_dir, VNULL), &env,
474                 ISSET(didvar, DID_HOME));
475             insert_env(format_env("SHELL", runas_pw->pw_shell, VNULL), &env,
476                 ISSET(didvar, DID_SHELL));
477             insert_env(format_env("LOGNAME", runas_pw->pw_name, VNULL), &env,
478                 ISSET(didvar, DID_LOGNAME));
479             insert_env(format_env("USER", runas_pw->pw_name, VNULL), &env,
480                 ISSET(didvar, DID_USER));
481             insert_env(format_env("USERNAME", runas_pw->pw_name, VNULL), &env,
482                 ISSET(didvar, DID_USERNAME));
483         } else {
484             if (!ISSET(didvar, DID_HOME))
485                 insert_env(format_env("HOME", user_dir, VNULL), &env, 0);
486             if (!ISSET(didvar, DID_SHELL))
487                 insert_env(format_env("SHELL", sudo_user.pw->pw_shell, VNULL),
488                     &env, 0);
489             if (!ISSET(didvar, DID_LOGNAME))
490                 insert_env(format_env("LOGNAME", user_name, VNULL), &env, 0);
491             if (!ISSET(didvar, DID_USER))
492                 insert_env(format_env("USER", user_name, VNULL), &env, 0);
493             if (!ISSET(didvar, DID_USERNAME))
494                 insert_env(format_env("USERNAME", user_name, VNULL), &env, 0);
495         }
496     } else {
497         /*
498          * Copy envp entries as long as they don't match env_delete or
499          * env_check.
500          */
501         for (ep = envp; *ep; ep++) {
502             int okvar;
503
504             /* Skip variables with values beginning with () (bash functions) */
505             if ((cp = strchr(*ep, '=')) != NULL) {
506                 if (strncmp(cp, "=() ", 3) == 0)
507                     continue;
508             }
509
510             /*
511              * First check variables against the blacklist in env_delete.
512              * If no match there check for '%' and '/' characters.
513              */
514             okvar = matches_env_delete(*ep) != TRUE;
515             if (okvar)
516                 okvar = matches_env_check(*ep) != FALSE;
517
518             if (okvar) {
519                 if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
520                     ps1 = *ep + 5;
521                 else if (strncmp(*ep, "PATH=", 5) == 0)
522                     SET(didvar, DID_PATH);
523                 else if (strncmp(*ep, "TERM=", 5) == 0)
524                     SET(didvar, DID_TERM);
525                 insert_env(*ep, &env, 0);
526             }
527         }
528     }
529
530 #ifdef SECURE_PATH
531     /* Replace the PATH envariable with a secure one. */
532     if (!user_is_exempt()) {
533         insert_env(format_env("PATH", SECURE_PATH, VNULL), &env, 1);
534         SET(didvar, DID_PATH);
535     }
536 #endif
537
538     /* Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is true. */
539     if (def_set_logname && runas_pw->pw_name) {
540         if (!ISSET(didvar, KEPT_LOGNAME))
541             insert_env(format_env("LOGNAME", runas_pw->pw_name, VNULL), &env, 1);
542         if (!ISSET(didvar, KEPT_USER))
543             insert_env(format_env("USER", runas_pw->pw_name, VNULL), &env, 1);
544         if (!ISSET(didvar, KEPT_USERNAME))
545             insert_env(format_env("USERNAME", runas_pw->pw_name, VNULL), &env, 1);
546     }
547
548     /* Set $HOME for `sudo -H'.  Only valid at PERM_FULL_RUNAS. */
549     if (runas_pw->pw_dir) {
550         if (ISSET(sudo_mode, MODE_RESET_HOME) ||
551             (ISSET(sudo_mode, MODE_RUN) && (def_always_set_home ||
552             (ISSET(sudo_mode, MODE_SHELL) && def_set_home))))
553             insert_env(format_env("HOME", runas_pw->pw_dir, VNULL), &env, 1);
554     }
555
556     /* Provide default values for $TERM and $PATH if they are not set. */
557     if (!ISSET(didvar, DID_TERM))
558         insert_env("TERM=unknown", &env, 0);
559     if (!ISSET(didvar, DID_PATH))
560         insert_env(format_env("PATH", _PATH_DEFPATH, VNULL), &env, 0);
561
562     /*
563      * Preload a noexec file?  For a list of LD_PRELOAD-alikes, see
564      * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
565      * XXX - should prepend to original value, if any
566      */
567     if (noexec && def_noexec_file != NULL) {
568 #if defined(__darwin__) || defined(__APPLE__)
569         insert_env(format_env("DYLD_INSERT_LIBRARIES", def_noexec_file, VNULL),
570             &env, 1);
571         insert_env(format_env("DYLD_FORCE_FLAT_NAMESPACE", VNULL), &env, 1);
572 #else
573 # if defined(__osf__) || defined(__sgi)
574         insert_env(format_env("_RLD_LIST", def_noexec_file, ":DEFAULT", VNULL),
575             &env, 1);
576 # else
577 #  ifdef _AIX
578         insert_env(format_env("LDR_PRELOAD", def_noexec_file, VNULL), &env, 1);
579 #  else
580         insert_env(format_env("LD_PRELOAD", def_noexec_file, VNULL), &env, 1);
581 #  endif /* _AIX */
582 # endif /* __osf__ || __sgi */
583 #endif /* __darwin__ || __APPLE__ */
584     }
585
586     /* Set PS1 if SUDO_PS1 is set. */
587     if (ps1)
588         insert_env(ps1, &env, 1);
589
590     /* Add the SUDO_COMMAND envariable (cmnd + args). */
591     if (user_args)
592         insert_env(format_env("SUDO_COMMAND", user_cmnd, " ", user_args, VNULL),
593             &env, 1);
594     else
595         insert_env(format_env("SUDO_COMMAND", user_cmnd, VNULL), &env, 1);
596
597     /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */
598     insert_env(format_env("SUDO_USER", user_name, VNULL), &env, 1);
599     easprintf(&cp, "SUDO_UID=%lu", (unsigned long) user_uid);
600     insert_env(cp, &env, 1);
601     easprintf(&cp, "SUDO_GID=%lu", (unsigned long) user_gid);
602     insert_env(cp, &env, 1);
603
604     return(env.envp);
605 }
606
607 char **
608 insert_env_vars(envp, env_vars)
609     char **envp;
610     struct list_member *env_vars;
611 {
612     struct list_member *cur;
613
614     if (env_vars == NULL)
615         return (envp);
616
617     /*
618      * Make sure we still own the environment and steal it back if not.
619      */
620     if (env.envp != envp) {
621         size_t evlen;
622         char **ep;
623
624         for (ep = envp; *ep != NULL; ep++)
625             continue;
626         evlen = ep - envp;
627         if (evlen + 1 > env.env_size) {
628             efree(env.envp);
629             env.env_size = evlen + 1 + 128;
630             env.envp = emalloc2(env.env_size, sizeof(char *));
631         }
632         memcpy(env.envp, envp, (evlen + 1) * sizeof(char *));
633         env.env_len = evlen;
634     }
635
636     /* Add user-specified environment variables. */
637     for (cur = env_vars; cur != NULL; cur = cur->next)
638         insert_env(cur->value, &env, 1);
639
640     return(env.envp);
641 }
642
643 /*
644  * Validate the list of environment variables passed in on the command
645  * line against env_delete, env_check, and env_keep.
646  * Calls log_error() if any specified variables are not allowed.
647  */
648 void
649 validate_env_vars(env_vars)
650     struct list_member *env_vars;
651 {
652     struct list_member *var;
653     char *eq, *bad = NULL;
654     size_t len, blen = 0, bsize = 0;
655     int okvar;
656
657     for (var = env_vars; var != NULL; var = var->next) {
658 #ifdef SECURE_PATH
659         if (!user_is_exempt() && strncmp(var->value, "PATH=", 5) == 0) {
660             okvar = FALSE;
661         } else
662 #endif
663         if (def_env_reset) {
664             okvar = matches_env_check(var->value);
665             if (okvar == -1)
666                 okvar = matches_env_keep(var->value);
667         } else {
668             okvar = matches_env_delete(var->value) == FALSE;
669             if (okvar == FALSE)
670                 okvar = matches_env_check(var->value) != FALSE;
671         }
672         if (okvar == FALSE) {
673             /* Not allowed, add to error string, allocating as needed. */
674             if ((eq = strchr(var->value, '=')) != NULL)
675                 *eq = '\0';
676             len = strlen(var->value) + 2;
677             if (blen + len >= bsize) {
678                 do {
679                     bsize += 1024;
680                 } while (blen + len >= bsize);
681                 bad = erealloc(bad, bsize);
682                 bad[blen] = '\0';
683             }
684             strlcat(bad, var->value, bsize);
685             strlcat(bad, ", ", bsize);
686             blen += len;
687             if (eq != NULL)
688                 *eq = '=';
689         }
690     }
691     if (bad != NULL) {
692         bad[blen - 2] = '\0';           /* remove trailing ", " */
693         log_error(NO_MAIL,
694             "sorry, you are not allowed to set the following environment variables: %s", bad);
695         /* NOTREACHED */
696         efree(bad);
697     }
698 }
699
700 void
701 init_envtables()
702 {
703     struct list_member *cur;
704     const char **p;
705
706     /* Fill in the "env_delete" list. */
707     for (p = initial_badenv_table; *p; p++) {
708         cur = emalloc(sizeof(struct list_member));
709         cur->value = estrdup(*p);
710         cur->next = def_env_delete;
711         def_env_delete = cur;
712     }
713
714     /* Fill in the "env_check" list. */
715     for (p = initial_checkenv_table; *p; p++) {
716         cur = emalloc(sizeof(struct list_member));
717         cur->value = estrdup(*p);
718         cur->next = def_env_check;
719         def_env_check = cur;
720     }
721
722     /* Fill in the "env_keep" list. */
723     for (p = initial_keepenv_table; *p; p++) {
724         cur = emalloc(sizeof(struct list_member));
725         cur->value = estrdup(*p);
726         cur->next = def_env_keep;
727         def_env_keep = cur;
728     }
729 }