Module Name:    src
Committed By:   christos
Date:           Fri Oct  1 20:11:32 UTC 2010

Modified Files:
        src/lib/libc/stdlib: getenv.3 getenv.c putenv.c setenv.c

Log Message:
make putenv POSIX compliant.


To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/lib/libc/stdlib/getenv.3
cvs rdiff -u -r1.23 -r1.24 src/lib/libc/stdlib/getenv.c
cvs rdiff -u -r1.12 -r1.13 src/lib/libc/stdlib/putenv.c
cvs rdiff -u -r1.38 -r1.39 src/lib/libc/stdlib/setenv.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/stdlib/getenv.3
diff -u src/lib/libc/stdlib/getenv.3:1.20 src/lib/libc/stdlib/getenv.3:1.21
--- src/lib/libc/stdlib/getenv.3:1.20	Thu Sep 23 08:49:31 2010
+++ src/lib/libc/stdlib/getenv.3	Fri Oct  1 16:11:32 2010
@@ -1,4 +1,4 @@
-.\"	$NetBSD: getenv.3,v 1.20 2010/09/23 12:49:31 njoly Exp $
+.\"	$NetBSD: getenv.3,v 1.21 2010/10/01 20:11:32 christos Exp $
 .\"
 .\" Copyright (c) 1988, 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -33,7 +33,7 @@
 .\"
 .\"     from: @(#)getenv.3	8.2 (Berkeley) 12/11/93
 .\"
-.Dd September 25, 2005
+.Dd October 1, 2010
 .Dt GETENV 3
 .Os
 .Sh NAME
@@ -54,7 +54,7 @@
 .Ft int
 .Fn setenv "const char *name" "const char *value" "int overwrite"
 .Ft int
-.Fn putenv "const char *string"
+.Fn putenv "char *string"
 .Ft int
 .Fn unsetenv "const char *name"
 .Sh DESCRIPTION
@@ -120,11 +120,18 @@
 .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 
+.Dq name=value
+and it will set the environment variable
+.Dq name
+equal to
+.Dq value
+by altering an existing entry, or creating a new one if an existing
+one does not exit.
+The actual string argument passed to
+.Fn putenv
+will become part of the environment.
+If one changes the string, the environment will also change.
 .Pp
 The
 .Fn unsetenv

Index: src/lib/libc/stdlib/getenv.c
diff -u src/lib/libc/stdlib/getenv.c:1.23 src/lib/libc/stdlib/getenv.c:1.24
--- src/lib/libc/stdlib/getenv.c:1.23	Tue Sep 28 20:44:04 2010
+++ src/lib/libc/stdlib/getenv.c	Fri Oct  1 16:11:32 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: getenv.c,v 1.23 2010/09/29 00:44:04 enami Exp $	*/
+/*	$NetBSD: getenv.c,v 1.24 2010/10/01 20:11:32 christos Exp $	*/
 
 /*
  * Copyright (c) 1987, 1993
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)getenv.c	8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: getenv.c,v 1.23 2010/09/29 00:44:04 enami Exp $");
+__RCSID("$NetBSD: getenv.c,v 1.24 2010/10/01 20:11:32 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -50,6 +50,7 @@
 rwlock_t __environ_lock = RWLOCK_INITIALIZER;
 #endif
 char **__environ_malloced;
+static char **saveenv;
 static size_t environ_malloced_len;
 
 __weak_alias(getenv_r, _getenv_r)
@@ -106,16 +107,29 @@
 	char **p;
 	size_t nl;
 
-	if (offset == -1) {
+	if (offset == -1 || saveenv != environ) {
 		char **ptr;
 		for (ptr = environ, offset = 0; *ptr != NULL; ptr++)
 			offset++;
 	}
 
 	nl = offset + 2; 	/* one for potentially new entry one for NULL */
-	if (nl <= environ_malloced_len)
+	if (nl <= environ_malloced_len && saveenv == environ)
 		return 0;
 
+	if (saveenv == environ) {		/* just increase size */
+		if ((p = realloc(saveenv, nl * sizeof(*p))) == NULL)
+			return -1;
+		saveenv = p;
+	} else {				/* get new space */
+		free(saveenv);
+		if ((saveenv = malloc(nl * sizeof(*saveenv))) == NULL)
+			return -1;
+		(void)memcpy(saveenv, environ, (nl - 2) * sizeof(*saveenv));
+	}
+	environ = saveenv;
+	environ[offset + 1] = NULL;
+
 	p = realloc(__environ_malloced, nl * sizeof(*p));
 	if (p == NULL)
 		return -1;
@@ -151,9 +165,9 @@
 	len = np - name;
 	for (p = environ; (c = *p) != NULL; ++p)
 		if (strncmp(c, name, len) == 0 && c[len] == '=') {
-			*offset = p - environ;
+			*offset = (int)(p - environ);
 			return c + len + 1;
 		}
-	*offset = p - environ;
+	*offset = (int)(p - environ);
 	return NULL;
 }

Index: src/lib/libc/stdlib/putenv.c
diff -u src/lib/libc/stdlib/putenv.c:1.12 src/lib/libc/stdlib/putenv.c:1.13
--- src/lib/libc/stdlib/putenv.c:1.12	Thu Aug  7 12:43:42 2003
+++ src/lib/libc/stdlib/putenv.c	Fri Oct  1 16:11:32 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: putenv.c,v 1.12 2003/08/07 16:43:42 agc Exp $	*/
+/*	$NetBSD: putenv.c,v 1.13 2010/10/01 20:11:32 christos Exp $	*/
 
 /*-
  * Copyright (c) 1988, 1993
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)putenv.c	8.2 (Berkeley) 3/27/94";
 #else
-__RCSID("$NetBSD: putenv.c,v 1.12 2003/08/07 16:43:42 agc Exp $");
+__RCSID("$NetBSD: putenv.c,v 1.13 2010/10/01 20:11:32 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -44,28 +44,41 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include "reentrant.h"
+#include "local.h"
 
 #ifdef __weak_alias
 __weak_alias(putenv,_putenv)
 #endif
 
 int
-putenv(str)
-	const char *str;
+putenv(char *str)
 {
 	char *p, *equal;
-	int rval;
+	int offset;
 
 	_DIAGASSERT(str != NULL);
 
-	if ((p = strdup(str)) == NULL)
-		return (-1);
-	if ((equal = strchr(p, '=')) == NULL) {
-		(void)free(p);
-		return (-1);
-	}
+	if ((equal = strchr(str, '=')) == NULL)
+		return -1;
+
+	if (rwlock_wrlock(&__environ_lock) != 0)
+		return -1;
+
 	*equal = '\0';
-	rval = setenv(p, equal + 1, 1);
-	(void)free(p);
-	return (rval);
+	p = __findenv(str, &offset);
+	*equal = '=';
+
+	if (__allocenv(offset) == -1)
+		goto bad;
+
+	if (p != NULL && environ[offset] == __environ_malloced[offset])
+		free(__environ_malloced[offset]);
+
+	environ[offset] = str;
+	rwlock_unlock(&__environ_lock);
+	return 0;
+bad:
+	rwlock_unlock(&__environ_lock);
+	return -1;
 }

Index: src/lib/libc/stdlib/setenv.c
diff -u src/lib/libc/stdlib/setenv.c:1.38 src/lib/libc/stdlib/setenv.c:1.39
--- src/lib/libc/stdlib/setenv.c:1.38	Thu Sep 30 08:41:33 2010
+++ src/lib/libc/stdlib/setenv.c	Fri Oct  1 16:11:32 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: setenv.c,v 1.38 2010/09/30 12:41:33 tron Exp $	*/
+/*	$NetBSD: setenv.c,v 1.39 2010/10/01 20:11:32 christos Exp $	*/
 
 /*
  * Copyright (c) 1987, 1993
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)setenv.c	8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: setenv.c,v 1.38 2010/09/30 12:41:33 tron Exp $");
+__RCSID("$NetBSD: setenv.c,v 1.39 2010/10/01 20:11:32 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -51,10 +51,6 @@
 __weak_alias(setenv,_setenv)
 #endif
 
-#ifdef _REENTRANT
-extern rwlock_t __environ_lock;
-#endif
-
 /*
  * setenv --
  *	Set the value of the environmental variable "name" to be
@@ -63,8 +59,7 @@
 int
 setenv(const char *name, const char *value, int rewrite)
 {
-	static char **saveenv;	/* copy of previously allocated space */
-	char *c, **newenv;
+	char *c;
 	const char *cc;
 	size_t l_value, size;
 	int offset;
@@ -90,20 +85,6 @@
 			goto good;
 		if (strlen(c) >= l_value)	/* old is enough; copy over */
 			goto copy;
-	} else {					/* create new slot */
-		size = (size_t)(sizeof(char *) * (offset + 2));
-		if (saveenv == environ) {		/* just increase size */
-			if ((newenv = realloc(saveenv, size)) == NULL)
-				goto bad;
-			saveenv = newenv;
-		} else {				/* get new space */
-			free(saveenv);
-			if ((saveenv = malloc(size)) == NULL)
-				goto bad;
-			(void)memcpy(saveenv, environ, size - sizeof(char *));
-		}
-		environ = saveenv;
-		environ[offset + 1] = NULL;
 	}
 	for (cc = name; *cc && *cc != '='; ++cc)	/* no `=' in name */
 		continue;

Reply via email to