2 * Copyright (c) 1989 - 1992, Julianne Frances Haugh
3 * Copyright (c) 1996 - 1999, Marek Michałkiewicz
4 * Copyright (c) 2003 - 2005, Tomasz Kłoczko
5 * Copyright (c) 2008 - 2009, Nicolas François
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the copyright holders or contributors may not be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #ident "$Id: env.c 2818 2009-04-27 20:07:59Z nekral-guest $"
41 #include "prototypes.h"
44 * NEWENVP_STEP must be a power of two. This is the number
45 * of (char *) pointers to allocate at a time, to avoid using
46 * realloc() too often.
48 #define NEWENVP_STEP 16
50 /*@null@*/char **newenvp = NULL;
51 extern char **environ;
53 static const char *forbid[] = {
55 "BASH_ENV=", /* GNU creeping featurism strikes again... */
60 "LD_", /* anything with the LD_ prefix */
70 /* these are allowed, but with no slashes inside
71 (to work around security problems in GNU gettext) */
72 static const char *noslash[] = {
75 "LC_", /* anything with the LC_ prefix */
80 * initenv() must be called once before using addenv().
84 newenvp = (char **) xmalloc (NEWENVP_STEP * sizeof (char *));
89 void addenv (const char *string, /*@null@*/const char *value)
96 size_t len = strlen (string) + strlen (value) + 2;
98 newstring = xmalloc (len);
99 wlen = snprintf (newstring, len, "%s=%s", string, value);
100 assert (wlen == (int) len -1);
102 newstring = xstrdup (string);
106 * Search for a '=' character within the string and if none is found
107 * just ignore the whole string.
110 cp = strchr (newstring, '=');
116 n = (size_t) (cp - newstring);
118 for (i = 0; i < newenvc; i++) {
119 if ( (strncmp (newstring, newenvp[i], n) == 0)
120 && (('=' == newenvp[i][n]) || ('\0' == newenvp[i][n]))) {
127 newenvp[i] = newstring;
131 newenvp[newenvc++] = newstring;
134 * Check whether newenvc is a multiple of NEWENVP_STEP.
135 * If so we have to resize the vector.
136 * the expression (newenvc & (NEWENVP_STEP - 1)) == 0
137 * is equal to (newenvc % NEWENVP_STEP) == 0
138 * as long as NEWENVP_STEP is a power of 2.
141 if ((newenvc & (NEWENVP_STEP - 1)) == 0) {
146 * If the resize operation succeds we can
147 * happily go on, else print a message.
150 newsize = (newenvc + NEWENVP_STEP) * sizeof (char *);
151 __newenvp = (char **) realloc (newenvp, newsize);
155 * If this is our current environment, update
156 * environ so that it doesn't point to some
157 * free memory area (realloc() could move it).
159 if (environ == newenvp) {
164 (void) fputs (_("Environment overflow\n"), stderr);
166 free (newenvp[newenvc]);
171 * The last entry of newenvp must be NULL
174 newenvp[newenvc] = NULL;
179 * set_env - copy command line arguments into the environment
181 void set_env (int argc, char *const *argv)
187 for (; argc > 0; argc--, argv++) {
188 if (strlen (*argv) >= sizeof variable) {
189 continue; /* ignore long entries */
192 cp = strchr (*argv, '=');
195 wlen = snprintf (variable, sizeof variable, "L%d", noname);
196 assert (wlen < (int) sizeof(variable));
198 addenv (variable, *argv);
202 for (p = forbid; NULL != *p; p++) {
203 if (strncmp (*argv, *p, strlen (*p)) == 0) {
209 strncpy (variable, *argv, (size_t)(cp - *argv));
210 variable[cp - *argv] = '\0';
211 printf (_("You may not change $%s\n"),
216 addenv (*argv, NULL);
222 * sanitize_env - remove some nasty environment variables
223 * If you fall into a total paranoia, you should call this
224 * function for any root-setuid program or anything the user
225 * might change the environment with. 99% useless as almost
226 * all modern Unixes will handle setuid executables properly,
227 * but... I feel better with that silly precaution. -j.
230 void sanitize_env (void)
232 char **envp = environ;
237 for (cur = envp; NULL != *cur; cur++) {
238 for (bad = forbid; NULL != *bad; bad++) {
239 if (strncmp (*cur, *bad, strlen (*bad)) == 0) {
240 for (move = cur; NULL != *move; move++) {
249 for (cur = envp; NULL != *cur; cur++) {
250 for (bad = noslash; NULL != *bad; bad++) {
251 if (strncmp (*cur, *bad, strlen (*bad)) != 0) {
254 if (strchr (*cur, '/') != NULL) {
257 for (move = cur; NULL != *move; move++) {