diff options
-rw-r--r-- | Makefile.help | 16 | ||||
-rw-r--r-- | Makefile.in | 3 | ||||
-rw-r--r-- | Rules.mak | 1 | ||||
-rw-r--r-- | libc/stdlib/setenv.c | 225 | ||||
-rw-r--r-- | libc/string/i386/memcpy.c | 29 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/brk.c | 32 |
6 files changed, 170 insertions, 136 deletions
diff --git a/Makefile.help b/Makefile.help index b8d2edc3c..a2087164b 100644 --- a/Makefile.help +++ b/Makefile.help @@ -14,6 +14,9 @@ help: @echo 'Build:' @echo ' all - libraries and generated headers' @echo ' pregen - generate headers' + @echo ' utils - build target utilities' + @echo ' (readelf, ldd, ldconfig, locale, iconv)' + @echo ' hostutils - build host utilities (see utils)' @echo @echo 'Configuration:' @echo ' allnoconfig - disable all symbols in .config' @@ -30,6 +33,8 @@ help: @echo ' install_runtime - install the libraries' @echo ' install_dev - install all headers and static libs' @echo ' install_headers - install headers excluding generated ones' + @echo ' install_utils - install target utilities' + @echo ' install_hostutils - install host utilities' @echo @echo 'Development:' @echo ' check - run testsuite' @@ -37,9 +42,18 @@ help: @echo ' release - create a distribution tarball' @echo @echo 'Environment variables:' - @echo ' - Quiet build' + @echo ' V="" - Quiet build (default)' @echo ' V=1 - Verbose build' @echo ' V=2 - Very verbose build' @echo ' CROSS= - Override CROSS_COMPILER_PREFIX from .config' @echo ' SHELL= - Shell to use for make' @echo ' CONFIG_SHELL= - Shell to use for menuconfig' + @echo + @echo ' PREFIX= - Prepended prefix' + @echo ' RUNTIME_PREFIX= - Prefix for the libdir containing shared objects' + @echo ' (usually "/")' + @echo ' DEVEL_PREFIX= - Prefix for the libdir containing static objects' + @echo ' and the include dir (usually "/usr")' + @echo ' SHARED_LIB_LOADER_PREFIX= - Directory where the shared loader resides.' + @echo ' (usually "/lib")' + diff --git a/Makefile.in b/Makefile.in index 968021935..30d7ffc40 100644 --- a/Makefile.in +++ b/Makefile.in @@ -466,6 +466,9 @@ utils: install_utils: utils $(MAKE) CROSS="$(CROSS)" CC="$(CC)" -C utils utils_install +install_hostutils: hostutils + $(MAKE) CROSS="$(CROSS)" CC="$(CC)" -C utils utils_install DOTHOST=.host + endif # ifeq ($(HAVE_DOT_CONFIG),y) include/bits include/config: @@ -528,7 +528,6 @@ endif LDFLAGS:=$(LDFLAGS_NOSTRIP) -Wl,-z,defs ifeq ($(DODEBUG),y) -#CFLAGS += -g3 CFLAGS += -O0 -g3 -DDEBUG else CFLAGS += $(OPTIMIZATION) $(XARCH_CFLAGS) -DNDEBUG diff --git a/libc/stdlib/setenv.c b/libc/stdlib/setenv.c index cf10804ec..6598a6c52 100644 --- a/libc/stdlib/setenv.c +++ b/libc/stdlib/setenv.c @@ -46,116 +46,109 @@ static char **last_environ; is then placed in the environment, while the argument of `putenv' must be used directly. This is all complicated by the fact that we try to reuse values once generated for a `setenv' call since we can never - free the strings. */ -int __add_to_environ (const char *name, const char *value, - const char *combined, int replace) attribute_hidden; -int __add_to_environ (const char *name, const char *value, - const char *combined, int replace) + free the strings. [in uclibc, we do not] */ +static int __add_to_environ(const char *name, const char *value, + int replace) { - register char **ep; - register size_t size; - const size_t namelen = strlen (name); - const size_t vallen = value != NULL ? strlen (value) + 1 : 0; - int rv = -1; - - __UCLIBC_MUTEX_LOCK(mylock); - - /* We have to get the pointer now that we have the lock and not earlier - since another thread might have created a new environment. */ - ep = __environ; - - size = 0; - if (ep != NULL) { - for (; *ep != NULL; ++ep) { - if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') - break; - else - ++size; - } - } - - if (ep == NULL || *ep == NULL) { - char **new_environ; - - /* We allocated this space; we can extend it. */ - new_environ = (char **) realloc (last_environ, (size + 2) * sizeof (char *)); - if (new_environ == NULL) { - goto DONE; - } - - /* If the whole entry is given add it. */ - if (combined != NULL) { - /* We must not add the string to the search tree since it belongs - to the user. */ - new_environ[size] = (char *) combined; - } else { - /* See whether the value is already known. */ - new_environ[size] = (char *) malloc (namelen + 1 + vallen); - if (new_environ[size] == NULL) { - __set_errno (ENOMEM); - goto DONE; + register char **ep; + register size_t size; + char *var_val; + char **new_environ; + /* name may come from putenv() and thus may contain "=VAL" part */ + const size_t namelen = strchrnul(name, '=') - name; + int rv = -1; + + __UCLIBC_MUTEX_LOCK(mylock); + + /* We have to get the pointer now that we have the lock and not earlier + since another thread might have created a new environment. */ + ep = __environ; + + size = 0; + if (ep != NULL) { + while (*ep != NULL) { + if (!strncmp(*ep, name, namelen) && (*ep)[namelen] == '=') { + /* Found */ + if (!replace) + goto DONE_OK; + goto REPLACE; } - - memcpy (new_environ[size], name, namelen); - new_environ[size][namelen] = '='; - memcpy (&new_environ[size][namelen + 1], value, vallen); - } - - if (__environ != last_environ) { - memcpy ((char *) new_environ, (char *) __environ, - size * sizeof (char *)); + ++size; + ++ep; } - - new_environ[size + 1] = NULL; - last_environ = __environ = new_environ; - } else if (replace) { - char *np; - - /* Use the user string if given. */ - if (combined != NULL) { - np = (char *) combined; - } else { - np = malloc (namelen + 1 + vallen); - if (np == NULL) { - goto DONE; - } - memcpy (np, name, namelen); - np[namelen] = '='; - memcpy (&np[namelen + 1], value, vallen); + } + + /* Not found, add at the end */ + + /* We allocated this space; we can extend it. */ + new_environ = realloc(last_environ, (size + 2) * sizeof(char *)); + if (new_environ == NULL) { + __set_errno(ENOMEM); + goto DONE; + } + if (__environ != last_environ) { + memcpy(new_environ, __environ, size * sizeof(char *)); + } + last_environ = __environ = new_environ; + + ep = &new_environ[size]; + /* Ensure env is NULL terminated in case malloc below fails */ + ep[0] = NULL; + ep[1] = NULL; + + REPLACE: + var_val = (char*) name; + /* Build VAR=VAL if we called by setenv, not putenv. */ + if (value != NULL) { + const size_t vallen = strlen(value) + 1; + + var_val = malloc(namelen + 1 + vallen); + if (var_val == NULL) { + __set_errno(ENOMEM); + goto DONE; } - *ep = np; - } + memcpy(var_val, name, namelen); + var_val[namelen] = '='; + memcpy(&var_val[namelen + 1], value, vallen); + } + *ep = var_val; - rv = 0; + DONE_OK: + rv = 0; DONE: - __UCLIBC_MUTEX_UNLOCK(mylock); - return rv; + __UCLIBC_MUTEX_UNLOCK(mylock); + return rv; } /* libc_hidden_proto(setenv) */ -int setenv (const char *name, const char *value, int replace) +int setenv(const char *name, const char *value, int replace) { - return __add_to_environ (name, value, NULL, replace); + /* NB: setenv("VAR", NULL, 1) inserts "VAR=" string */ + return __add_to_environ(name, value ? value : "", replace); } libc_hidden_def(setenv) /* libc_hidden_proto(unsetenv) */ -int unsetenv (const char *name) +int unsetenv(const char *name) { - size_t len; - char **ep; - - if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) { - __set_errno (EINVAL); + const char *eq; + size_t len; + char **ep; + + if (name == NULL || *name == '\0' + || *(eq = strchrnul(name, '=')) == '=' + ) { + __set_errno(EINVAL); return -1; - } - - len = strlen (name); - __UCLIBC_MUTEX_LOCK(mylock); - ep = __environ; - while (*ep != NULL) { - if (!strncmp (*ep, name, len) && (*ep)[len] == '=') { + } + len = eq - name; /* avoiding strlen this way */ + + __UCLIBC_MUTEX_LOCK(mylock); + ep = __environ; + /* NB: clearenv(); unsetenv("foo"); should not segfault */ + if (ep) while (*ep != NULL) { + if (!strncmp(*ep, name, len) && (*ep)[len] == '=') { /* Found it. Remove this pointer by moving later ones back. */ char **dp = ep; do { @@ -165,42 +158,34 @@ int unsetenv (const char *name) } else { ++ep; } - } - __UCLIBC_MUTEX_UNLOCK(mylock); - return 0; + } + __UCLIBC_MUTEX_UNLOCK(mylock); + return 0; } libc_hidden_def(unsetenv) /* The `clearenv' was planned to be added to POSIX.1 but probably never made it. Nevertheless the POSIX.9 standard (POSIX bindings for Fortran 77) requires this function. */ -int clearenv (void) +int clearenv(void) { - __UCLIBC_MUTEX_LOCK(mylock); - if (__environ == last_environ && __environ != NULL) { - /* We allocated this environment so we can free it. */ - free (__environ); - last_environ = NULL; - } - /* Clear the environment pointer removes the whole environment. */ - __environ = NULL; - __UCLIBC_MUTEX_UNLOCK(mylock); - return 0; + __UCLIBC_MUTEX_LOCK(mylock); + /* If we allocated this environment we can free it. + * If we did not allocate this environment, it's NULL already + * and is safe to free(). */ + free(last_environ); + last_environ = NULL; + /* Clearing environ removes the whole environment. */ + __environ = NULL; + __UCLIBC_MUTEX_UNLOCK(mylock); + return 0; } /* Put STRING, which is of the form "NAME=VALUE", in the environment. */ -int putenv (char *string) +int putenv(char *string) { - int result; - const char *const name_end = strchr (string, '='); - - if (name_end != NULL) { - char *name = strndup(string, name_end - string); - result = __add_to_environ (name, NULL, string, 1); - free(name); - return(result); - } - unsetenv (string); - return 0; + if (strchr(string, '=') != NULL) { + return __add_to_environ(string, NULL, 1); + } + return unsetenv(string); } - diff --git a/libc/string/i386/memcpy.c b/libc/string/i386/memcpy.c index 285583f3b..216ddfd1a 100644 --- a/libc/string/i386/memcpy.c +++ b/libc/string/i386/memcpy.c @@ -35,19 +35,20 @@ /* Experimentally off - libc_hidden_proto(memcpy) */ void *memcpy(void * to, const void * from, size_t n) { - int d0, d1, d2; - __asm__ __volatile__( - "rep ; movsl\n\t" - "testb $2,%b4\n\t" - "je 1f\n\t" - "movsw\n" - "1:\ttestb $1,%b4\n\t" - "je 2f\n\t" - "movsb\n" - "2:" - : "=&c" (d0), "=&D" (d1), "=&S" (d2) - :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) - : "memory"); - return (to); + int d0, d1, d2; + __asm__ __volatile__( + " rep; movsl\n" + " movl %4,%%ecx\n" + " andl $3,%%ecx\n" + /* jz is optional. avoids "rep; movsb" with ecx == 0, + * but adds a branch, which is currently (2008) faster */ + " jz 1f\n" + " rep; movsb\n" + "1:\n" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + : "0" (n / 4), "g" (n), "1" ((long)to), "2" ((long)from) + : "memory" + ); + return to; } libc_hidden_def(memcpy) diff --git a/libc/sysdeps/linux/common/brk.c b/libc/sysdeps/linux/common/brk.c new file mode 100644 index 000000000..18836ba59 --- /dev/null +++ b/libc/sysdeps/linux/common/brk.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <errno.h> +#include <unistd.h> +#include <sys/syscall.h> + +libc_hidden_proto(brk) + +#define __NR___syscall_brk __NR_brk +static inline _syscall1(void *, __syscall_brk, void *, end) + +/* This must be initialized data because commons can't have aliases. */ +void * __curbrk attribute_hidden = 0; + +int brk(void *addr) +{ + void *newbrk = __syscall_brk(addr); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) |