Back to index

glibc  2.9
getenv.c
Go to the documentation of this file.
00001 /* Copyright (C) 1991,92,94,96,98,99,2002,2005 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <endian.h>
00020 #include <errno.h>
00021 #include <stdint.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <unistd.h>
00025 
00026 
00027 /* Return the value of the environment variable NAME.  This implementation
00028    is tuned a bit in that it assumes no environment variable has an empty
00029    name which of course should always be true.  We have a special case for
00030    one character names so that for the general case we can assume at least
00031    two characters which we can access.  By doing this we can avoid using the
00032    `strncmp' most of the time.  */
00033 char *
00034 getenv (name)
00035      const char *name;
00036 {
00037   size_t len = strlen (name);
00038   char **ep;
00039   uint16_t name_start;
00040 
00041   if (__environ == NULL || name[0] == '\0')
00042     return NULL;
00043 
00044   if (name[1] == '\0')
00045     {
00046       /* The name of the variable consists of only one character.  Therefore
00047         the first two characters of the environment entry are this character
00048         and a '=' character.  */
00049 #if __BYTE_ORDER == __LITTLE_ENDIAN || !_STRING_ARCH_unaligned
00050       name_start = ('=' << 8) | *(const unsigned char *) name;
00051 #else
00052 # if __BYTE_ORDER == __BIG_ENDIAN
00053       name_start = '=' | ((*(const unsigned char *) name) << 8);
00054 # else
00055  #error "Funny byte order."
00056 # endif
00057 #endif
00058       for (ep = __environ; *ep != NULL; ++ep)
00059        {
00060 #if _STRING_ARCH_unaligned
00061          uint16_t ep_start = *(uint16_t *) *ep;
00062 #else
00063          uint16_t ep_start = (((unsigned char *) *ep)[0]
00064                             | (((unsigned char *) *ep)[1] << 8));
00065 #endif
00066          if (name_start == ep_start)
00067            return &(*ep)[2];
00068        }
00069     }
00070   else
00071     {
00072 #if _STRING_ARCH_unaligned
00073       name_start = *(const uint16_t *) name;
00074 #else
00075       name_start = (((const unsigned char *) name)[0]
00076                   | (((const unsigned char *) name)[1] << 8));
00077 #endif
00078       len -= 2;
00079       name += 2;
00080 
00081       for (ep = __environ; *ep != NULL; ++ep)
00082        {
00083 #if _STRING_ARCH_unaligned
00084          uint16_t ep_start = *(uint16_t *) *ep;
00085 #else
00086          uint16_t ep_start = (((unsigned char *) *ep)[0]
00087                             | (((unsigned char *) *ep)[1] << 8));
00088 #endif
00089 
00090          if (name_start == ep_start && !strncmp (*ep + 2, name, len)
00091              && (*ep)[len + 2] == '=')
00092            return &(*ep)[len + 3];
00093        }
00094     }
00095 
00096   return NULL;
00097 }
00098 libc_hidden_def (getenv)