2 * Copyright (c) 1993 Paul Kranenburg
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Paul Kranenburg.
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/param.h>
34 #include <sys/types.h>
47 #include <sys/link_aout.h>
52 * Standard directories to search for files specified by -l.
54 #ifndef STANDARD_SEARCH_DIRS
55 #define STANDARD_SEARCH_DIRS "/usr/lib/aout"
59 * Actual vector of library search directories,
60 * including `-L'ed and LD_LIBRARY_PATH spec'd ones.
65 const char *standard_search_dirs
[] = {
71 add_search_dir(const char *name
)
75 for (n
= 0; n
< n_search_dirs
; n
++)
76 if (strcmp(search_dirs
[n
], name
) == 0)
79 search_dirs
= (char **)
80 xrealloc(search_dirs
, n_search_dirs
* sizeof search_dirs
[0]);
81 search_dirs
[n_search_dirs
- 1] = strdup(name
);
88 register char *cp
, *dup
;
93 /* Add search directories from `path' */
94 path
= dup
= strdup(path
);
95 while ((cp
= strsep(&path
, ":")) != NULL
)
105 /* Append standard search directories */
106 n
= sizeof standard_search_dirs
/ sizeof standard_search_dirs
[0];
107 for (i
= 0; i
< n
; i
++)
108 add_search_dir(standard_search_dirs
[i
]);
112 * Return true if CP points to a valid dewey number.
113 * Decode and leave the result in the array DEWEY.
114 * Return the number of decoded entries in DEWEY.
124 for (n
= 0, i
= 0; i
< MAXDEWEY
; i
++) {
128 if (*cp
== '.') cp
++;
132 dewey
[n
++] = strtol(cp
, &cp
, 10);
139 * Compare two dewey arrays.
140 * Return -1 if `d1' represents a smaller value than `d2'.
141 * Return 1 if `d1' represents a greater value than `d2'.
145 cmpndewey(d1
, n1
, d2
, n2
)
151 for (i
= 0; i
< n1
&& i
< n2
; i
++) {
167 errx(1, "cmpndewey: cant happen");
172 * Search directories for a shared library matching the given
173 * major and minor version numbers. See search_lib_dir() below for
174 * the detailed matching rules.
176 * As soon as a directory with an acceptable match is found, the search
177 * terminates. Subsequent directories are not searched for a better
178 * match. This is in conformance with the SunOS searching rules. Also,
179 * it avoids a lot of directory searches that are virtually guaranteed to
182 * The return value is a full pathname to the matching library. The
183 * string is dynamically allocated. If no matching library is found, the
184 * function returns NULL.
188 findshlib(name
, majorp
, minorp
, do_dot_a
)
190 int *majorp
, *minorp
;
195 for (i
= 0; i
< n_search_dirs
; i
++) {
198 path
= search_lib_dir(search_dirs
[i
], name
, majorp
, minorp
,
208 * Search library directories for a file with the given name. The
209 * return value is a full pathname to the matching file. The string
210 * is dynamically allocated. If no matching file is found, the function
220 for (i
= 0; i
< n_search_dirs
; i
++) {
221 char *path
= concat(search_dirs
[i
], "/", name
);
224 if (lstat(path
, &sb
) != -1) /* We found it */
234 * Search a given directory for a library (preferably shared) satisfying
235 * the given criteria.
237 * The matching rules are as follows:
240 * find the library with the highest major version;
242 * insist on a major version identical to *majorp;
244 * Always find the library with the highest minor version;
246 * insist on a minor version >= *minorp;
248 * It is invalid to specify a specific minor number while wildcarding
251 * The actual major and minor numbers found are returned via the pointer
254 * A suitable shared library is always preferred over a static (.a) library.
255 * If do_dot_a is false, then a static library will not be accepted in
258 * The return value is a full pathname to the matching library. The
259 * string is dynamically allocated. If no matching library is found, the
260 * function returns NULL.
264 search_lib_dir(dir
, name
, majorp
, minorp
, do_dot_a
)
274 int best_dewey
[MAXDEWEY
];
276 char dot_a_name
[MAXNAMLEN
+1];
277 char dot_so_name
[MAXNAMLEN
+1];
279 if((dd
= opendir(dir
)) == NULL
)
282 namelen
= strlen(name
);
284 dot_a_name
[0] = '\0';
285 dot_so_name
[0] = '\0';
287 while((dp
= readdir(dd
)) != NULL
) {
290 if(strlen(dp
->d_name
) < 3 + namelen
+ 2 || /* lib+xxx+.a */
291 strncmp(dp
->d_name
, "lib", 3) != 0 ||
292 strncmp(dp
->d_name
+ 3, name
, namelen
) != 0 ||
293 dp
->d_name
[3+namelen
] != '.')
296 extension
= dp
->d_name
+ 3 + namelen
+ 1; /* a or so.* */
298 if(strncmp(extension
, "so.", 3) == 0) {
299 int cur_dewey
[MAXDEWEY
];
302 cur_ndewey
= getdewey(cur_dewey
, extension
+3);
303 if(cur_ndewey
< 2) /* Too few version numbers */
306 if(*majorp
!= -1) { /* Need exact match on major */
307 if(cur_dewey
[0] != *majorp
)
309 if(*minorp
!= -1) { /* Need minor >= minimum */
310 if(cur_dewey
[1] < *minorp
)
315 if(cmpndewey(cur_dewey
, cur_ndewey
, best_dewey
,
316 best_ndewey
) <= 0) /* No better than prior match */
319 /* We found a better match */
320 strcpy(dot_so_name
, dp
->d_name
);
321 bcopy(cur_dewey
, best_dewey
,
322 cur_ndewey
* sizeof best_dewey
[0]);
323 best_ndewey
= cur_ndewey
;
324 } else if(do_dot_a
&& strcmp(extension
, "a") == 0)
325 strcpy(dot_a_name
, dp
->d_name
);
329 if(dot_so_name
[0] != '\0') {
330 *majorp
= best_dewey
[0];
331 *minorp
= best_dewey
[1];
332 return concat(dir
, "/", dot_so_name
);
335 if(dot_a_name
[0] != '\0')
336 return concat(dir
, "/", dot_a_name
);