setenv.c.patch   [plain text]


--- setenv.c.orig	2003-05-20 15:23:25.000000000 -0700
+++ setenv.c	2004-11-05 17:15:11.000000000 -0800
@@ -40,81 +40,137 @@
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
+#include <crt_externs.h>
+#include <errno.h>
 
 char *__findenv(const char *, int *);
+__private_extern__ int __setenv(const char *, const char *, int, int);
 
-/*
- * setenv --
- *	Set the value of the environmental variable "name" to be
- *	"value".  If rewrite is set, replace any current value.
- */
-int
-setenv(name, value, rewrite)
+#ifndef BUILDING_VARIANT
+__private_extern__ int
+__setenv(name, value, rewrite, copy)
 	const char *name;
 	const char *value;
-	int rewrite;
+	int rewrite, copy;
 {
-	extern char **environ;
+	char ***environp = _NSGetEnviron();
 	static char **alloced;			/* if allocated space before */
 	char *c;
-	int l_value, offset;
+	int offset;
 
-	if (*value == '=')			/* no `=' in value */
-		++value;
-	l_value = strlen(value);
 	if ((c = __findenv(name, &offset))) {	/* find if already exists */
 		if (!rewrite)
 			return (0);
-		if (strlen(c) >= l_value) {	/* old larger; copy over */
-			while ( (*c++ = *value++) );
-			return (0);
-		}
+		/* In UNIX03, we can't overwrite even if the string is long
+		 * enough, because the putenv() string is owned by the user
+		 * (ie, always malloc() a new string) */
 	} else {					/* create new slot */
 		int cnt;
 		char **p;
 
-		for (p = environ, cnt = 0; *p; ++p, ++cnt);
-		if (alloced == environ) {			/* just increase size */
-			p = (char **)realloc((char *)environ,
+		for (p = *environp, cnt = 0; *p; ++p, ++cnt);
+		if (alloced == *environp) {			/* just increase size */
+			p = (char **)realloc((char *)*environp,
 			    (size_t)(sizeof(char *) * (cnt + 2)));
 			if (!p)
 				return (-1);
-			alloced = environ = p;
+			alloced = *environp = p;
 		}
 		else {				/* get new space */
 						/* copy old entries into it */
 			p = malloc((size_t)(sizeof(char *) * (cnt + 2)));
 			if (!p)
 				return (-1);
-			bcopy(environ, p, cnt * sizeof(char *));
-			alloced = environ = p;
+			bcopy(*environp, p, cnt * sizeof(char *));
+			alloced = *environp = p;
 		}
-		environ[cnt + 1] = NULL;
+		(*environp)[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))))
-		return (-1);
-	for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
-	for (*c++ = '='; (*c++ = *value++); );
+	/* For non Unix03, or UnixO3 setenv(), we make a copy of the user's
+	 * strings.  For Unix03 putenv(), we put the string directly in
+	 * the environment. */
+	if (copy) {
+		for (c = (char *)name; *c && *c != '='; ++c);	/* no `=' in name */
+		if (!((*environp)[offset] =			/* name + `=' + value */
+		    malloc((size_t)((int)(c - name) + strlen(value) + 2))))
+			return (-1);
+		for (c = (*environp)[offset]; (*c = *name++) && *c != '='; ++c);
+		for (*c++ = '='; (*c++ = *value++); );
+	} else
+		(*environp)[offset] = name;
 	return (0);
 }
+#endif /* !BUILD_VARIANT */
+
+/*
+ * setenv --
+ *	Set the value of the environmental variable "name" to be
+ *	"value".  If rewrite is set, replace any current value.
+ */
+int
+setenv(name, value, rewrite)
+	const char *name;
+	const char *value;
+	int rewrite;
+{
+	/* no null ptr or empty str */
+	if(name == NULL || *name == 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+#if __DARWIN_UNIX03
+	/* no '=' in name */
+	if (strchr(name, '=')) {
+		errno = EINVAL;
+		return (-1);
+	}
+#endif /* __DARWIN_UNIX03 */
+
+	if (*value == '=')			/* no `=' in value */
+		++value;
+	return (__setenv(name, value, rewrite, 1));
+}
 
 /*
  * unsetenv(name) --
  *	Delete environmental variable "name".
  */
+#if __DARWIN_UNIX03
+int
+#else /* !__DARWIN_UNIX03 */
 void
+#endif /* __DARWIN_UNIX03 */
 unsetenv(name)
 	const char *name;
 {
-	extern char **environ;
+	char **environ = *_NSGetEnviron();
 	char **p;
 	int offset;
 
+#if __DARWIN_UNIX03
+	/* no null ptr or empty str */
+	if(name == NULL || *name == 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	/* no '=' in name */
+	if (strchr(name, '=')) {
+		errno = EINVAL;
+		return (-1);
+	}
+#else /* !__DARWIN_UNIX03 */
+	/* no null ptr or empty str */
+	if(name == NULL || *name == 0)
+		return;
+#endif /* __DARWIN_UNIX03 */
 	while (__findenv(name, &offset))	/* if set multiple times */
 		for (p = &environ[offset];; ++p)
 			if (!(*p = *(p + 1)))
 				break;
+#if __DARWIN_UNIX03
+	return 0;
+#endif /* __DARWIN_UNIX03 */
 }