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).
This commit is contained in:
Andrey A. Chernov 2007-04-30 02:25:02 +00:00
parent 2f51d93626
commit bdda893471
4 changed files with 48 additions and 19 deletions

View File

@ -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

View File

@ -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));
}

View File

@ -33,24 +33,28 @@ static char sccsid[] = "@(#)putenv.c 8.2 (Berkeley) 3/27/94";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <errno.h>
#include <stdlib.h>
#include <string.h>
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);
}

View File

@ -33,6 +33,7 @@ static char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
@ -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);
}