diff --git a/libc/Android.mk b/libc/Android.mk index e183fb014..b674adfeb 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -39,7 +39,6 @@ endif libc_common_src_files := \ bionic/arc4random.c \ bionic/bindresvport.c \ - bionic/clearenv.c \ bionic/daemon.c \ bionic/err.c \ bionic/ether_aton.c \ @@ -77,9 +76,6 @@ libc_common_src_files := \ stdio/snprintf.c\ stdio/sprintf.c \ stdlib/atexit.c \ - stdlib/getenv.c \ - stdlib/putenv.c \ - stdlib/setenv.c \ unistd/syslog.c \ # Fortify implementations of libc functions. @@ -112,6 +108,7 @@ libc_bionic_src_files := \ bionic/brk.cpp \ bionic/chmod.cpp \ bionic/chown.cpp \ + bionic/clearenv.cpp \ bionic/clock.cpp \ bionic/clone.cpp \ bionic/cmsg_nxthdr.cpp \ @@ -404,6 +401,8 @@ libc_upstream_openbsd_src_files := \ upstream-openbsd/lib/libc/stdlib/atoi.c \ upstream-openbsd/lib/libc/stdlib/atol.c \ upstream-openbsd/lib/libc/stdlib/atoll.c \ + upstream-openbsd/lib/libc/stdlib/getenv.c \ + upstream-openbsd/lib/libc/stdlib/setenv.c \ upstream-openbsd/lib/libc/stdlib/strtoimax.c \ upstream-openbsd/lib/libc/stdlib/strtol.c \ upstream-openbsd/lib/libc/stdlib/strtoll.c \ diff --git a/libc/bionic/clearenv.c b/libc/bionic/clearenv.cpp similarity index 89% rename from libc/bionic/clearenv.c rename to libc/bionic/clearenv.cpp index 0f6f066cc..c70cc3e1c 100644 --- a/libc/bionic/clearenv.c +++ b/libc/bionic/clearenv.cpp @@ -26,17 +26,15 @@ * SUCH DAMAGE. */ -#include +#include +#include -extern char** environ; - -int clearenv(void) -{ - char **P = environ; - - if (P != NULL) { - for (; *P; ++P) - *P = NULL; +int clearenv() { + char** e = environ; + if (e != NULL) { + for (; *e; ++e) { + *e = NULL; } - return 0; + } + return 0; } diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h index 58538ffc7..6c966f783 100644 --- a/libc/include/stdlib.h +++ b/libc/include/stdlib.h @@ -46,10 +46,10 @@ extern __noreturn void exit(int); extern __noreturn void _Exit(int); extern int atexit(void (*)(void)); -extern char *getenv(const char *); -extern int putenv(const char *); -extern int setenv(const char *, const char *, int); -extern int unsetenv(const char *); +extern char* getenv(const char*); +extern int putenv(char*); +extern int setenv(const char*, const char*, int); +extern int unsetenv(const char*); extern int clearenv(void); extern char* mkdtemp(char*); diff --git a/libc/include/unistd.h b/libc/include/unistd.h index d21f23d3f..6cb36d8f9 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -47,7 +47,8 @@ __BEGIN_DECLS #define SEEK_CUR 1 #define SEEK_END 2 -extern char **environ; +extern char** environ; + extern __noreturn void _exit(int); extern pid_t fork(void); diff --git a/libc/stdlib/putenv.c b/libc/stdlib/putenv.c deleted file mode 100644 index 54482f6a1..000000000 --- a/libc/stdlib/putenv.c +++ /dev/null @@ -1,50 +0,0 @@ -/* $OpenBSD: putenv.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */ -/*- - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include - -int -putenv(const char *str) -{ - char *p, *equal; - int rval; - - if ((p = strdup(str)) == NULL) - return (-1); - if ((equal = strchr(p, '=')) == NULL) { - (void)free(p); - return (-1); - } - *equal = '\0'; - rval = setenv(p, equal + 1, 1); - (void)free(p); - return (rval); -} diff --git a/libc/stdlib/getenv.c b/libc/upstream-openbsd/lib/libc/stdlib/getenv.c similarity index 83% rename from libc/stdlib/getenv.c rename to libc/upstream-openbsd/lib/libc/stdlib/getenv.c index 72367b34e..fd8482e9e 100644 --- a/libc/stdlib/getenv.c +++ b/libc/upstream-openbsd/lib/libc/stdlib/getenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getenv.c,v 1.8 2005/08/08 08:05:36 espie Exp $ */ +/* $OpenBSD: getenv.c,v 1.10 2010/08/23 22:31:50 millert Exp $ */ /* * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. @@ -31,31 +31,29 @@ #include #include -char *__findenv(const char *name, int *offset); +char *__findenv(const char *name, int len, int *offset); /* * __findenv -- * Returns pointer to value associated with name, if any, else NULL. + * Starts searching within the environmental array at offset. * Sets offset to be the offset of the name/value combination in the - * environmental array, for use by setenv(3) and unsetenv(3). + * environmental array, for use by putenv(3), setenv(3) and unsetenv(3). * Explicitly removes '=' in argument name. * * This routine *should* be a static; don't use it. */ char * -__findenv(const char *name, int *offset) +__findenv(const char *name, int len, int *offset) { extern char **environ; - int len, i; + int i; const char *np; char **p, *cp; if (name == NULL || environ == NULL) return (NULL); - for (np = name; *np && *np != '='; ++np) - ; - len = np - name; - for (p = environ; (cp = *p) != NULL; ++p) { + for (p = environ + *offset; (cp = *p) != NULL; ++p) { for (np = name, i = len; i && *cp; i--) if (*cp++ != *np++) break; @@ -74,7 +72,10 @@ __findenv(const char *name, int *offset) char * getenv(const char *name) { - int offset; + int offset = 0; + const char *np; - return (__findenv(name, &offset)); + for (np = name; *np && *np != '='; ++np) + ; + return (__findenv(name, (int)(np - name), &offset)); } diff --git a/libc/stdlib/setenv.c b/libc/upstream-openbsd/lib/libc/stdlib/setenv.c similarity index 54% rename from libc/stdlib/setenv.c rename to libc/upstream-openbsd/lib/libc/stdlib/setenv.c index 856db5e93..9060fdba8 100644 --- a/libc/stdlib/setenv.c +++ b/libc/upstream-openbsd/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.14 2012/09/23 16:08:04 jeremy Exp $ */ /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. @@ -28,12 +28,59 @@ * SUCH DAMAGE. */ +#include #include #include -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 = 0; + + 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; + /* could be set multiple times */ + while (__findenv(str, (int)(cp - str), &offset)) { + for (P = &environ[offset];; ++P) + if (!(*P = *(P + 1))) + break; + } + 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,29 +90,46 @@ extern char **environ; int setenv(const char *name, const char *value, int rewrite) { - static char **lastenv; /* last value of environ */ - char *C; - int l_value, offset; + char *C, **P; + const char *np; + int l_value, offset = 0; + + if (!name || !*name) { + errno = EINVAL; + return (-1); + } + for (np = name; *np && *np != '='; ++np) + ; + if (*np) { + errno = EINVAL; + return (-1); /* has `=' in name */ + } - if (*value == '=') /* no `=' in value */ - ++value; l_value = strlen(value); - if ((C = __findenv(name, &offset))) { /* find if already exists */ + if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) { + int tmpoff = offset + 1; if (!rewrite) return (0); - if ((int)strlen(C) >= l_value) { /* old larger; copy over */ +#if 0 /* XXX - existing entry may not be writable */ + if (strlen(C) >= l_value) { /* old larger; copy over */ while ((*C++ = *value++)) ; return (0); } +#endif + /* could be set multiple times */ + while (__findenv(name, (int)(np - name), &tmpoff)) { + for (P = &environ[tmpoff];; ++P) + if (!(*P = *(P + 1))) + break; + } } else { /* create new slot */ size_t cnt; - char **P; for (P = environ; *P != NULL; P++) ; cnt = P - environ; - P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); + P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); if (!P) return (-1); if (lastenv != environ) @@ -74,10 +138,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) ; @@ -94,12 +156,25 @@ int unsetenv(const char *name) { char **P; - int offset; + const char *np; + int offset = 0; - while (__findenv(name, &offset)) /* if set multiple times */ + if (!name || !*name) { + errno = EINVAL; + return (-1); + } + 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; + } + return (0); }