summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdlib/setenv.c
diff options
context:
space:
mode:
authormillert <millert@openbsd.org>2009-06-03 15:52:16 +0000
committermillert <millert@openbsd.org>2009-06-03 15:52:16 +0000
commit471b62eeaa7f3a18c0aa98b5d605e5cec1625b62 (patch)
tree4b3e2d396ac12f089089348501e828ed4ada2055 /lib/libc/stdlib/setenv.c
parentAdd a section summarising the status line. There are quite a number of status (diff)
downloadwireguard-openbsd-471b62eeaa7f3a18c0aa98b5d605e5cec1625b62.tar.xz
wireguard-openbsd-471b62eeaa7f3a18c0aa98b5d605e5cec1625b62.zip
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.
Diffstat (limited to 'lib/libc/stdlib/setenv.c')
-rw-r--r--lib/libc/stdlib/setenv.c79
1 files changed, 68 insertions, 11 deletions
diff --git a/lib/libc/stdlib/setenv.c b/lib/libc/stdlib/setenv.c
index 36540ebb0c8..242830d7b9a 100644
--- a/lib/libc/stdlib/setenv.c
+++ b/lib/libc/stdlib/setenv.c
@@ -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.
* All rights reserved.
@@ -28,12 +28,53 @@
* SUCH DAMAGE.
*/
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
-char *__findenv(const char *name, int *offset);
+char *__findenv(const char *name, int len, int *offset);
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 --
@@ -43,14 +84,21 @@ extern char **environ;
int
setenv(const char *name, const char *value, int rewrite)
{
- static char **lastenv; /* last value of environ */
char *C;
+ const char *np;
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);
- if ((C = __findenv(name, &offset))) { /* find if already exists */
+ if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) {
if (!rewrite)
return (0);
if (strlen(C) >= l_value) { /* old larger; copy over */
@@ -74,10 +122,8 @@ setenv(const char *name, const char *value, int rewrite)
offset = cnt;
environ[cnt + 1] = NULL;
}
- 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)((int)(np - name) + l_value + 2))))
return (-1);
for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
;
@@ -90,14 +136,25 @@ setenv(const char *name, const char *value, int rewrite)
* unsetenv(name) --
* Delete environmental variable "name".
*/
-void
+int
unsetenv(const char *name)
{
char **P;
+ const char *np;
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)
if (!(*P = *(P + 1)))
break;
+ }
+ return (0);
}