diff options
author | Ulrich Drepper <drepper@redhat.com> | 1998-06-08 13:37:25 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1998-06-08 13:37:25 +0000 |
commit | 31f7410f5c413605f039e898151f01231f11efa5 (patch) | |
tree | 3c920d642b67b6d739877f2f22faf2d8b9ee6e84 /sysdeps/generic | |
parent | c0fb8a563c1c49e5fbec9bc22deac618910a3ff4 (diff) | |
download | glibc-31f7410f5c413605f039e898151f01231f11efa5.tar.gz glibc-31f7410f5c413605f039e898151f01231f11efa5.tar.xz glibc-31f7410f5c413605f039e898151f01231f11efa5.zip |
Update.
1998-06-08 13:34 Ulrich Drepper <drepper@cygnus.com> * elf/sprof.c: Implement call graph profiling. * sysdeps/generic/getenv.c: Optimize to use strncmp less often. 1998-06-07 Andreas Jaeger <aj@arthur.rhein-neckar.de> * pwd/fgetpwent_r.c (__fgetpwent_r): Correct buffer overflow fix. * grp/fgetgrent_r.c (__fgetgrent_r): Likewise. * shadow/fgetspent_r.c (__fgetspent_r): Likewise. Noticed by Jake Garver <garver@valkyrie.net>. 1998-06-07 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * libio/genops.c (__underflow): Read character from read pointer as unsigned. (__uflow): Likewise.
Diffstat (limited to 'sysdeps/generic')
-rw-r--r-- | sysdeps/generic/getenv.c | 68 |
1 files changed, 62 insertions, 6 deletions
diff --git a/sysdeps/generic/getenv.c b/sysdeps/generic/getenv.c index 990ddfd93f..b6f405df08 100644 --- a/sysdeps/generic/getenv.c +++ b/sysdeps/generic/getenv.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992, 1994, 1996 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1992, 1994, 1996, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,7 +16,9 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <endian.h> #include <errno.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -25,20 +27,74 @@ #define __environ environ #endif -/* Return the value of the environment variable NAME. */ +/* Return the value of the environment variable NAME. This implementation + is tuned a bit in that it assumes no environment variable has an empty + name which of course should always be true. We have a special case for + one character names so that for the general case we can assume at least + two characters which we can access. By doing this we can avoid using the + `strncmp' most of the time. */ char * getenv (name) const char *name; { const size_t len = strlen (name); char **ep; + uint16_t name_start; - if (__environ == NULL) + if (__environ == NULL || name[0] == '\0') return NULL; - for (ep = __environ; *ep != NULL; ++ep) - if (!strncmp (*ep, name, len) && (*ep)[len] == '=') - return &(*ep)[len + 1]; + if (name[1] == '\0') + { + /* The name of the variable consists of only one character. Therefore + the first two characters of the environment entry are this character + and a '=' character. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + name_start = ('=' << 8) | *(const unsigned char *) name; +#else +# if __BYTE_ORDER == __BIG_ENDIAN + name_start = '=' | ((*(const unsigned char *) name) << 8); +# else + #error "Funny byte order." +# endif +#endif + for (ep = __environ; *ep != NULL; ++ep) + { +#if _STRING_ARCH_unaligned + uint16_t ep_start = *(uint16_t *) *ep; +#else + uint16_t ep_start = (((unsigned char *) *ep)[0] + | (((unsigned char *) *ep)[1] << 8)); +#endif + if (name_start == ep_start) + return &(*ep)[2]; + } + } + else + { +#if _STRING_ARCH_unaligned + name_start = *(const uint16_t *) name; +#else + name_start = (((const unsigned char *) name)[0] + | (((const unsigned char *) name)[1] << 8)); +#endif + len -= 2; + name += 2; + + for (ep = __environ; *ep != NULL; ++ep) + { +#if _STRING_ARCH_unaligned + uint16_t ep_start = *(uint16_t *) *ep; +#else + uint16_t ep_start = (((unsigned char *) *ep)[0] + | (((unsigned char *) *ep)[1] << 8)); +#endif + + if (name_start == ep_start && !strncmp (*ep + 2, name, len) + && (*ep)[len + 2] == '=') + return &(*ep)[len + 3]; + } + } return NULL; } |