Make putenv() fully conforms to Open Group specs Issue 6

(also IEEE Std 1003.1-2001)

The specs explicitly says that altering passed string
should change the environment, i.e. putenv() directly puts its arg
into environment (unlike setenv() which just copies it there).
It means that putenv() can't be implemented via setenv()
(like we have before) at all. Putenv() value lives (allows modifying)
up to the next putenv() or setenv() call.
This commit is contained in:
Andrey A. Chernov 2007-04-30 16:56:18 +00:00
parent 0f23397d3f
commit 15fdb055e5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=169138
4 changed files with 58 additions and 26 deletions

View File

@ -88,11 +88,17 @@ to the given
.Pp
The
.Fn putenv
function takes an argument of the form ``name=value'' and is
equivalent to:
.Bd -literal -offset indent
setenv(name, value, 1);
.Ed
function takes an argument of the form ``name=value'' and
puts it directly into the current environment.
If the variable
.Fa name
does not exist in the list,
it is inserted with the given
.Fa value .
If the variable
.Fa name
does exist, it is reset to the given
.Fa value .
.Pp
The
.Fn unsetenv
@ -145,7 +151,8 @@ The
function conforms to
.St -isoC .
The
.Fn setenv
.Fn setenv ,
.Fn putenv
and
.Fn unsetenv
functions conforms to

View File

@ -43,7 +43,8 @@ inline char *__findenv(const char *, int *);
* __findenv --
* 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).
* environmental array, for use by putenv(3), setenv(3) and unsetenv(3).
* Explicitly removes '=' in argument name.
*
* This routine *should* be a static; don't use it.
*/
@ -59,7 +60,9 @@ __findenv(name, offset)
if (environ == NULL)
return (NULL);
len = strlen(name);
for (np = name; *np && *np != '='; ++np)
continue;
len = np - name;
for (p = environ; (cp = *p) != NULL; ++p) {
for (np = name, i = len; i && *cp; i--)
if (*cp++ != *np++)

View File

@ -37,24 +37,46 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
extern char **__alloced; /* if allocated space before */
char *__findenv(const char *, int *);
int
putenv(str)
char *str;
{
char *p, *equal;
int rval, serrno;
extern char **environ;
char *eq;
int offset;
if ((p = strdup(str)) == NULL)
return (-1);
if ((equal = index(p, '=')) == NULL) {
(void)free(p);
if (str == NULL || (eq = strchr(str, '=')) == NULL || eq == str) {
errno = EINVAL;
return (-1);
}
*equal = '\0';
rval = setenv(p, equal + 1, 1);
serrno = errno;
(void)free(p);
errno = serrno;
return (rval);
/* Trimmed version of setenv(3). */
if (__findenv(str, &offset) == NULL) {
int cnt;
char **p;
for (p = environ, cnt = 0; *p; ++p, ++cnt);
if (__alloced == environ) { /* just increase size */
p = (char **)realloc((char *)environ,
(size_t)(sizeof(char *) * (cnt + 2)));
if (!p)
return (-1);
}
else { /* get new space */
/* copy old entries into it */
p = (char **)malloc((size_t)(sizeof(char *) * (cnt + 2)));
if (!p)
return (-1);
bcopy(environ, p, cnt * sizeof(char *));
}
__alloced = environ = p;
environ[cnt + 1] = NULL;
offset = cnt;
}
environ[offset] = str;
return (0);
}

View File

@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
char **__alloced; /* if allocated space before */
char *__findenv(const char *, int *);
/*
@ -52,7 +54,6 @@ setenv(name, value, rewrite)
int rewrite;
{
extern char **environ;
static char **alloced; /* if allocated space before */
char *c;
int l_value, offset;
@ -74,26 +75,25 @@ setenv(name, value, rewrite)
char **p;
for (p = environ, cnt = 0; *p; ++p, ++cnt);
if (alloced == environ) { /* just increase size */
if (__alloced == environ) { /* just increase size */
p = (char **)realloc((char *)environ,
(size_t)(sizeof(char *) * (cnt + 2)));
if (!p)
return (-1);
alloced = environ = p;
}
else { /* get new space */
/* copy old entries into it */
p = malloc((size_t)(sizeof(char *) * (cnt + 2)));
p = (char **)malloc((size_t)(sizeof(char *) * (cnt + 2)));
if (!p)
return (-1);
bcopy(environ, p, cnt * sizeof(char *));
alloced = environ = p;
}
__alloced = environ = p;
environ[cnt + 1] = NULL;
offset = cnt;
}
if (!(environ[offset] = /* name + `=' + value */
malloc((size_t)(strlen(name) + l_value + 2))))
(char *)malloc((size_t)(strlen(name) + l_value + 2))))
return (-1);
for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
for (*c++ = '='; (*c++ = *value++); );