summaryrefslogtreecommitdiffstats
path: root/libexec/rtld-aout/shlib.c
diff options
context:
space:
mode:
authorpaul <paul@FreeBSD.org>1993-11-03 23:41:59 +0000
committerpaul <paul@FreeBSD.org>1993-11-03 23:41:59 +0000
commit66fdbc00cfad3be604d07da78b916f4c04f96dbc (patch)
treeae9c655d7f7352058dd703d580c1f70430c1e5f7 /libexec/rtld-aout/shlib.c
parent7f9e326f196003559252a070bd773ee08a76b244 (diff)
downloadFreeBSD-src-66fdbc00cfad3be604d07da78b916f4c04f96dbc.zip
FreeBSD-src-66fdbc00cfad3be604d07da78b916f4c04f96dbc.tar.gz
Imported NetBSD's ld for shared libs.
Diffstat (limited to 'libexec/rtld-aout/shlib.c')
-rw-r--r--libexec/rtld-aout/shlib.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/libexec/rtld-aout/shlib.c b/libexec/rtld-aout/shlib.c
new file mode 100644
index 0000000..4be8354
--- /dev/null
+++ b/libexec/rtld-aout/shlib.c
@@ -0,0 +1,203 @@
+/*
+ * $Id: shlib.c,v 1.3 1993/10/23 00:34:26 pk Exp $
+ */
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <string.h>
+#include <dirent.h>
+#include <a.out.h>
+
+#include "ld.h"
+
+/*
+ * Standard directories to search for files specified by -l.
+ */
+#ifndef STANDARD_SEARCH_DIRS
+#define STANDARD_SEARCH_DIRS "/usr/lib", "/usr/local/lib"
+#endif
+
+char *standard_search_dirs[] = {
+ STANDARD_SEARCH_DIRS
+};
+
+int n_search_dirs;
+
+void
+add_search_dir(name)
+ char *name;
+{
+ n_search_dirs++;
+ search_dirs = (char **)xrealloc(search_dirs,
+ n_search_dirs * sizeof(char *));
+ search_dirs[n_search_dirs - 1] = strdup(name);
+}
+
+void
+std_search_dirs(paths)
+char *paths;
+{
+ char *cp;
+ int i, n;
+
+ if (paths != NULL)
+ /* Add search directories from `paths' */
+ while ((cp = strtok(paths, ":")) != NULL) {
+ paths = NULL;
+ add_search_dir(cp);
+ }
+
+ /* Append standard search directories */
+ n = sizeof standard_search_dirs / sizeof standard_search_dirs[0];
+ for (i = 0; i < n; i++)
+ add_search_dir(standard_search_dirs[i]);
+}
+
+/*
+ * Return true if CP points to a valid dewey number.
+ * Decode and leave the result in the array DEWEY.
+ * Return the number of decoded entries in DEWEY.
+ */
+
+int
+getdewey(dewey, cp)
+int dewey[];
+char *cp;
+{
+ int i, n;
+
+ for (n = 0, i = 0; i < MAXDEWEY; i++) {
+ if (*cp == '\0')
+ break;
+
+ if (*cp == '.') cp++;
+ if (!isdigit(*cp))
+ return 0;
+
+ dewey[n++] = strtol(cp, &cp, 10);
+ }
+
+ return n;
+}
+
+/*
+ * Compare two dewey arrays.
+ * Return -1 if `d1' represents a smaller value than `d2'.
+ * Return 1 if `d1' represents a greater value than `d2'.
+ * Return 0 if equal.
+ */
+int
+cmpndewey(d1, n1, d2, n2)
+int d1[], d2[];
+int n1, n2;
+{
+ int i;
+
+ for (i = 0; i < n1 && i < n2; i++) {
+ if (d1[i] < d2[i])
+ return -1;
+ if (d1[i] > d2[i])
+ return 1;
+ }
+
+ if (n1 == n2)
+ return 0;
+
+ if (i == n1)
+ return -1;
+
+ if (i == n2)
+ return 1;
+}
+
+/*
+ * Search directories for a shared library matching the given
+ * major and minor version numbers.
+ *
+ * MAJOR == -1 && MINOR == -1 --> find highest version
+ * MAJOR != -1 && MINOR == -1 --> find highest minor version
+ * MAJOR == -1 && MINOR != -1 --> invalid
+ * MAJOR != -1 && MINOR != -1 --> find highest micro version
+ */
+
+/* Not interested in devices right now... */
+#undef major
+#undef minor
+
+char *
+findshlib(name, majorp, minorp)
+char *name;
+int *majorp, *minorp;
+{
+ int dewey[MAXDEWEY];
+ int ndewey;
+ int tmp[MAXDEWEY];
+ int i;
+ int len;
+ char *lname, *path = NULL;
+ int major = *majorp, minor = *minorp;
+
+ len = strlen(name);
+ lname = (char *)alloca(len + sizeof("lib"));
+ sprintf(lname, "lib%s", name);
+ len += 3;
+
+ ndewey = 0;
+
+ for (i = 0; i < n_search_dirs; i++) {
+ DIR *dd = opendir(search_dirs[i]);
+ struct dirent *dp;
+
+ if (dd == NULL)
+ continue;
+
+ while ((dp = readdir(dd)) != NULL) {
+ int n, j, might_take_it = 0;
+
+ if (dp->d_namlen < len + 4)
+ continue;
+ if (strncmp(dp->d_name, lname, len) != 0)
+ continue;
+ if (strncmp(dp->d_name+len, ".so.", 4) != 0)
+ continue;
+
+ if ((n = getdewey(tmp, dp->d_name+len+4)) == 0)
+ continue;
+
+ if (major == -1 && minor == -1) {
+ might_take_it = 1;
+ } else if (major != -1 && minor == -1) {
+ if (tmp[0] == major)
+ might_take_it = 1;
+ } else if (major != -1 && minor != -1) {
+ if (tmp[0] == major)
+ if (n == 1 || tmp[1] >= minor)
+ might_take_it = 1;
+ }
+
+ if (!might_take_it)
+ continue;
+
+ if (cmpndewey(tmp, n, dewey, ndewey) <= 0)
+ continue;
+
+ /* We have a better version */
+ if (path)
+ free(path);
+ path = concat(search_dirs[i], "/", dp->d_name);
+ bcopy(tmp, dewey, sizeof(dewey));
+ ndewey = n;
+ *majorp = dewey[0];
+ *minorp = dewey[1];
+ }
+ closedir(dd);
+ }
+
+ return path;
+}
OpenPOWER on IntegriCloud