Browse Source

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.
OPENBSD_4_6
millert 15 years ago
parent
commit
d3d9cc08f7
6 changed files with 120 additions and 89 deletions
  1. +3
    -3
      src/include/stdlib.h
  2. +2
    -2
      src/lib/libc/stdlib/Makefile.inc
  3. +39
    -15
      src/lib/libc/stdlib/getenv.3
  4. +8
    -8
      src/lib/libc/stdlib/getenv.c
  5. +0
    -50
      src/lib/libc/stdlib/putenv.c
  6. +68
    -11
      src/lib/libc/stdlib/setenv.c

+ 3
- 3
src/include/stdlib.h View File

@ -1,4 +1,4 @@
/* $OpenBSD: stdlib.h,v 1.45 2008/09/07 20:36:07 martynas Exp $ */
/* $OpenBSD: stdlib.h,v 1.46 2009/06/03 15:52:16 millert Exp $ */
/* $NetBSD: stdlib.h,v 1.25 1995/12/27 21:19:08 jtc Exp $ */ /* $NetBSD: stdlib.h,v 1.25 1995/12/27 21:19:08 jtc Exp $ */
/*- /*-
@ -164,7 +164,7 @@ long nrand48(unsigned short[3]);
unsigned short *seed48(unsigned short[3]); unsigned short *seed48(unsigned short[3]);
void srand48(long); void srand48(long);
int putenv(const char *);
int putenv(char *);
#endif #endif
#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 #if __BSD_VISIBLE || __XPG_VISIBLE >= 420
@ -210,7 +210,7 @@ unsigned long long
*/ */
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XPG_VISIBLE >= 600 #if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XPG_VISIBLE >= 600
int setenv(const char *, const char *, int); int setenv(const char *, const char *, int);
void unsetenv(const char *);
int unsetenv(const char *);
#endif #endif
#if __BSD_VISIBLE #if __BSD_VISIBLE


+ 2
- 2
src/lib/libc/stdlib/Makefile.inc View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile.inc,v 1.41 2008/09/13 22:48:45 martynas Exp $
# $OpenBSD: Makefile.inc,v 1.42 2009/06/03 15:52:16 millert Exp $
# stdlib sources # stdlib sources
.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib .PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib
@ -6,7 +6,7 @@
SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \ SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \
cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \ cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \
getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c l64a.c llabs.c \ getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c l64a.c llabs.c \
lldiv.c lsearch.c malloc.c merge.c putenv.c qsort.c radixsort.c rand.c \
lldiv.c lsearch.c malloc.c merge.c qsort.c radixsort.c rand.c \
random.c realpath.c setenv.c strtoimax.c strtol.c \ random.c realpath.c setenv.c strtoimax.c strtol.c \
strtoll.c strtonum.c strtoul.c strtoull.c strtoumax.c system.c \ strtoll.c strtonum.c strtoul.c strtoull.c strtoumax.c system.c \
tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \ tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \


+ 39
- 15
src/lib/libc/stdlib/getenv.3 View File

@ -29,9 +29,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: getenv.3,v 1.12 2007/05/31 19:19:31 jmc Exp $
.\" $OpenBSD: getenv.3,v 1.13 2009/06/03 15:52:16 millert Exp $
.\" .\"
.Dd $Mdocdate: May 31 2007 $
.Dd $Mdocdate: June 3 2009 $
.Dt GETENV 3 .Dt GETENV 3
.Os .Os
.Sh NAME .Sh NAME
@ -47,8 +47,8 @@
.Ft int .Ft int
.Fn setenv "const char *name" "const char *value" "int overwrite" .Fn setenv "const char *name" "const char *value" "int overwrite"
.Ft int .Ft int
.Fn putenv "const char *string"
.Ft void
.Fn putenv "char *string"
.Ft int
.Fn unsetenv "const char *name" .Fn unsetenv "const char *name"
.Sh DESCRIPTION .Sh DESCRIPTION
These functions set, unset, and fetch environment variables from the host 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
The The
.Fn putenv .Fn putenv
function takes an argument of the form function takes an argument of the form
.Ar name Ns = Ns Ar value
and is equivalent to:
.Bd -literal -offset indent
setenv(name, value, 1);
.Ed
.Ar name Ns = Ns Ar value .
The memory pointed to by
.Ar string
becomes part of the environment and must not be deallocated by the caller.
If the variable already exists, it will be overwritten.
A common source of bugs is to pass a
.Ar string
argument that is a locally scoped string buffer.
This will result in corruption of the environment after leaving
the scope in which the variable is defined.
For this reason, the
.Fn setenv
function is preferred over
.Fn putenv .
.Pp .Pp
The The
.Fn unsetenv .Fn unsetenv
@ -99,10 +108,7 @@ function deletes all instances of the variable name pointed to by
.Fa name .Fa name
from the list. from the list.
.Sh RETURN VALUES .Sh RETURN VALUES
The functions
.Fn setenv
and
.Fn putenv
These functions
return zero if successful; otherwise the global variable return zero if successful; otherwise the global variable
.Va errno .Va errno
is set to indicate the error and \-1 is returned. is set to indicate the error and \-1 is returned.
@ -112,12 +118,30 @@ If
is successful, the string returned should be considered read-only. is successful, the string returned should be considered read-only.
.Sh ERRORS .Sh ERRORS
.Bl -tag -width Er .Bl -tag -width Er
.It Bq Er EINVAL
The
.Fn setenv
or
.Fn putenv
function was passed a
.Ar name
containing an
.Sq =
character.
.Pp
The
.Fn putenv
function was passed a
.Ar string
that did not contain an
.Sq =
character.
.It Bq Er ENOMEM .It Bq Er ENOMEM
The function
The
.Fn setenv .Fn setenv
or or
.Fn putenv .Fn putenv
failed because they were unable to allocate memory for the environment.
function failed because it was unable to allocate memory for the environment.
.El .El
.Sh SEE ALSO .Sh SEE ALSO
.Xr csh 1 , .Xr csh 1 ,


+ 8
- 8
src/lib/libc/stdlib/getenv.c View File

@ -1,4 +1,4 @@
/* $OpenBSD: getenv.c,v 1.8 2005/08/08 08:05:36 espie Exp $ */
/* $OpenBSD: getenv.c,v 1.9 2009/06/03 15:52:16 millert Exp $ */
/* /*
* Copyright (c) 1987, 1993 * Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
@ -31,7 +31,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
char *__findenv(const char *name, int *offset);
char *__findenv(const char *name, int len, int *offset);
/* /*
* __findenv -- * __findenv --
@ -43,18 +43,15 @@ char *__findenv(const char *name, int *offset);
* This routine *should* be a static; don't use it. * This routine *should* be a static; don't use it.
*/ */
char * char *
__findenv(const char *name, int *offset)
__findenv(const char *name, int len, int *offset)
{ {
extern char **environ; extern char **environ;
int len, i;
int i;
const char *np; const char *np;
char **p, *cp; char **p, *cp;
if (name == NULL || environ == NULL) if (name == NULL || environ == NULL)
return (NULL); return (NULL);
for (np = name; *np && *np != '='; ++np)
;
len = np - name;
for (p = environ; (cp = *p) != NULL; ++p) { for (p = environ; (cp = *p) != NULL; ++p) {
for (np = name, i = len; i && *cp; i--) for (np = name, i = len; i && *cp; i--)
if (*cp++ != *np++) if (*cp++ != *np++)
@ -75,6 +72,9 @@ char *
getenv(const char *name) getenv(const char *name)
{ {
int offset; int offset;
const char *np;
return (__findenv(name, &offset));
for (np = name; *np && *np != '='; ++np)
;
return (__findenv(name, (int)(np - name), &offset));
} }

+ 0
- 50
src/lib/libc/stdlib/putenv.c View File

@ -1,50 +0,0 @@
/* $OpenBSD: putenv.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
/*-
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdlib.h>
#include <string.h>
int
putenv(const char *str)
{
char *p, *equal;
int rval;
if ((p = strdup(str)) == NULL)
return (-1);
if ((equal = strchr(p, '=')) == NULL) {
(void)free(p);
return (-1);
}
*equal = '\0';
rval = setenv(p, equal + 1, 1);
(void)free(p);
return (rval);
}

+ 68
- 11
src/lib/libc/stdlib/setenv.c View File

@ -1,4 +1,4 @@
/* $OpenBSD: setenv.c,v 1.9 2005/08/08 08:05:37 espie Exp $ */
/* $OpenBSD: setenv.c,v 1.10 2009/06/03 15:52:16 millert Exp $ */
/* /*
* Copyright (c) 1987 Regents of the University of California. * Copyright (c) 1987 Regents of the University of California.
* All rights reserved. * All rights reserved.
@ -28,12 +28,53 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
char *__findenv(const char *name, int *offset);
char *__findenv(const char *name, int len, int *offset);
extern char **environ; extern char **environ;
static char **lastenv; /* last value of environ */
/*
* putenv --
* Add a name=value string directly to the environmental, replacing
* any current value.
*/
int
putenv(char *str)
{
char **P, *cp;
size_t cnt;
int offset;
for (cp = str; *cp && *cp != '='; ++cp)
;
if (*cp != '=') {
errno = EINVAL;
return (-1); /* missing `=' in string */
}
if (__findenv(str, (int)(cp - str), &offset) != NULL) {
environ[offset] = str;
return (0);
}
/* create new slot for string */
for (P = environ; *P != NULL; P++)
;
cnt = P - environ;
P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2));
if (!P)
return (-1);
if (lastenv != environ)
memcpy(P, environ, cnt * sizeof(char *));
lastenv = environ = P;
environ[cnt] = str;
environ[cnt + 1] = NULL;
return (0);
}
/* /*
* setenv -- * setenv --
@ -43,14 +84,21 @@ extern char **environ;
int int
setenv(const char *name, const char *value, int rewrite) setenv(const char *name, const char *value, int rewrite)
{ {
static char **lastenv; /* last value of environ */
char *C; char *C;
const char *np;
int l_value, offset; int l_value, offset;
if (*value == '=') /* no `=' in value */
++value;
for (np = name; *np && *np != '='; ++np)
;
#ifdef notyet
if (*np) {
errno = EINVAL;
return (-1); /* has `=' in name */
}
#endif
l_value = strlen(value); l_value = strlen(value);
if ((C = __findenv(name, &offset))) { /* find if already exists */
if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) {
if (!rewrite) if (!rewrite)
return (0); return (0);
if (strlen(C) >= l_value) { /* old larger; copy over */ if (strlen(C) >= l_value) { /* old larger; copy over */
@ -74,10 +122,8 @@ setenv(const char *name, const char *value, int rewrite)
offset = cnt; offset = cnt;
environ[cnt + 1] = NULL; environ[cnt + 1] = NULL;
} }
for (C = (char *)name; *C && *C != '='; ++C)
; /* no `=' in name */
if (!(environ[offset] = /* name + `=' + value */ if (!(environ[offset] = /* name + `=' + value */
malloc((size_t)((int)(C - name) + l_value + 2))))
malloc((size_t)((int)(np - name) + l_value + 2))))
return (-1); return (-1);
for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
; ;
@ -90,14 +136,25 @@ setenv(const char *name, const char *value, int rewrite)
* unsetenv(name) -- * unsetenv(name) --
* Delete environmental variable "name". * Delete environmental variable "name".
*/ */
void
int
unsetenv(const char *name) unsetenv(const char *name)
{ {
char **P; char **P;
const char *np;
int offset; int offset;
while (__findenv(name, &offset)) /* if set multiple times */
for (np = name; *np && *np != '='; ++np)
;
if (*np) {
errno = EINVAL;
return (-1); /* has `=' in name */
}
/* could be set multiple times */
while (__findenv(name, (int)(np - name), &offset)) {
for (P = &environ[offset];; ++P) for (P = &environ[offset];; ++P)
if (!(*P = *(P + 1))) if (!(*P = *(P + 1)))
break; break;
}
return (0);
} }

Loading…
Cancel
Save