summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/ld/rtld/rtld.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/ld/rtld/rtld.c')
-rw-r--r--gnu/usr.bin/ld/rtld/rtld.c103
1 files changed, 99 insertions, 4 deletions
diff --git a/gnu/usr.bin/ld/rtld/rtld.c b/gnu/usr.bin/ld/rtld/rtld.c
index 72194af2d7d..33b5cd76551 100644
--- a/gnu/usr.bin/ld/rtld/rtld.c
+++ b/gnu/usr.bin/ld/rtld/rtld.c
@@ -1331,6 +1331,103 @@ static struct so_map dlmap = {
};
static int dlerrno;
+/*
+ * Populate sod struct for dlopen's call to map_obj
+ */
+void
+build_sod(name, sodp)
+ char *name;
+ struct sod *sodp;
+{
+ unsigned int number;
+ unsigned int tuplet;
+ unsigned int strange = 0;
+ int major, minor;
+ char *realname, *tok, *tok1;
+
+ /* default is an absolute or relative path */
+ sodp->sod_name = (long)strdup(name); /* strtok is destructive */
+ sodp->sod_library = 0;
+ sodp->sod_major = sodp->sod_minor = 0;
+ /* asking for lookup? */
+ if (strncmp((char *)sodp->sod_name, "lib", 3) == NULL) {
+ /* skip over 'lib' */
+ tok = (char *)sodp->sod_name + 3;
+ /* dot guardian */
+ if((strchr(tok, '.') != NULL) && (*(tok+strlen(tok)-1)!='.')) {
+ tok = strtok(tok, ".");
+ /* default */
+ major = minor = -1;
+ /* removed 'lib' and extensions from name */
+ realname = tok;
+ /* loop through name - parse skipping name */
+ for(tuplet=1;((tok=strtok(NULL,"."))!=NULL);tuplet++) {
+ switch (tuplet) {
+ /* 'so' extension */
+ case 1:
+ if(strcmp(tok, "so") != NULL)
+ strange = 1;
+ break;
+ /* major ver extension */
+ case 2:
+ for(tok1=tok;
+ (*tok1 != '\0');
+ tok1++) {
+ if(isdigit(*tok1))
+ number = 1;
+ else {
+ number = 0;
+ break;
+ }
+ }
+ if(number)
+ major = atoi(tok);
+ else {
+ major = 0;
+ strange = 1;
+ }
+ break;
+ /* minor ver extension */
+ case 3:
+ for(tok1=tok;
+ (*tok1 != '\0');
+ tok1++) {
+ if(isdigit(*tok1))
+ number = 1;
+ else {
+ number = 0;
+ break;
+ }
+ }
+ if(number)
+ minor = atoi(tok);
+ else {
+ minor = 0;
+ strange = 1;
+ }
+ break;
+ /* if we get here, it must be weird */
+ default:
+ strange = 1;
+ } /* end switch */
+ } /* end for */
+ /* normal */
+ if(!strange) {
+ free((char *)sodp->sod_name);
+ sodp->sod_name = (long)strdup(realname);
+ sodp->sod_library = 1;
+ sodp->sod_major = major;
+ sodp->sod_minor = minor;
+ }
+ /* strange */
+ else {
+ free((char *)sodp->sod_name);
+ sodp->sod_name = (long)strdup(name);
+ }
+ } /* end if dots */
+ } /* end if lookup */
+}
+
static void *
__dlopen(name, mode)
char *name;
@@ -1352,11 +1449,9 @@ __dlopen(name, mode)
return NULL;
}
- sodp->sod_name = (long)strdup(name);
- sodp->sod_library = 0;
- sodp->sod_major = sodp->sod_minor = 0;
+ build_sod(name, sodp);
- if ((smp = map_object(name, sodp, 0)) == NULL) {
+ if ((smp = map_object((char *)sodp->sod_name, sodp, 0)) == NULL) {
#ifdef DEBUG
xprintf("%s: %s\n", name, strerror(errno));
#endif