diff options
author | ache <ache@FreeBSD.org> | 2007-04-30 16:56:18 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 2007-04-30 16:56:18 +0000 |
commit | d85104099ad40c33148426adb779741c366c2f19 (patch) | |
tree | 0f48274fab3bf61e5379abd241da2f704d7da652 /lib/libc/stdlib/putenv.c | |
parent | b5d028a647a14c0c4d23e84788a75778dfd9a05e (diff) | |
download | FreeBSD-src-d85104099ad40c33148426adb779741c366c2f19.zip FreeBSD-src-d85104099ad40c33148426adb779741c366c2f19.tar.gz |
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.
Diffstat (limited to 'lib/libc/stdlib/putenv.c')
-rw-r--r-- | lib/libc/stdlib/putenv.c | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/lib/libc/stdlib/putenv.c b/lib/libc/stdlib/putenv.c index b6c7ccb..56b78cf 100644 --- a/lib/libc/stdlib/putenv.c +++ b/lib/libc/stdlib/putenv.c @@ -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); } |