diff options
author | millert <> | 2009-06-03 15:52:16 +0000 |
---|---|---|
committer | millert <> | 2009-06-03 15:52:16 +0000 |
commit | ba53e391e204926a7a71b5a9848b928a56af0062 (patch) | |
tree | 27076f4f89f7c81fc3ad7e7b02facdf369d4b2e6 | |
parent | 43170abfbd0c2858c372e7ef19f5dffe4f34137c (diff) | |
download | openbsd-ba53e391e204926a7a71b5a9848b928a56af0062.tar.gz openbsd-ba53e391e204926a7a71b5a9848b928a56af0062.tar.bz2 openbsd-ba53e391e204926a7a71b5a9848b928a56af0062.zip |
Make putenv(), setenv() and unsetenv() standards compliant. The
standard explicitly disallows passing setenv a name with a '=' in
it but historic BSD behavior is to allow this but to ignore the '='
and anything after it.
-rw-r--r-- | src/lib/libc/stdlib/Makefile.inc | 4 | ||||
-rw-r--r-- | src/lib/libc/stdlib/getenv.3 | 54 | ||||
-rw-r--r-- | src/lib/libc/stdlib/getenv.c | 16 | ||||
-rw-r--r-- | src/lib/libc/stdlib/putenv.c | 50 | ||||
-rw-r--r-- | src/lib/libc/stdlib/setenv.c | 79 |
5 files changed, 117 insertions, 86 deletions
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc index c149aeef0a..3b9b36a1ed 100644 --- a/src/lib/libc/stdlib/Makefile.inc +++ b/src/lib/libc/stdlib/Makefile.inc | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: Makefile.inc,v 1.41 2008/09/13 22:48:45 martynas Exp $ | 1 | # $OpenBSD: Makefile.inc,v 1.42 2009/06/03 15:52:16 millert Exp $ |
2 | 2 | ||
3 | # stdlib sources | 3 | # stdlib sources |
4 | .PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib | 4 | .PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib |
@@ -6,7 +6,7 @@ | |||
6 | SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \ | 6 | SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \ |
7 | cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \ | 7 | cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \ |
8 | getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c l64a.c llabs.c \ | 8 | getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c l64a.c llabs.c \ |
9 | lldiv.c lsearch.c malloc.c merge.c putenv.c qsort.c radixsort.c rand.c \ | 9 | lldiv.c lsearch.c malloc.c merge.c qsort.c radixsort.c rand.c \ |
10 | random.c realpath.c setenv.c strtoimax.c strtol.c \ | 10 | random.c realpath.c setenv.c strtoimax.c strtol.c \ |
11 | strtoll.c strtonum.c strtoul.c strtoull.c strtoumax.c system.c \ | 11 | strtoll.c strtonum.c strtoul.c strtoull.c strtoumax.c system.c \ |
12 | tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \ | 12 | tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \ |
diff --git a/src/lib/libc/stdlib/getenv.3 b/src/lib/libc/stdlib/getenv.3 index 1d8546997f..484ff991dc 100644 --- a/src/lib/libc/stdlib/getenv.3 +++ b/src/lib/libc/stdlib/getenv.3 | |||
@@ -29,9 +29,9 @@ | |||
29 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 29 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
30 | .\" SUCH DAMAGE. | 30 | .\" SUCH DAMAGE. |
31 | .\" | 31 | .\" |
32 | .\" $OpenBSD: getenv.3,v 1.12 2007/05/31 19:19:31 jmc Exp $ | 32 | .\" $OpenBSD: getenv.3,v 1.13 2009/06/03 15:52:16 millert Exp $ |
33 | .\" | 33 | .\" |
34 | .Dd $Mdocdate: May 31 2007 $ | 34 | .Dd $Mdocdate: June 3 2009 $ |
35 | .Dt GETENV 3 | 35 | .Dt GETENV 3 |
36 | .Os | 36 | .Os |
37 | .Sh NAME | 37 | .Sh NAME |
@@ -47,8 +47,8 @@ | |||
47 | .Ft int | 47 | .Ft int |
48 | .Fn setenv "const char *name" "const char *value" "int overwrite" | 48 | .Fn setenv "const char *name" "const char *value" "int overwrite" |
49 | .Ft int | 49 | .Ft int |
50 | .Fn putenv "const char *string" | 50 | .Fn putenv "char *string" |
51 | .Ft void | 51 | .Ft int |
52 | .Fn unsetenv "const char *name" | 52 | .Fn unsetenv "const char *name" |
53 | .Sh DESCRIPTION | 53 | .Sh DESCRIPTION |
54 | These functions set, unset, and fetch environment variables from the host | 54 | These functions set, unset, and fetch environment variables from the host |
@@ -87,11 +87,20 @@ is zero, the variable is not reset, otherwise it is reset to the given | |||
87 | The | 87 | The |
88 | .Fn putenv | 88 | .Fn putenv |
89 | function takes an argument of the form | 89 | function takes an argument of the form |
90 | .Ar name Ns = Ns Ar value | 90 | .Ar name Ns = Ns Ar value . |
91 | and is equivalent to: | 91 | The memory pointed to by |
92 | .Bd -literal -offset indent | 92 | .Ar string |
93 | setenv(name, value, 1); | 93 | becomes part of the environment and must not be deallocated by the caller. |
94 | .Ed | 94 | If the variable already exists, it will be overwritten. |
95 | A common source of bugs is to pass a | ||
96 | .Ar string | ||
97 | argument that is a locally scoped string buffer. | ||
98 | This will result in corruption of the environment after leaving | ||
99 | the scope in which the variable is defined. | ||
100 | For this reason, the | ||
101 | .Fn setenv | ||
102 | function is preferred over | ||
103 | .Fn putenv . | ||
95 | .Pp | 104 | .Pp |
96 | The | 105 | The |
97 | .Fn unsetenv | 106 | .Fn unsetenv |
@@ -99,10 +108,7 @@ function deletes all instances of the variable name pointed to by | |||
99 | .Fa name | 108 | .Fa name |
100 | from the list. | 109 | from the list. |
101 | .Sh RETURN VALUES | 110 | .Sh RETURN VALUES |
102 | The functions | 111 | These functions |
103 | .Fn setenv | ||
104 | and | ||
105 | .Fn putenv | ||
106 | return zero if successful; otherwise the global variable | 112 | return zero if successful; otherwise the global variable |
107 | .Va errno | 113 | .Va errno |
108 | is set to indicate the error and \-1 is returned. | 114 | is set to indicate the error and \-1 is returned. |
@@ -112,12 +118,30 @@ If | |||
112 | is successful, the string returned should be considered read-only. | 118 | is successful, the string returned should be considered read-only. |
113 | .Sh ERRORS | 119 | .Sh ERRORS |
114 | .Bl -tag -width Er | 120 | .Bl -tag -width Er |
121 | .It Bq Er EINVAL | ||
122 | The | ||
123 | .Fn setenv | ||
124 | or | ||
125 | .Fn putenv | ||
126 | function was passed a | ||
127 | .Ar name | ||
128 | containing an | ||
129 | .Sq = | ||
130 | character. | ||
131 | .Pp | ||
132 | The | ||
133 | .Fn putenv | ||
134 | function was passed a | ||
135 | .Ar string | ||
136 | that did not contain an | ||
137 | .Sq = | ||
138 | character. | ||
115 | .It Bq Er ENOMEM | 139 | .It Bq Er ENOMEM |
116 | The function | 140 | The |
117 | .Fn setenv | 141 | .Fn setenv |
118 | or | 142 | or |
119 | .Fn putenv | 143 | .Fn putenv |
120 | failed because they were unable to allocate memory for the environment. | 144 | function failed because it was unable to allocate memory for the environment. |
121 | .El | 145 | .El |
122 | .Sh SEE ALSO | 146 | .Sh SEE ALSO |
123 | .Xr csh 1 , | 147 | .Xr csh 1 , |
diff --git a/src/lib/libc/stdlib/getenv.c b/src/lib/libc/stdlib/getenv.c index 72367b34e2..5aff11c61a 100644 --- a/src/lib/libc/stdlib/getenv.c +++ b/src/lib/libc/stdlib/getenv.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: getenv.c,v 1.8 2005/08/08 08:05:36 espie Exp $ */ | 1 | /* $OpenBSD: getenv.c,v 1.9 2009/06/03 15:52:16 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1987, 1993 | 3 | * Copyright (c) 1987, 1993 |
4 | * The Regents of the University of California. All rights reserved. | 4 | * The Regents of the University of California. All rights reserved. |
@@ -31,7 +31,7 @@ | |||
31 | #include <stdlib.h> | 31 | #include <stdlib.h> |
32 | #include <string.h> | 32 | #include <string.h> |
33 | 33 | ||
34 | char *__findenv(const char *name, int *offset); | 34 | char *__findenv(const char *name, int len, int *offset); |
35 | 35 | ||
36 | /* | 36 | /* |
37 | * __findenv -- | 37 | * __findenv -- |
@@ -43,18 +43,15 @@ char *__findenv(const char *name, int *offset); | |||
43 | * This routine *should* be a static; don't use it. | 43 | * This routine *should* be a static; don't use it. |
44 | */ | 44 | */ |
45 | char * | 45 | char * |
46 | __findenv(const char *name, int *offset) | 46 | __findenv(const char *name, int len, int *offset) |
47 | { | 47 | { |
48 | extern char **environ; | 48 | extern char **environ; |
49 | int len, i; | 49 | int i; |
50 | const char *np; | 50 | const char *np; |
51 | char **p, *cp; | 51 | char **p, *cp; |
52 | 52 | ||
53 | if (name == NULL || environ == NULL) | 53 | if (name == NULL || environ == NULL) |
54 | return (NULL); | 54 | return (NULL); |
55 | for (np = name; *np && *np != '='; ++np) | ||
56 | ; | ||
57 | len = np - name; | ||
58 | for (p = environ; (cp = *p) != NULL; ++p) { | 55 | for (p = environ; (cp = *p) != NULL; ++p) { |
59 | for (np = name, i = len; i && *cp; i--) | 56 | for (np = name, i = len; i && *cp; i--) |
60 | if (*cp++ != *np++) | 57 | if (*cp++ != *np++) |
@@ -75,6 +72,9 @@ char * | |||
75 | getenv(const char *name) | 72 | getenv(const char *name) |
76 | { | 73 | { |
77 | int offset; | 74 | int offset; |
75 | const char *np; | ||
78 | 76 | ||
79 | return (__findenv(name, &offset)); | 77 | for (np = name; *np && *np != '='; ++np) |
78 | ; | ||
79 | return (__findenv(name, (int)(np - name), &offset)); | ||
80 | } | 80 | } |
diff --git a/src/lib/libc/stdlib/putenv.c b/src/lib/libc/stdlib/putenv.c deleted file mode 100644 index 54482f6a14..0000000000 --- a/src/lib/libc/stdlib/putenv.c +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | /* $OpenBSD: putenv.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */ | ||
2 | /*- | ||
3 | * Copyright (c) 1988, 1993 | ||
4 | * The Regents of the University of California. All rights reserved. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions | ||
8 | * are met: | ||
9 | * 1. Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * 2. Redistributions in binary form must reproduce the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer in the | ||
13 | * documentation and/or other materials provided with the distribution. | ||
14 | * 3. Neither the name of the University nor the names of its contributors | ||
15 | * may be used to endorse or promote products derived from this software | ||
16 | * without specific prior written permission. | ||
17 | * | ||
18 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
28 | * SUCH DAMAGE. | ||
29 | */ | ||
30 | |||
31 | #include <stdlib.h> | ||
32 | #include <string.h> | ||
33 | |||
34 | int | ||
35 | putenv(const char *str) | ||
36 | { | ||
37 | char *p, *equal; | ||
38 | int rval; | ||
39 | |||
40 | if ((p = strdup(str)) == NULL) | ||
41 | return (-1); | ||
42 | if ((equal = strchr(p, '=')) == NULL) { | ||
43 | (void)free(p); | ||
44 | return (-1); | ||
45 | } | ||
46 | *equal = '\0'; | ||
47 | rval = setenv(p, equal + 1, 1); | ||
48 | (void)free(p); | ||
49 | return (rval); | ||
50 | } | ||
diff --git a/src/lib/libc/stdlib/setenv.c b/src/lib/libc/stdlib/setenv.c index 36540ebb0c..242830d7b9 100644 --- a/src/lib/libc/stdlib/setenv.c +++ b/src/lib/libc/stdlib/setenv.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: setenv.c,v 1.9 2005/08/08 08:05:37 espie Exp $ */ | 1 | /* $OpenBSD: setenv.c,v 1.10 2009/06/03 15:52:16 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1987 Regents of the University of California. | 3 | * Copyright (c) 1987 Regents of the University of California. |
4 | * All rights reserved. | 4 | * All rights reserved. |
@@ -28,12 +28,53 @@ | |||
28 | * SUCH DAMAGE. | 28 | * SUCH DAMAGE. |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <errno.h> | ||
31 | #include <stdlib.h> | 32 | #include <stdlib.h> |
32 | #include <string.h> | 33 | #include <string.h> |
33 | 34 | ||
34 | char *__findenv(const char *name, int *offset); | 35 | char *__findenv(const char *name, int len, int *offset); |
35 | 36 | ||
36 | extern char **environ; | 37 | extern char **environ; |
38 | static char **lastenv; /* last value of environ */ | ||
39 | |||
40 | /* | ||
41 | * putenv -- | ||
42 | * Add a name=value string directly to the environmental, replacing | ||
43 | * any current value. | ||
44 | */ | ||
45 | int | ||
46 | putenv(char *str) | ||
47 | { | ||
48 | char **P, *cp; | ||
49 | size_t cnt; | ||
50 | int offset; | ||
51 | |||
52 | for (cp = str; *cp && *cp != '='; ++cp) | ||
53 | ; | ||
54 | if (*cp != '=') { | ||
55 | errno = EINVAL; | ||
56 | return (-1); /* missing `=' in string */ | ||
57 | } | ||
58 | |||
59 | if (__findenv(str, (int)(cp - str), &offset) != NULL) { | ||
60 | environ[offset] = str; | ||
61 | return (0); | ||
62 | } | ||
63 | |||
64 | /* create new slot for string */ | ||
65 | for (P = environ; *P != NULL; P++) | ||
66 | ; | ||
67 | cnt = P - environ; | ||
68 | P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); | ||
69 | if (!P) | ||
70 | return (-1); | ||
71 | if (lastenv != environ) | ||
72 | memcpy(P, environ, cnt * sizeof(char *)); | ||
73 | lastenv = environ = P; | ||
74 | environ[cnt] = str; | ||
75 | environ[cnt + 1] = NULL; | ||
76 | return (0); | ||
77 | } | ||
37 | 78 | ||
38 | /* | 79 | /* |
39 | * setenv -- | 80 | * setenv -- |
@@ -43,14 +84,21 @@ extern char **environ; | |||
43 | int | 84 | int |
44 | setenv(const char *name, const char *value, int rewrite) | 85 | setenv(const char *name, const char *value, int rewrite) |
45 | { | 86 | { |
46 | static char **lastenv; /* last value of environ */ | ||
47 | char *C; | 87 | char *C; |
88 | const char *np; | ||
48 | int l_value, offset; | 89 | int l_value, offset; |
49 | 90 | ||
50 | if (*value == '=') /* no `=' in value */ | 91 | for (np = name; *np && *np != '='; ++np) |
51 | ++value; | 92 | ; |
93 | #ifdef notyet | ||
94 | if (*np) { | ||
95 | errno = EINVAL; | ||
96 | return (-1); /* has `=' in name */ | ||
97 | } | ||
98 | #endif | ||
99 | |||
52 | l_value = strlen(value); | 100 | l_value = strlen(value); |
53 | if ((C = __findenv(name, &offset))) { /* find if already exists */ | 101 | if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) { |
54 | if (!rewrite) | 102 | if (!rewrite) |
55 | return (0); | 103 | return (0); |
56 | if (strlen(C) >= l_value) { /* old larger; copy over */ | 104 | if (strlen(C) >= l_value) { /* old larger; copy over */ |
@@ -74,10 +122,8 @@ setenv(const char *name, const char *value, int rewrite) | |||
74 | offset = cnt; | 122 | offset = cnt; |
75 | environ[cnt + 1] = NULL; | 123 | environ[cnt + 1] = NULL; |
76 | } | 124 | } |
77 | for (C = (char *)name; *C && *C != '='; ++C) | ||
78 | ; /* no `=' in name */ | ||
79 | if (!(environ[offset] = /* name + `=' + value */ | 125 | if (!(environ[offset] = /* name + `=' + value */ |
80 | malloc((size_t)((int)(C - name) + l_value + 2)))) | 126 | malloc((size_t)((int)(np - name) + l_value + 2)))) |
81 | return (-1); | 127 | return (-1); |
82 | for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) | 128 | for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) |
83 | ; | 129 | ; |
@@ -90,14 +136,25 @@ setenv(const char *name, const char *value, int rewrite) | |||
90 | * unsetenv(name) -- | 136 | * unsetenv(name) -- |
91 | * Delete environmental variable "name". | 137 | * Delete environmental variable "name". |
92 | */ | 138 | */ |
93 | void | 139 | int |
94 | unsetenv(const char *name) | 140 | unsetenv(const char *name) |
95 | { | 141 | { |
96 | char **P; | 142 | char **P; |
143 | const char *np; | ||
97 | int offset; | 144 | int offset; |
98 | 145 | ||
99 | while (__findenv(name, &offset)) /* if set multiple times */ | 146 | for (np = name; *np && *np != '='; ++np) |
147 | ; | ||
148 | if (*np) { | ||
149 | errno = EINVAL; | ||
150 | return (-1); /* has `=' in name */ | ||
151 | } | ||
152 | |||
153 | /* could be set multiple times */ | ||
154 | while (__findenv(name, (int)(np - name), &offset)) { | ||
100 | for (P = &environ[offset];; ++P) | 155 | for (P = &environ[offset];; ++P) |
101 | if (!(*P = *(P + 1))) | 156 | if (!(*P = *(P + 1))) |
102 | break; | 157 | break; |
158 | } | ||
159 | return (0); | ||
103 | } | 160 | } |