From bdda89347122e9814a3a681adfc4d950fa914066 Mon Sep 17 00:00:00 2001 From: "Andrey A. Chernov" Date: Mon, 30 Apr 2007 02:25:02 +0000 Subject: [PATCH] Make setenv, putenv, getenv and unsetenv conforming to Open Group specs Issue 6 (also IEEE Std 1003.1-2001) in following areas: args, return, errors. Putenv still needs rewriting because specs explicitly says that altering passed string later should change the environment (currently we copy the string so can't provide that). --- lib/libc/stdlib/getenv.3 | 32 +++++++++++++++++++++++--------- lib/libc/stdlib/getenv.c | 10 +++++----- lib/libc/stdlib/putenv.c | 8 ++++++-- lib/libc/stdlib/setenv.c | 17 ++++++++++++++--- 4 files changed, 48 insertions(+), 19 deletions(-) diff --git a/lib/libc/stdlib/getenv.3 b/lib/libc/stdlib/getenv.3 index 3d365f16a26b..35547aa6b332 100644 --- a/lib/libc/stdlib/getenv.3 +++ b/lib/libc/stdlib/getenv.3 @@ -50,21 +50,17 @@ .Ft int .Fn setenv "const char *name" "const char *value" "int overwrite" .Ft int -.Fn putenv "const char *string" -.Ft void +.Fn putenv "char *string" +.Ft int .Fn unsetenv "const char *name" .Sh DESCRIPTION These functions set, unset and fetch environment variables from the host .Em environment list . For compatibility with differing environment conventions, -the given arguments -.Fa name -and +the given argument .Fa value -may be appended and prepended, -respectively, -with an equal sign +may be prepended with an equal sign .Dq Li \&= . .Pp The @@ -121,9 +117,21 @@ is not in the current environment, .Dv NULL is returned. .Pp -.Rv -std setenv putenv +.Rv -std setenv putenv unsetenv .Sh ERRORS .Bl -tag -width Er +.It Bq Er EINVAL +The function +.Fn setenv +or +.Fn unsetenv +failed because the +.Fa name +is a +.Dv NULL +pointer, points to an empty string, or points to a string containing an +.Dq Li \&= +character. .It Bq Er ENOMEM The function .Fn setenv @@ -141,6 +149,12 @@ The .Fn getenv function conforms to .St -isoC . +The +.Fn setenv +and +.Fn unsetenv +functions conforms to +.St -p1003.1-2001 . .Sh HISTORY The functions .Fn setenv diff --git a/lib/libc/stdlib/getenv.c b/lib/libc/stdlib/getenv.c index 306b6a19f8be..73ac407b4314 100644 --- a/lib/libc/stdlib/getenv.c +++ b/lib/libc/stdlib/getenv.c @@ -44,7 +44,6 @@ inline char *__findenv(const char *, int *); * Returns pointer to value associated with name, if any, else NULL. * Sets offset to be the offset of the name/value combination in the * environmental array, for use by setenv(3) and unsetenv(3). - * Explicitly removes '=' in argument name. * * This routine *should* be a static; don't use it. */ @@ -58,11 +57,9 @@ __findenv(name, offset) const char *np; char **p, *cp; - if (name == NULL || environ == NULL) + if (environ == NULL) return (NULL); - for (np = name; *np && *np != '='; ++np) - continue; - len = np - name; + len = strlen(name); for (p = environ; (cp = *p) != NULL; ++p) { for (np = name, i = len; i && *cp; i--) if (*cp++ != *np++) @@ -85,5 +82,8 @@ getenv(name) { int offset; + if (name == NULL || !*name || strchr(name, '=') != NULL) + return (NULL); + return (__findenv(name, &offset)); } diff --git a/lib/libc/stdlib/putenv.c b/lib/libc/stdlib/putenv.c index a5eea5d0ddfd..b6c7ccb67f83 100644 --- a/lib/libc/stdlib/putenv.c +++ b/lib/libc/stdlib/putenv.c @@ -33,24 +33,28 @@ static char sccsid[] = "@(#)putenv.c 8.2 (Berkeley) 3/27/94"; #include __FBSDID("$FreeBSD$"); +#include #include #include int putenv(str) - const char *str; + char *str; { char *p, *equal; - int rval; + int rval, serrno; if ((p = strdup(str)) == NULL) return (-1); if ((equal = index(p, '=')) == NULL) { (void)free(p); + errno = EINVAL; return (-1); } *equal = '\0'; rval = setenv(p, equal + 1, 1); + serrno = errno; (void)free(p); + errno = serrno; return (rval); } diff --git a/lib/libc/stdlib/setenv.c b/lib/libc/stdlib/setenv.c index 202c022ebfcf..4f05f3207baf 100644 --- a/lib/libc/stdlib/setenv.c +++ b/lib/libc/stdlib/setenv.c @@ -33,6 +33,7 @@ static char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93"; #include __FBSDID("$FreeBSD$"); +#include #include #include #include @@ -55,6 +56,11 @@ setenv(name, value, rewrite) char *c; int l_value, offset; + if (name == NULL || !*name || strchr(name, '=') != NULL) { + errno = EINVAL; + return (-1); + } + if (*value == '=') /* no `=' in value */ ++value; l_value = strlen(value); @@ -88,9 +94,8 @@ setenv(name, value, rewrite) environ[cnt + 1] = NULL; offset = cnt; } - for (c = (char *)name; *c && *c != '='; ++c); /* no `=' in name */ if (!(environ[offset] = /* name + `=' + value */ - malloc((size_t)((int)(c - name) + l_value + 2)))) + malloc((size_t)(strlen(name) + l_value + 2)))) return (-1); for (c = environ[offset]; (*c = *name++) && *c != '='; ++c); for (*c++ = '='; (*c++ = *value++); ); @@ -101,7 +106,7 @@ setenv(name, value, rewrite) * unsetenv(name) -- * Delete environmental variable "name". */ -void +int unsetenv(name) const char *name; { @@ -109,8 +114,14 @@ unsetenv(name) char **p; int offset; + if (name == NULL || !*name || strchr(name, '=') != NULL) { + errno = EINVAL; + return (-1); + } + while (__findenv(name, &offset)) /* if set multiple times */ for (p = &environ[offset];; ++p) if (!(*p = *(p + 1))) break; + return (0); }