This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: setenv problems
Hi,
[ skipped ]
>> http://www.opengroup.org/onlinepubs/000095399/functions/setenv.html
>> says that setenv() should fail with EINVAL if name contains an equal
>> sign.
> Ok, also considering the linux man pages state the same and the function
> isn't specified by ANSI. Would you like to try your hand at a patch?
[ skipped ]
Here is the patch, attached. Let me know if there are any questions/comments.
Tested with this:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
static char * _getenv(char *);
char * _getenv(char * var) {
char * aux = getenv(var);
if (aux) { return aux; }
return "(NULL)";
}
int main(int argc, char ** argv) {
printf("getenv('nada' = %s\n", getenv("nada"));
printf("getenv('TMP') = %s\n", getenv("TMP"));
printf("getenv('TMP=XA') = %s\n", getenv("TMP=XA"));
printf("setenv('PAWEL','DATA') = %d\n", setenv("PAWEL", "DATA", 1));
printf("getenv('PAWEL') = %s\n", getenv("PAWEL"));
errno = 0;
printf("setenv('PAWE=L', 'DATA') = %d\n", setenv("PAWE=L", "DATA", 1));
fflush(stdout);
perror("setenv()");
printf("setenv('LOOK','=FEEL') = %d\n", setenv("LOOK", "=FEEL", 1));
printf("unsetenv('PAWEL') = %d\n", unsetenv("PAWEL"));
printf("getenv('LOOK') = %s\n", getenv("LOOK"));
printf("getenv('PAWEL') = %s\n", getenv("PAWEL"));
printf("setenv('LOOK', 'JAM', nod) = %d\n", setenv("LOOK", "JAM", 0));
printf("getenv('LOOK') = %s\n", getenv("LOOK"));
printf("setenv('LOOK', 'MONKEY', od) = %d\n", setenv("LOOK", "MONKEY", 1));
printf("getenv('LOOK') = %s\n", getenv("LOOK"));
errno = 0;
printf("unsetenv('=') = %d\n", unsetenv("="));
perror("unsetenv()");
errno = 0;
printf("unsetenv('KARA') = %d\n", unsetenv("KARA"));
perror("unsetenv()");
return 0;
}
--
With best of best regards
Pawel S. Veselov
Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/newlib/ChangeLog,v
retrieving revision 1.1193
diff -u -p -r1.1193 ChangeLog
--- ChangeLog 19 Sep 2008 16:11:35 -0000 1.1193
+++ ChangeLog 23 Sep 2008 17:14:04 -0000
@@ -1,3 +1,17 @@
+2008-09-23 Pawel Veselov <pawel.veselov@gmail.com>
+ Fixed setenv/getenv/unsetenv to be OpenGroup compliant:
+ * libc/include/stdlib.h (unsetenv, _unsetenv_r): redefine with integer
+ return types.
+ * libc/stdlib/getenv_r.c (_findenv_r): Do no special processing with
+ names that contain equal chars
+ * libc/stdlib/setenv.c: redefine _unsetenv_r as returning int
+ * libc/stdlib/setenv_r.c (_setenv_r): return -1 and set errno to
+ EINVAL if name contains an equal char. Do not remove any equal chars
+ from the value.
+ (_unsetenv_r): redeclare to return int. Return -1 and set EINVAL
+ if name contains equal char. Return -1 if no variable(s) were found.
+ Return 0 otherwise.
+
2008-09-19 Eric Blake <ebb9@byu.net>
Supply missing POSIX errno values.
Index: libc/include/stdlib.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/stdlib.h,v
retrieving revision 1.26
diff -u -p -r1.26 stdlib.h
--- libc/include/stdlib.h 5 Dec 2005 22:15:21 -0000 1.26
+++ libc/include/stdlib.h 23 Sep 2008 17:14:04 -0000
@@ -174,8 +174,8 @@ unsigned long long _EXFUN(_strtoull_r,(s
#ifndef __CYGWIN__
_VOID _EXFUN(cfree,(_PTR));
-void _EXFUN(unsetenv,(const char *__string));
-void _EXFUN(_unsetenv_r,(struct _reent *, const char *__string));
+int _EXFUN(unsetenv,(const char *__string));
+int _EXFUN(_unsetenv_r,(struct _reent *, const char *__string));
#endif
#endif /* ! __STRICT_ANSI__ */
Index: libc/stdlib/getenv_r.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/getenv_r.c,v
retrieving revision 1.5
diff -u -p -r1.5 getenv_r.c
--- libc/stdlib/getenv_r.c 30 Apr 2002 18:23:38 -0000 1.5
+++ libc/stdlib/getenv_r.c 23 Sep 2008 17:14:05 -0000
@@ -74,7 +74,6 @@ static char ***p_environ = &environ;
* 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).
- * Explicitly removes '=' in argument name.
*
* This routine *should* be a static; don't use it.
*/
@@ -99,13 +98,8 @@ _DEFUN (_findenv_r, (reent_ptr, name, of
return NULL;
}
- c = name;
- len = 0;
- while (*c && *c != '=')
- {
- c++;
- len++;
- }
+ len = strlen(name);
+ c = name + len;
for (p = *p_environ; *p; ++p)
if (!strncmp (*p, name, len))
Index: libc/stdlib/setenv.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/setenv.c,v
retrieving revision 1.2
diff -u -p -r1.2 setenv.c
--- libc/stdlib/setenv.c 22 Feb 2001 22:12:40 -0000 1.2
+++ libc/stdlib/setenv.c 23 Sep 2008 17:14:05 -0000
@@ -23,7 +23,7 @@
#include <stdlib.h>
#include <string.h>
-extern void _unsetenv_r _PARAMS ((struct _reent *, const char *));
+extern int _unsetenv_r _PARAMS ((struct _reent *, const char *));
/*
* setenv --
@@ -44,11 +44,11 @@ _DEFUN (setenv, (name, value, rewrite),
* unsetenv(name) --
* Delete environmental variable "name".
*/
-void
+int
_DEFUN (unsetenv, (name),
_CONST char *name)
{
- _unsetenv_r (_REENT, name);
+ return _unsetenv_r (_REENT, name);
}
#endif /* !_REENT_ONLY */
Index: libc/stdlib/setenv_r.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/setenv_r.c,v
retrieving revision 1.6
diff -u -p -r1.6 setenv_r.c
--- libc/stdlib/setenv_r.c 20 Jan 2005 17:31:04 -0000 1.6
+++ libc/stdlib/setenv_r.c 23 Sep 2008 17:14:05 -0000
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
+#include <errno.h>
#include "envlock.h"
extern char **environ;
@@ -43,6 +44,8 @@ extern char *_findenv_r _PARAMS ((struct
* _setenv_r --
* Set the value of the environmental variable "name" to be
* "value". If rewrite is set, replace any current value.
+ * If "name" contains equal sign, -1 is returned, and errno is
+ * set to EINVAL;
*/
int
@@ -56,10 +59,14 @@ _DEFUN (_setenv_r, (reent_ptr, name, val
register char *C;
int l_value, offset;
+ if (strchr(name, '='))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
ENV_LOCK;
- if (*value == '=') /* no `=' in value */
- ++value;
l_value = strlen (value);
if ((C = _findenv_r (reent_ptr, name, &offset)))
{ /* find if already exists */
@@ -132,20 +139,33 @@ _DEFUN (_setenv_r, (reent_ptr, name, val
* _unsetenv_r(name) --
* Delete environmental variable "name".
*/
-void
+int
_DEFUN (_unsetenv_r, (reent_ptr, name),
struct _reent *reent_ptr _AND
_CONST char *name)
{
register char **P;
int offset;
+ int rc;
+
+ if (strchr(name, '='))
+ {
+ errno = EINVAL;
+ return -1;
+ }
ENV_LOCK;
+ rc = -1;
+
while (_findenv_r (reent_ptr, name, &offset)) /* if set multiple times */
- for (P = &(*p_environ)[offset];; ++P)
- if (!(*P = *(P + 1)))
- break;
+ {
+ rc = 0;
+ for (P = &(*p_environ)[offset];; ++P)
+ if (!(*P = *(P + 1)))
+ break;
+ }
ENV_UNLOCK;
+ return (rc);
}