X-Git-Url: http://git.csclub.uwaterloo.ca/?p=kopensolaris-gnu%2Fglibc.git;a=blobdiff_plain;f=nss%2Fnsswitch.c;h=36c1d0035ef7b4c52e650c71b3daf9a979d04933;hp=16e1caf50d52603906da1d8016953126e9d0f6a7;hb=40b510f64dd26b2c5fedd93779895d54562f52bf;hpb=efab527aac74f6feb569658e2009f3b5541da575 diff --git a/nss/nsswitch.c b/nss/nsswitch.c index 16e1caf50d..36c1d0035e 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -1,42 +1,48 @@ -/* Copyright (C) 1996 Free Software Foundation, Inc. -This file is part of the GNU C Library. -Contributed by Ulrich Drepper , 1996. +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ #include #include #include #include -#include +#include +#include /* We need some help from ld.so. */ #include #include #include #include +#if !defined DO_STATIC_NSS || defined PIC +# include +#endif + #include "nsswitch.h" -#include "../elf/link.h" /* We need some help from ld.so. */ /* Prototypes for the local functions. */ -static void *nss_lookup_function (service_user *ni, const char *fct_name); -static name_database *nss_parse_file (const char *fname); -static name_database_entry *nss_getline (char *line); -static service_user *nss_parse_service_list (const char *line); +static void *nss_lookup_function (service_user *ni, const char *fct_name) + internal_function; +static name_database *nss_parse_file (const char *fname) internal_function; +static name_database_entry *nss_getline (char *line) internal_function; +static service_user *nss_parse_service_list (const char *line) + internal_function; static service_library *nss_new_service (name_database *database, - const char *name); + const char *name) internal_function; /* Declare external database variables. */ @@ -63,9 +69,10 @@ static struct __libc_lock_define_initialized (static, lock) -/* Nonzero if the sevices are already initialized. */ -static int nss_initialized; - +#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; +#endif /* The root of the whole data base. */ static name_database *service_table; @@ -74,8 +81,8 @@ static name_database *service_table; /* -1 == database not found 0 == database entry pointer stored */ int -__nss_database_lookup (const char *database, const char *defconfig, - service_user **ni) +__nss_database_lookup (const char *database, const char *alternate_name, + const char *defconfig, service_user **ni) { /* Prevent multiple threads to change the service table. */ __libc_lock_lock (lock); @@ -88,7 +95,8 @@ __nss_database_lookup (const char *database, const char *defconfig, return 0; } - if (nss_initialized == 0 && service_table == NULL) + /* Are we initialized yet? */ + if (service_table == NULL) /* Read config file. */ service_table = nss_parse_file (_PATH_NSSWITCH_CONF); @@ -103,6 +111,13 @@ __nss_database_lookup (const char *database, const char *defconfig, for (entry = service_table->entry; entry != NULL; entry = entry->next) if (strcmp (database, entry->name) == 0) *ni = entry->service; + + if (*ni == NULL && alternate_name != NULL) + /* We haven't found an entry so far. Try to find it with the + alternative name. */ + for (entry = service_table->entry; entry != NULL; entry = entry->next) + if (strcmp (alternate_name, entry->name) == 0) + *ni = entry->service; } /* No configuration data is available, either because nsswitch.conf @@ -112,7 +127,7 @@ __nss_database_lookup (const char *database, const char *defconfig, or null to use the most common default. */ if (*ni == NULL) *ni = nss_parse_service_list (defconfig - ?: "compat [NOTFOUND=return] files"); + ?: "nis [NOTFOUND=return] files"); __libc_lock_unlock (lock); @@ -158,7 +173,7 @@ __nss_next (service_user **ni, const char *fct_name, void **fctp, int status, else { /* This is really only for debugging. */ - if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_SUCCESS) + if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN) __libc_fatal ("illegal status in " __FUNCTION__); if (nss_next_action (*ni, status) == NSS_ACTION_RETURN) @@ -193,16 +208,16 @@ __nss_configure_lookup (const char *dbname, const char *service_line) int cmp = strcmp (dbname, databases[cnt].name); if (cmp == 0) break; - if (cmp > 0) + if (cmp < 0) { - errno = EINVAL; + __set_errno (EINVAL); return -1; } } if (cnt == sizeof databases) { - errno = EINVAL; + __set_errno (EINVAL); return -1; } @@ -216,7 +231,7 @@ __nss_configure_lookup (const char *dbname, const char *service_line) if (new_db == NULL) { /* Illegal service specification. */ - errno = EINVAL; + __set_errno (EINVAL); return -1; } @@ -232,18 +247,61 @@ __nss_configure_lookup (const char *dbname, const char *service_line) } +#if !defined DO_STATIC_NSS || defined PIC static int -nss_dlerror_run (void (*operate) (void)) +nss_dlerror_run (void (*operate) (void *), void *args) { - const char *last_errstring = NULL; + char *last_errstring = NULL; const char *last_object_name = NULL; + int result; + + (void) _dl_catch_error (&last_errstring, &last_object_name, operate, args); - (void) _dl_catch_error (&last_errstring, &last_object_name, operate); + result = last_errstring != NULL; + if (result) + free (last_errstring); - return last_errstring != NULL; + return result; } +struct do_open_args +{ + /* Argument to do_open. */ + char *shlib_name; + service_user *ni; +}; + +struct get_sym_args +{ + /* Arguments to get_sym. */ + struct link_map *map; + char *name; + + /* Return values of get_sym. */ + ElfW(Addr) loadbase; + const ElfW(Sym) *ref; +}; + +static void +do_open (void *a) +{ + struct do_open_args *args = (struct do_open_args *) a; + /* Open and relocate the shared object. */ + args->ni->library->lib_handle = _dl_open (args->shlib_name, RTLD_LAZY); +} + +static void +get_sym (void *a) +{ + struct get_sym_args *args = (struct get_sym_args *) a; + struct link_map *scope[2] = { args->map, NULL }; + args->ref = NULL; + args->loadbase = _dl_lookup_symbol (args->name, &args->ref, + scope, args->map->l_name, 0); +} +#endif + /* Comparison function for searching NI->known tree. */ static int known_compare (const void *p1, const void *p2) @@ -254,6 +312,7 @@ known_compare (const void *p1, const void *p2) static void * +internal_function nss_lookup_function (service_user *ni, const char *fct_name) { void **found, *result; @@ -314,30 +373,30 @@ nss_lookup_function (service_user *ni, const char *fct_name) } } +#if !defined DO_STATIC_NSS || defined PIC if (ni->library->lib_handle == NULL) { /* Load the shared library. */ size_t shlen = (7 + strlen (ni->library->name) + 3 - + sizeof (NSS_SHLIB_REVISION)); - char shlib_name[shlen]; + + strlen (__nss_shlib_revision) + 1); - void do_open (void) - { - /* Open and relocate the shared object. */ - ni->library->lib_handle = _dl_open (shlib_name, RTLD_LAZY); - } + struct do_open_args args; + args.shlib_name = __alloca (shlen); + args.ni = ni; /* Construct shared object name. */ - __stpcpy (__stpcpy (__stpcpy (shlib_name, "libnss_"), - ni->library->name), - ".so" NSS_SHLIB_REVISION); + __stpcpy (__stpcpy (__stpcpy (__stpcpy (args.shlib_name, + "libnss_"), + ni->library->name), + ".so"), + __nss_shlib_revision); - if (nss_dlerror_run (do_open) != 0) + if (nss_dlerror_run (do_open, &args) != 0) /* Failed to load the library. */ - ni->library->lib_handle = (void *) -1; + ni->library->lib_handle = (void *) -1l; } - if (ni->library->lib_handle == (void *) -1) + if (ni->library->lib_handle == (void *) -1l) /* Library not found => function not found. */ result = NULL; else @@ -345,27 +404,66 @@ nss_lookup_function (service_user *ni, const char *fct_name) /* Get the desired function. Again, GNU ld.so magic ahead. */ size_t namlen = (5 + strlen (ni->library->name) + 1 + strlen (fct_name) + 1); - char name[namlen]; - struct link_map *map = ni->library->lib_handle; - ElfW(Addr) loadbase; - const ElfW(Sym) *ref = NULL; - void get_sym (void) - { - struct link_map *scope[2] = { map, NULL }; - loadbase = _dl_lookup_symbol (name, &ref, - scope, map->l_name, 0); - } + struct get_sym_args args; + args.name = __alloca (namlen); + args.map = ni->library->lib_handle; /* Construct the function name. */ - __stpcpy (__stpcpy (__stpcpy (__stpcpy (name, "_nss_"), + __stpcpy (__stpcpy (__stpcpy (__stpcpy (args.name, "_nss_"), ni->library->name), "_"), fct_name); /* Look up the symbol. */ - result = (nss_dlerror_run (get_sym) - ? NULL : (void *) (loadbase + ref->st_value)); + result = (nss_dlerror_run (get_sym, &args) ? NULL + : (void *) (args.loadbase + args.ref->st_value)); } +#else + /* We can't get function address dynamically in static linking. */ + { +# define DEFINE_ENT(h,nm) \ + extern void _nss_##h##_get##nm##ent_r (void); \ + extern void _nss_##h##_end##nm##ent (void); \ + extern void _nss_##h##_set##nm##ent (void); +# define DEFINE_GET(h,nm) \ + extern void _nss_##h##_get##nm##_r (void); +# define DEFINE_GETBY(h,nm,ky) \ + extern void _nss_##h##_get##nm##by##ky##_r (void); +# include "function.def" +# undef DEFINE_ENT +# undef DEFINE_GET +# undef DEFINE_GETBY +# define DEFINE_ENT(h,nm) \ + { #h"_get"#nm"ent_r", _nss_##h##_get##nm##ent_r }, \ + { #h"_end"#nm"ent", _nss_##h##_end##nm##ent }, \ + { #h"_set"#nm"ent", _nss_##h##_set##nm##ent }, +# define DEFINE_GET(h,nm) \ + { #h"_get"#nm"_r", _nss_##h##_get##nm##_r }, +# define DEFINE_GETBY(h,nm,ky) \ + { #h"_get"#nm"by"#ky"_r", _nss_##h##_get##nm##by##ky##_r }, + static struct fct_tbl { const char *fname; void *fp; } *tp, tbl[] = + { +# include "function.def" + { NULL, NULL } + }; + size_t namlen = (5 + strlen (ni->library->name) + 1 + + strlen (fct_name) + 1); + char name[namlen]; + + /* Construct the function name. */ + __stpcpy (__stpcpy (__stpcpy (name, ni->library->name), + "_"), + fct_name); + + result = NULL; + for (tp = &tbl[0]; tp->fname; tp++) + if (strcmp (tp->fname, name) == 0) + { + result = tp->fp; + break; + } + } +#endif /* Remember function pointer for later calls. Even if null, we record it so a second try needn't search the library again. */ @@ -381,6 +479,7 @@ nss_lookup_function (service_user *ni, const char *fct_name) static name_database * +internal_function nss_parse_file (const char *fname) { FILE *fp; @@ -453,6 +552,7 @@ nss_parse_file (const char *fname) `( ( "[" "!"? ( "=" )+ "]" )? )*' */ static service_user * +internal_function nss_parse_service_list (const char *line) { service_user *result = NULL, **nextp = &result; @@ -487,8 +587,7 @@ nss_parse_service_list (const char *line) free (new_service); return result; } - memcpy (source, name, line - name); - source[line - name] = '\0'; + *((char *) __mempcpy (source, name, line - name)) = '\0'; new_service->name = source; } @@ -498,6 +597,7 @@ nss_parse_service_list (const char *line) new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE; new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE; new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN; + new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; new_service->library = NULL; new_service->known = NULL; new_service->next = NULL; @@ -601,6 +701,7 @@ nss_parse_service_list (const char *line) } static name_database_entry * +internal_function nss_getline (char *line) { const char *name; @@ -647,6 +748,7 @@ nss_getline (char *line) static service_library * +internal_function nss_new_service (name_database *database, const char *name) { service_library **currentp = &database->library;