Remove compiler warning:
[unix-history] / gnu / usr.bin / ld / shlib.c
CommitLineData
1136f72d 1/*
1558d71a 2 * $Id: shlib.c,v 1.4 1993/12/02 00:56:40 jkh Exp $
1136f72d
PR
3 */
4
5#include <sys/param.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <sys/file.h>
11#include <sys/time.h>
12#include <fcntl.h>
13#include <string.h>
14#include <dirent.h>
15#include <a.out.h>
16
17#include "ld.h"
18
19/*
20 * Standard directories to search for files specified by -l.
21 */
22#ifndef STANDARD_SEARCH_DIRS
23#define STANDARD_SEARCH_DIRS "/usr/lib", "/usr/local/lib"
24#endif
25
26char *standard_search_dirs[] = {
27 STANDARD_SEARCH_DIRS
28};
29
30int n_search_dirs;
31
32void
33add_search_dir(name)
34 char *name;
35{
36 n_search_dirs++;
37 search_dirs = (char **)xrealloc(search_dirs,
38 n_search_dirs * sizeof(char *));
39 search_dirs[n_search_dirs - 1] = strdup(name);
40}
41
42void
43std_search_dirs(paths)
44char *paths;
45{
46 char *cp;
47 int i, n;
48
49 if (paths != NULL)
50 /* Add search directories from `paths' */
7fc7155d 51 while ((cp = strsep(&paths, ":")) != NULL) {
1136f72d 52 add_search_dir(cp);
7fc7155d
PR
53 if (paths)
54 *(paths-1) = ':';
1136f72d
PR
55 }
56
57 /* Append standard search directories */
58 n = sizeof standard_search_dirs / sizeof standard_search_dirs[0];
59 for (i = 0; i < n; i++)
60 add_search_dir(standard_search_dirs[i]);
61}
62
63/*
64 * Return true if CP points to a valid dewey number.
65 * Decode and leave the result in the array DEWEY.
66 * Return the number of decoded entries in DEWEY.
67 */
68
69int
70getdewey(dewey, cp)
71int dewey[];
72char *cp;
73{
74 int i, n;
75
76 for (n = 0, i = 0; i < MAXDEWEY; i++) {
77 if (*cp == '\0')
78 break;
79
80 if (*cp == '.') cp++;
81 if (!isdigit(*cp))
82 return 0;
83
84 dewey[n++] = strtol(cp, &cp, 10);
85 }
86
87 return n;
88}
89
90/*
91 * Compare two dewey arrays.
92 * Return -1 if `d1' represents a smaller value than `d2'.
93 * Return 1 if `d1' represents a greater value than `d2'.
94 * Return 0 if equal.
95 */
96int
97cmpndewey(d1, n1, d2, n2)
98int d1[], d2[];
99int n1, n2;
100{
101 int i;
102
103 for (i = 0; i < n1 && i < n2; i++) {
104 if (d1[i] < d2[i])
105 return -1;
106 if (d1[i] > d2[i])
107 return 1;
108 }
109
110 if (n1 == n2)
111 return 0;
112
113 if (i == n1)
114 return -1;
115
116 if (i == n2)
117 return 1;
118}
119
120/*
121 * Search directories for a shared library matching the given
122 * major and minor version numbers.
123 *
124 * MAJOR == -1 && MINOR == -1 --> find highest version
125 * MAJOR != -1 && MINOR == -1 --> find highest minor version
126 * MAJOR == -1 && MINOR != -1 --> invalid
127 * MAJOR != -1 && MINOR != -1 --> find highest micro version
128 */
129
130/* Not interested in devices right now... */
131#undef major
132#undef minor
133
134char *
1558d71a 135findshlib(name, majorp, minorp)
1136f72d
PR
136char *name;
137int *majorp, *minorp;
138{
139 int dewey[MAXDEWEY];
140 int ndewey;
141 int tmp[MAXDEWEY];
142 int i;
143 int len;
144 char *lname, *path = NULL;
145 int major = *majorp, minor = *minorp;
146
147 len = strlen(name);
148 lname = (char *)alloca(len + sizeof("lib"));
149 sprintf(lname, "lib%s", name);
150 len += 3;
151
152 ndewey = 0;
153
154 for (i = 0; i < n_search_dirs; i++) {
155 DIR *dd = opendir(search_dirs[i]);
156 struct dirent *dp;
157
158 if (dd == NULL)
159 continue;
160
161 while ((dp = readdir(dd)) != NULL) {
162 int n, j, might_take_it = 0;
163
164 if (dp->d_namlen < len + 4)
165 continue;
166 if (strncmp(dp->d_name, lname, len) != 0)
167 continue;
168 if (strncmp(dp->d_name+len, ".so.", 4) != 0)
169 continue;
170
171 if ((n = getdewey(tmp, dp->d_name+len+4)) == 0)
172 continue;
173
174 if (major == -1 && minor == -1) {
175 might_take_it = 1;
176 } else if (major != -1 && minor == -1) {
177 if (tmp[0] == major)
178 might_take_it = 1;
179 } else if (major != -1 && minor != -1) {
180 if (tmp[0] == major)
181 if (n == 1 || tmp[1] >= minor)
182 might_take_it = 1;
183 }
184
185 if (!might_take_it)
186 continue;
187
188 if (cmpndewey(tmp, n, dewey, ndewey) <= 0)
189 continue;
190
191 /* We have a better version */
192 if (path)
193 free(path);
194 path = concat(search_dirs[i], "/", dp->d_name);
195 bcopy(tmp, dewey, sizeof(dewey));
196 ndewey = n;
197 *majorp = dewey[0];
198 *minorp = dewey[1];
199 }
200 closedir(dd);
201 }
202
203 return path;
204}