diff --git a/nss/nsswitch.c b/nss/nsswitch.c index 3c48b4b85e..0d823e7ad2 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -337,6 +337,8 @@ known_compare (const void *p1, const void *p2) static int nss_load_library (service_user *ni) { + char *ld_library_path; + if (ni->library == NULL) { /* This service has not yet been used. Fetch the service @@ -366,6 +368,19 @@ nss_load_library (service_user *ni) ".so"), __nss_shlib_revision); + if (ni->path != NULL) + { + /* Construct new LD_LIBRARY_PATH. */ + ld_library_path = malloc (strlen (getenv ("LD_LIBRARY_PATH")) + + strlen (ni->path) + + 1); + __stpcpy (__stpcpy (__stpcpy (ld_library_path, + ni->path), + ":"), + getenv ("LD_LIBRARY_PATH")); + setenv ("LD_LIBRARY_PATH", ld_library_path, 1); + } + ni->library->lib_handle = __libc_dlopen (shlib_name); if (ni->library->lib_handle == NULL) { @@ -622,6 +637,7 @@ nss_parse_service_list (const char *line) { service_user *new_service; const char *name; + const char *path; while (isspace (line[0])) ++line; @@ -631,14 +647,14 @@ nss_parse_service_list (const char *line) /* Read identifier. */ name = line; - while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[') + while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[' + && line[0] != ':') ++line; if (name == line) return result; - new_service = (service_user *) malloc (sizeof (service_user) - + (line - name + 1)); + + line - name + 1); if (new_service == NULL) return result; @@ -652,8 +668,22 @@ nss_parse_service_list (const char *line) new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; new_service->library = NULL; new_service->known = NULL; + new_service->path = NULL; new_service->next = NULL; + if (line[0] == ':') + { + /* Read path of the shared object */ + ++line; + path = line; + while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[') + ++line; + if (name == line) + return result; + new_service->path = (char *) malloc (line - path + 1); + *((char *) __mempcpy (new_service->path, path, line - path)) = '\0'; + } + while (isspace (line[0])) ++line; @@ -756,6 +786,8 @@ nss_parse_service_list (const char *line) continue; finish: + if (new_service->path != NULL) + free (new_service->path); free (new_service); return result; } @@ -884,6 +916,9 @@ free_database_entries (name_database_entry *entry) if (service->known != NULL) __tdestroy (service->known, free); + if (service->path != NULL) + free (service->path); + service = service->next; free (olds); } diff --git a/nss/nsswitch.h b/nss/nsswitch.h index 63573b9ebc..e31dba8358 100644 --- a/nss/nsswitch.h +++ b/nss/nsswitch.h @@ -68,6 +68,8 @@ typedef struct service_user service_library *library; /* Collection of known functions. */ void *known; + /* Path of the shared object file (will be prepended to LD_LIBRARY_PATH) */ + char *path; /* Name of the service (`files', `dns', `nis', ...). */ char name[0]; } service_user;