summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormillert <>2009-06-03 15:52:16 +0000
committermillert <>2009-06-03 15:52:16 +0000
commitba53e391e204926a7a71b5a9848b928a56af0062 (patch)
tree27076f4f89f7c81fc3ad7e7b02facdf369d4b2e6
parent43170abfbd0c2858c372e7ef19f5dffe4f34137c (diff)
downloadopenbsd-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.inc4
-rw-r--r--src/lib/libc/stdlib/getenv.354
-rw-r--r--src/lib/libc/stdlib/getenv.c16
-rw-r--r--src/lib/libc/stdlib/putenv.c50
-rw-r--r--src/lib/libc/stdlib/setenv.c79
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 @@
6SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \ 6SRCS+= 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
54These functions set, unset, and fetch environment variables from the host 54These 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
87The 87The
88.Fn putenv 88.Fn putenv
89function takes an argument of the form 89function takes an argument of the form
90.Ar name Ns = Ns Ar value 90.Ar name Ns = Ns Ar value .
91and is equivalent to: 91The memory pointed to by
92.Bd -literal -offset indent 92.Ar string
93setenv(name, value, 1); 93becomes part of the environment and must not be deallocated by the caller.
94.Ed 94If the variable already exists, it will be overwritten.
95A common source of bugs is to pass a
96.Ar string
97argument that is a locally scoped string buffer.
98This will result in corruption of the environment after leaving
99the scope in which the variable is defined.
100For this reason, the
101.Fn setenv
102function is preferred over
103.Fn putenv .
95.Pp 104.Pp
96The 105The
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
100from the list. 109from the list.
101.Sh RETURN VALUES 110.Sh RETURN VALUES
102The functions 111These functions
103.Fn setenv
104and
105.Fn putenv
106return zero if successful; otherwise the global variable 112return zero if successful; otherwise the global variable
107.Va errno 113.Va errno
108is set to indicate the error and \-1 is returned. 114is set to indicate the error and \-1 is returned.
@@ -112,12 +118,30 @@ If
112is successful, the string returned should be considered read-only. 118is 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
122The
123.Fn setenv
124or
125.Fn putenv
126function was passed a
127.Ar name
128containing an
129.Sq =
130character.
131.Pp
132The
133.Fn putenv
134function was passed a
135.Ar string
136that did not contain an
137.Sq =
138character.
115.It Bq Er ENOMEM 139.It Bq Er ENOMEM
116The function 140The
117.Fn setenv 141.Fn setenv
118or 142or
119.Fn putenv 143.Fn putenv
120failed because they were unable to allocate memory for the environment. 144function 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
34char *__findenv(const char *name, int *offset); 34char *__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 */
45char * 45char *
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 *
75getenv(const char *name) 72getenv(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
34int
35putenv(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
34char *__findenv(const char *name, int *offset); 35char *__findenv(const char *name, int len, int *offset);
35 36
36extern char **environ; 37extern char **environ;
38static 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 */
45int
46putenv(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;
43int 84int
44setenv(const char *name, const char *value, int rewrite) 85setenv(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 */
93void 139int
94unsetenv(const char *name) 140unsetenv(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}