From ea278354429c511389edab51dcb588343652601d Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Thu, 5 Mar 1998 14:03:24 +0000 Subject: [PATCH] Update. 1998-03-05 Ulrich Drepper * elf/rtld.c: Speed up processing of environment variables. Do only one run on the environment by avoiding to call getenv. * sysdeps/generic/dl-sysdep.c (_dl_next_ld_env_entry): New function. Used by patch above. 1998-03-05 10:25 Ulrich Drepper * nss/getXXbyYY_r.c: Don't try to contact nscd every time when it failed. Only do this every NSS_NSCD_RETRY times. * nss/nsswitch.c: Define __nss_nscd_not_available, used by above change. * nscd/nscd_getgr_r.c (__nscd_getgr_r): Return 2 if contacting the daemon failed. * nscd/nscd_getpw_r.c (__nscd_getpw_r): Likewise. 1998-03-05 Ulrich Drepper * nss/nsswitch.c (nss_lookup_function): Don't modify errno if NSS module cannot be found. Reported by Andreas Jaeger. 1998-03-05 11:40 Franz Sirl * nscd/nscd_getgr_r.c: Change char to int to avoid compiler warning on platforms which default to unsigned chars. * nscd/nscd_getpw_r.c: Likewise. * sysdeps/unix/sysv/linux/powerpc/sysdep.h: Undefine L before defining it. 1998-03-05 Andreas Jaeger * elf/Makefile (install-bin): Change = to += for sprof to install ldd also. --- ChangeLog | 35 ++++++++ NEWS | 7 +- README.template | 6 +- elf/Makefile | 2 +- elf/rtld.c | 141 +++++++++++++++++++++++-------- manual/maint.texi | 2 +- nscd/nscd_getgr_r.c | 5 +- nscd/nscd_getpw_r.c | 5 +- nss/getXXbyYY_r.c | 26 ++++-- nss/nsswitch.c | 12 ++- sysdeps/generic/dl-sysdep.c | 26 ++++++ sysdeps/unix/sysv/linux/powerpc/sysdep.h | 3 +- 12 files changed, 214 insertions(+), 56 deletions(-) diff --git a/ChangeLog b/ChangeLog index dfa32c7..eae4f20 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +1998-03-05 Ulrich Drepper + + * elf/rtld.c: Speed up processing of environment variables. Do + only one run on the environment by avoiding to call getenv. + * sysdeps/generic/dl-sysdep.c (_dl_next_ld_env_entry): New + function. Used by patch above. + +1998-03-05 10:25 Ulrich Drepper + + * nss/getXXbyYY_r.c: Don't try to contact nscd every time when it + failed. Only do this every NSS_NSCD_RETRY times. + * nss/nsswitch.c: Define __nss_nscd_not_available, used by above + change. + * nscd/nscd_getgr_r.c (__nscd_getgr_r): Return 2 if contacting the + daemon failed. + * nscd/nscd_getpw_r.c (__nscd_getpw_r): Likewise. + +1998-03-05 Ulrich Drepper + + * nss/nsswitch.c (nss_lookup_function): Don't modify errno if NSS + module cannot be found. Reported by Andreas Jaeger. + +1998-03-05 11:40 Franz Sirl + + * nscd/nscd_getgr_r.c: Change char to int to avoid compiler warning + on platforms which default to unsigned chars. + * nscd/nscd_getpw_r.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/sysdep.h: Undefine L before + defining it. + +1998-03-05 Andreas Jaeger + + * elf/Makefile (install-bin): Change = to += for sprof to install + ldd also. + 1998-03-04 16:12 H.J. Lu * libio/strops.c (_IO_str_seekoff): Handle MODE == 0. diff --git a/NEWS b/NEWS index 5da5bfc..9a86da0 100644 --- a/NEWS +++ b/NEWS @@ -54,6 +54,11 @@ Version 2.1 * The localedata addon is now part of glibc. * An implementation of profiling shared libraries was added by Ulrich Drepper. + +* Thorsten Kukuk provided an implementation for a caching daemon for NSS + (nscd). + +* Tim Waugh provided an implementation of the POSIX.2 wordexp function family. Version 2.0.5 @@ -503,7 +508,7 @@ Version 1.06 `make dvi' will produce a DVI file of the printed manual. `make info' will produce Info files that you can read on line using C-h i in Emacs or the `info' program. - Please send comments on the manual to bug-glibc-manual@prep.ai.mit.edu. + Please send comments on the manual to bug-glibc-manual@gnu.org. * The library now supports SVR4 on i386s (i386-unknown-sysv4). diff --git a/README.template b/README.template index 5c7484b..0850475 100644 --- a/README.template +++ b/README.template @@ -73,9 +73,9 @@ GNU libc at http://www.gnu.org/software/libc/libc.html. The GNU C Library is completely documented by the Texinfo manual found in the `manual/' subdirectory. The manual is still being updated and -contains some known errors and omissions; we regret that we do not have -the resources to work on the manual as much as we would like. Please -send comments on the manual to , and +contains some known errors and omissions; we regret that we do not +have the resources to work on the manual as much as we would like. +Please send comments on the manual to , and not to the library bug-reporting address. The file NOTES contains a description of the feature-test macros used diff --git a/elf/Makefile b/elf/Makefile index 0b37b1f..aff64e4 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -61,7 +61,7 @@ generated += ldd endif others = sprof -install-bin = sprof +install-bin += sprof ifeq (yes,$(has-ldconfig)) others-static += ldconfig diff --git a/elf/rtld.c b/elf/rtld.c index 95830c5..2707da6 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -53,6 +53,15 @@ static void print_unresolved (int errcode, const char *objname, static void print_missing_version (int errcode, const char *objname, const char *errsting); + +/* This is a list of all the modes the dynamic loader can be in. */ +enum mode { normal, list, verify, trace }; + +/* Process all environments variables the dynamic linker must recognize. + Since all of them start with `LD_' we are a bit smarter while finding + all the entries. */ +static void process_envvars (enum mode *modep, int *lazyp); + int _dl_argc; char **_dl_argv; const char *_dl_rpath; @@ -147,7 +156,6 @@ _dl_start (void *arg) return _dl_sysdep_start (arg, &dl_main); } - /* Now life is peachy; we can do all normal operations. On to the real work. */ @@ -260,7 +268,7 @@ dl_main (const ElfW(Phdr) *phdr, const ElfW(Phdr) *ph; struct link_map *main_map; int lazy; - enum { normal, list, verify, trace } mode; + enum mode mode; struct link_map **preloads; unsigned int npreloads; const char *preloadlist; @@ -268,41 +276,8 @@ dl_main (const ElfW(Phdr) *phdr, char *file; int has_interp = 0; - /* Test whether we want to see the content of the auxiliary array passed - up from the kernel. */ - if (getenv ("LD_SHOW_AUXV") != NULL) - _dl_show_auxv (); - - mode = getenv ("LD_TRACE_LOADED_OBJECTS") != NULL ? trace : normal; - _dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1; - - /* LAZY is determined by the environment variable LD_WARN and - LD_BIND_NOW if we trace the binary. */ - if (mode == trace) - lazy = (_dl_verbose - ? (*(getenv ("LD_BIND_NOW") ?: "") == '\0' ? 1 : 0) : -1); - else - lazy = !__libc_enable_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0'; - - /* See whether we want to use profiling. */ - _dl_profile = getenv ("LD_PROFILE"); - if (_dl_profile != NULL) - if (_dl_profile[0] == '\0') - /* An empty string is of not much help. Disable profiling. */ - _dl_profile = NULL; - else - { - /* OK, we have the name of a shared object we want to - profile. It's up to the user to provide a good name, it - must match the file name or soname of one of the loaded - objects. Now let's see where we are supposed to place the - result. */ - _dl_profile_output = getenv ("LD_PROFILE_OUTPUT"); - - if (_dl_profile_output == NULL || _dl_profile_output[0] == '\0') - /* This is the default place. */ - _dl_profile_output = "/var/tmp"; - } + /* Process the environment variable which control the behaviour. */ + process_envvars (&mode, &lazy); /* Set up a flag which tells we are just starting. */ _dl_starting_up = 1; @@ -930,3 +905,95 @@ print_missing_version (int errcode __attribute__ ((unused)), _dl_sysdep_error (_dl_argv[0] ?: "", ": ", objname, ": ", errstring, "\n", NULL); } + +/* Process all environments variables the dynamic linker must recognize. + Since all of them start with `LD_' we are a bit smarter while finding + all the entries. */ +static void +process_envvars (enum mode *modep, int *lazyp) +{ + char **runp = NULL; + char *envline; + enum mode mode = normal; + int bind_now = 0; + + /* This is the default place for profiling data file. */ + _dl_profile_output = "/var/tmp"; + + while ((envline = _dl_next_ld_env_entry (&runp)) != NULL) + { + int result; + + /* Do we bind early? */ + result = strncmp (&envline[3], "BIND_NOW=", 9); + if (result == 0) + { + bind_now = 1; + continue; + } + if (result < 0) + continue; + + /* Which shared object shall be profiled. */ + result = strncmp (&envline[3], "PROFILE=", 8); + if (result == 0) + { + _dl_profile = &envline[11]; + if (*_dl_profile == '\0') + _dl_profile = NULL; + continue; + } + if (result < 0) + continue; + + /* Where to place the profiling data file. */ + result = strncmp (&envline[3], "PROFILE_OUTPUT=", 15); + if (result == 0) + { + _dl_profile_output = &envline[18]; + if (*_dl_profile_output == '\0') + _dl_profile_output = "/var/tmp"; + continue; + } + if (result < 0) + continue; + + /* Test whether we want to see the content of the auxiliary + array passed up from the kernel. */ + result = strncmp (&envline[3], "SHOW_AUXV=", 10); + if (result == 0) + { + _dl_show_auxv (); + continue; + } + if (result < 0) + continue; + + /* The mode of the dynamic linker can be set. */ + result = strncmp (&envline[3], "TRACE_LOADED_OBJECTS=", 21); + if (result == 0) + { + mode = trace; + continue; + } + if (result < 0) + continue; + + /* Warning level, verbose or not. */ + result = strncmp (&envline[3], "WARN=", 5); + if (result == 0) + { + _dl_verbose = envline[8] != '\0'; + continue; + } + } + + /* LAZY is determined by the environment variable LD_WARN and + LD_BIND_NOW if we trace the binary. */ + if (mode == trace) + *lazyp = _dl_verbose ? !bind_now : -1; + else + *lazyp = !__libc_enable_secure && !bind_now; + + *modep = mode; +} diff --git a/manual/maint.texi b/manual/maint.texi index 560b04e..6225cb4 100644 --- a/manual/maint.texi +++ b/manual/maint.texi @@ -377,7 +377,7 @@ doesn't tell you, that's a bug in the manual. Report that too! If the function's behavior disagrees with the manual, then either the library or the manual has a bug, so report the disagreement. If you find any errors or omissions in this manual, please report them to the Internet -address @email{bug-glibc-manual@@prep.ai.mit.edu}. +address @email{bug-glibc-manual@@gnu.org}. @node Source Layout @appendixsec Adding New Functions diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c index 596e31f..8129d81 100644 --- a/nscd/nscd_getgr_r.c +++ b/nscd/nscd_getgr_r.c @@ -48,7 +48,7 @@ __nscd_getgrgid_r (gid_t gid, struct group *resultbuf, char *buffer, size_t buflen) { char *p = buffer; - char plen; + int plen; plen = snprintf (buffer, buflen, "%d", gid); if (plen == -1) @@ -98,7 +98,8 @@ __nscd_getgr_r (const char *key, request_type type, struct group *resultbuf, ssize_t nbytes; if (sock == -1) - return 1; + /* Returning two signals that contacting the daemon failed. */ + return 2; req.version = NSCD_VERSION; req.type = type; diff --git a/nscd/nscd_getpw_r.c b/nscd/nscd_getpw_r.c index 4fc78e1..4420b80 100644 --- a/nscd/nscd_getpw_r.c +++ b/nscd/nscd_getpw_r.c @@ -48,7 +48,7 @@ __nscd_getpwuid_r (uid_t uid, struct passwd *resultbuf, char *buffer, size_t buflen) { char *p = buffer; - char plen; + int plen; plen = snprintf (buffer, buflen, "%d", uid); if (plen == -1) @@ -98,7 +98,8 @@ __nscd_getpw_r (const char *key, request_type type, struct passwd *resultbuf, ssize_t nbytes; if (sock == -1) - return 1; + /* Returning two signals that contacting the daemon failed. */ + return 2; req.version = NSCD_VERSION; req.type = type; diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c index a4dc001..8a38b0d 100644 --- a/nss/getXXbyYY_r.c +++ b/nss/getXXbyYY_r.c @@ -88,6 +88,12 @@ extern struct __res_state _res; /* The lookup function for the first entry of this service. */ extern int DB_LOOKUP_FCT (service_user **nip, const char *name, void **fctp); +/* Nonzero if the NSCD is not available. This variable will be increased + whenever we try to use the NSCD but see it is not avilable. So we + can recheck the presence every once in a while. */ +extern int __nss_nscd_not_available; +/* Interval in which we transfer retry to contact the NSCD. */ +#define NSS_NSCD_RETRY 100 int @@ -111,11 +117,21 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer, #endif #ifdef USE_NSCD - nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen H_ERRNO_VAR); - if (nscd_status < 1) + if (__nss_nscd_not_available && ++__nss_nscd_not_available > NSS_NSCD_RETRY) + __nss_nscd_not_available = 0; + + if (!__nss_nscd_not_available) { - *result = nscd_status == 0 ? resbuf : NULL; - return nscd_status; + nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen + H_ERRNO_VAR); + if (nscd_status < 1) + { + *result = nscd_status == 0 ? resbuf : NULL; + return nscd_status; + } + if (nscd_status == 2) + /* This return value indicates that contacting the server failed. */ + __nss_nscd_not_available = 1; } #endif @@ -152,7 +168,7 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer, status = (*fct) (ADD_VARIABLES, resbuf, buffer, buflen, __errno_location () H_ERRNO_VAR); - /* The the status is NSS_STATUS_TRYAGAIN and errno is ERANGE the + /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the provided buffer is too small. In this case we should give the user the possibility to enlarge the buffer and we should not simply go on with the next service (even if the TRYAGAIN diff --git a/nss/nsswitch.c b/nss/nsswitch.c index 65da26b..2a3e44a 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -69,6 +69,9 @@ static struct __libc_lock_define_initialized (static, lock) +/* Nonzero if no NSCD is available. */ +int __nss_nscd_not_available; + #if !defined DO_STATIC_NSS || defined PIC /* String with revision number of the shared object files. */ static const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15; @@ -380,7 +383,7 @@ nss_lookup_function (service_user *ni, const char *fct_name) /* Load the shared library. */ size_t shlen = (7 + strlen (ni->library->name) + 3 + strlen (__nss_shlib_revision) + 1); - + int saved_errno = errno; struct do_open_args args; args.shlib_name = __alloca (shlen); args.ni = ni; @@ -393,8 +396,11 @@ nss_lookup_function (service_user *ni, const char *fct_name) __nss_shlib_revision); if (nss_dlerror_run (do_open, &args) != 0) - /* Failed to load the library. */ - ni->library->lib_handle = (void *) -1l; + { + /* Failed to load the library. */ + ni->library->lib_handle = (void *) -1l; + __set_errno (saved_errno); + } } if (ni->library->lib_handle == (void *) -1l) diff --git a/sysdeps/generic/dl-sysdep.c b/sysdeps/generic/dl-sysdep.c index b007aa6..21b470c 100644 --- a/sysdeps/generic/dl-sysdep.c +++ b/sysdeps/generic/dl-sysdep.c @@ -243,3 +243,29 @@ _dl_show_auxv (void) break; } } + +/* Walk through the environment of the process and return all entries + starting with `LD_'. */ +char * +_dl_next_ld_env_entry (char ***position) +{ + char **current = *position; + char *result = NULL; + + if (current == NULL) + /* We start over. */ + current = _environ; + + while (result == NULL && *current != NULL) + { + if ((*current)[0] == 'L' && (*current)[1] == 'D' && (*current)[2] == '_') + result = *current; + + ++current; + } + + /* Save current position for next visit. */ + *position = current; + + return result; +} diff --git a/sysdeps/unix/sysv/linux/powerpc/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/sysdep.h index 944793d..c75e2a8 100644 --- a/sysdeps/unix/sysv/linux/powerpc/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/sysdep.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1992, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1992, 1997, 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 @@ -138,6 +138,7 @@ END (name) /* Local labels stripped out by the linker. */ +#undef L #define L(x) .L##x #endif /* ASSEMBLER */ -- 2.7.4