X-Git-Url: http://git.csclub.uwaterloo.ca/?p=kopensolaris-gnu%2Fglibc.git;a=blobdiff_plain;f=nss%2Fnsswitch.c;h=36c1d0035ef7b4c52e650c71b3daf9a979d04933;hp=9c7a2d790967b9c3cca9df6acc80997d9ad279a9;hb=40b510f64dd26b2c5fedd93779895d54562f52bf;hpb=65fc48e1674fd83e3da8757c4131efdc191fa5ea diff --git a/nss/nsswitch.c b/nss/nsswitch.c index 9c7a2d7909..36c1d0035e 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -21,23 +21,28 @@ #include #include #include -#include +#include #include /* We need some help from ld.so. */ #include #include #include #include -#include + +#if !defined DO_STATIC_NSS || defined PIC +# include +#endif #include "nsswitch.h" /* 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. */ @@ -64,8 +69,10 @@ static struct __libc_lock_define_initialized (static, lock) +#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; @@ -106,8 +113,8 @@ __nss_database_lookup (const char *database, const char *alternate_name, *ni = entry->service; if (*ni == NULL && alternate_name != NULL) - /* We haven't found a an entry so far. Try to find it with - the alternative name. */ + /* 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; @@ -240,14 +247,15 @@ __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) { char *last_errstring = NULL; const char *last_object_name = NULL; int result; - (void) _dl_catch_error (&last_errstring, &last_object_name, operate); + (void) _dl_catch_error (&last_errstring, &last_object_name, operate, args); result = last_errstring != NULL; if (result) @@ -257,6 +265,43 @@ nss_dlerror_run (void (*operate) (void)) } +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) @@ -267,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; @@ -327,26 +373,25 @@ 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 + strlen (__nss_shlib_revision) + 1); - char shlib_name[shlen]; - 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 (__stpcpy (shlib_name, "libnss_"), + __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 *) -1l; } @@ -359,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. */ @@ -395,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; @@ -467,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; @@ -501,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; } @@ -616,6 +701,7 @@ nss_parse_service_list (const char *line) } static name_database_entry * +internal_function nss_getline (char *line) { const char *name; @@ -662,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;