No empty .Rs/.Re
[netbsd-mini2440.git] / libexec / ld.aout_so / shlib.c
blob40ff178a9c5a1d0fea2ffbb78513591dfd82390d
1 /* $NetBSD: shlib.c,v 1.22 2008/04/28 20:23:03 martin Exp $ */
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Paul Kranenburg.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #ifdef sun
33 char *strsep();
34 int isdigit();
35 #endif
37 #include <sys/param.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/file.h>
41 #include <sys/time.h>
42 #include <sys/exec_aout.h>
43 #include <ctype.h>
44 #include <dirent.h>
45 #include <err.h>
46 #include <fcntl.h>
47 #include <a.out.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <paths.h>
52 #include <link_aout.h>
54 #include "shlib.h"
57 * Standard directories to search for files specified by -l.
59 #ifndef STANDARD_SEARCH_DIRS
60 #define STANDARD_SEARCH_DIRS "/usr/lib"
61 #endif
64 * Actual vector of library search directories,
65 * including `-L'ed and LD_LIBRARY_PATH spec'd ones.
67 char **search_dirs;
68 int n_search_dirs;
70 const char *standard_search_dirs[] = {
71 STANDARD_SEARCH_DIRS
74 void
75 add_search_dir(name)
76 const char *name;
78 n_search_dirs += 2;
79 search_dirs = (char **)
80 xrealloc(search_dirs, n_search_dirs * sizeof search_dirs[0]);
81 search_dirs[n_search_dirs - 2] = strdup(name);
82 search_dirs[n_search_dirs - 1] =
83 xmalloc(sizeof(_PATH_EMUL_AOUT) + strlen(name));
84 strcpy(search_dirs[n_search_dirs - 1], _PATH_EMUL_AOUT);
85 strcat(search_dirs[n_search_dirs - 1], name);
88 void
89 remove_search_dir(name)
90 char *name;
92 int n;
94 for (n = 0; n < n_search_dirs; n++) {
95 if (strcmp(search_dirs[n], name))
96 continue;
97 free(search_dirs[n]);
98 free(search_dirs[n+1]);
99 if (n < (n_search_dirs - 2))
100 bcopy(&search_dirs[n+2], &search_dirs[n],
101 (n_search_dirs - n - 2) * sizeof search_dirs[0]);
102 n_search_dirs -= 2;
106 void
107 add_search_path(path)
108 char *path;
110 register char *cp, *dup;
112 if (path == NULL)
113 return;
115 /* Add search directories from `path' */
116 path = dup = strdup(path);
117 while ((cp = strsep(&path, ":")) != NULL)
118 add_search_dir(cp);
119 free(dup);
122 void
123 remove_search_path(path)
124 char *path;
126 register char *cp, *dup;
128 if (path == NULL)
129 return;
131 /* Remove search directories from `path' */
132 path = dup = strdup(path);
133 while ((cp = strsep(&path, ":")) != NULL)
134 remove_search_dir(cp);
135 free(dup);
138 void
139 std_search_path()
141 int i, n;
143 /* Append standard search directories */
144 n = sizeof standard_search_dirs / sizeof standard_search_dirs[0];
145 for (i = 0; i < n; i++)
146 add_search_dir(standard_search_dirs[i]);
150 * Return true if CP points to a valid dewey number.
151 * Decode and leave the result in the array DEWEY.
152 * Return the number of decoded entries in DEWEY.
156 getdewey(dewey, cp)
157 int dewey[];
158 char *cp;
160 int i, n;
162 for (n = 0, i = 0; i < MAXDEWEY; i++) {
163 if (*cp == '\0')
164 break;
166 if (*cp == '.') cp++;
167 #ifdef SUNOS_LIB_COMPAT
168 if (!(isdigit)(*cp))
169 #else
170 if (!isdigit((unsigned char)*cp))
171 #endif
172 return 0;
174 dewey[n++] = strtol(cp, &cp, 10);
177 return n;
181 * Compare two dewey arrays.
182 * Return -1 if `d1' represents a smaller value than `d2'.
183 * Return 1 if `d1' represents a greater value than `d2'.
184 * Return 0 if equal.
187 cmpndewey(d1, n1, d2, n2)
188 int d1[], d2[];
189 int n1, n2;
191 register int i;
193 for (i = 0; i < n1 && i < n2; i++) {
194 if (d1[i] < d2[i])
195 return -1;
196 if (d1[i] > d2[i])
197 return 1;
200 if (n1 == n2)
201 return 0;
203 if (i == n1)
204 return -1;
206 if (i == n2)
207 return 1;
209 errx(1, "cmpndewey: cant happen");
210 return 0;
214 * Search directories for a shared library matching the given
215 * major and minor version numbers.
217 * MAJOR == -1 && MINOR == -1 --> find highest version
218 * MAJOR != -1 && MINOR == -1 --> find highest minor version
219 * MAJOR == -1 && MINOR != -1 --> invalid
220 * MAJOR != -1 && MINOR != -1 --> find highest micro version
223 /* Not interested in devices right now... */
224 #undef major
225 #undef minor
227 char *
228 findshlib(name, majorp, minorp, do_dot_a)
229 char *name;
230 int *majorp, *minorp;
231 int do_dot_a;
233 int dewey[MAXDEWEY];
234 int ndewey;
235 int tmp[MAXDEWEY];
236 int i;
237 int len;
238 char *lname, *path = NULL;
239 int major = *majorp, minor = *minorp;
241 len = strlen(name) + sizeof("lib");
242 #if defined(__SSP__) || defined(__SSP_ALL__)
243 lname = xmalloc(len);
244 #else
245 lname = alloca(len);
246 #endif
247 len--;
248 sprintf(lname, "lib%s", name);
250 ndewey = 0;
252 for (i = 0; i < n_search_dirs; i++) {
253 DIR *dd = opendir(search_dirs[i]);
254 struct dirent *dp;
255 int found_dot_a = 0;
256 int found_dot_so = 0;
258 if (dd == NULL)
259 continue;
261 while ((dp = readdir(dd)) != NULL) {
262 int n;
263 struct exec ex;
264 char *xpath;
265 FILE *fp;
267 if (do_dot_a && path == NULL &&
268 dp->d_namlen == len + 2 &&
269 strncmp(dp->d_name, lname, len) == 0 &&
270 (dp->d_name+len)[0] == '.' &&
271 (dp->d_name+len)[1] == 'a') {
273 path = concat(search_dirs[i], "/", dp->d_name);
274 found_dot_a = 1;
277 if (dp->d_namlen < len + 4)
278 continue;
279 if (strncmp(dp->d_name, lname, len) != 0)
280 continue;
281 if (strncmp(dp->d_name+len, ".so.", 4) != 0)
282 continue;
284 if ((n = getdewey(tmp, dp->d_name+len+4)) == 0)
285 continue;
287 if (major != -1 && found_dot_a) { /* XXX */
288 free(path);
289 path = NULL;
290 found_dot_a = 0;
293 /* verify the library is a.out */
294 xpath = concat(search_dirs[i], "/", dp->d_name);
295 fp = fopen(xpath, "r");
296 free(xpath);
297 if (fp == NULL) {
298 continue;
300 if (sizeof(ex) != fread(&ex, 1, sizeof(ex), fp)) {
301 fclose(fp);
302 continue;
304 fclose(fp);
305 if (N_GETMAGIC(ex) != ZMAGIC
306 || (N_GETFLAG(ex) & EX_DYNAMIC) == 0) {
307 continue;
310 if (major == -1 && minor == -1) {
311 goto compare_version;
312 } else if (major != -1 && minor == -1) {
313 if (tmp[0] == major)
314 goto compare_version;
315 } else if (major != -1 && minor != -1) {
316 if (tmp[0] == major) {
317 if (n == 1 || tmp[1] >= minor)
318 goto compare_version;
322 /* else, this file does not qualify */
323 continue;
325 compare_version:
326 if (cmpndewey(tmp, n, dewey, ndewey) <= 0)
327 continue;
329 /* We have a better version */
330 found_dot_so = 1;
331 if (path)
332 free(path);
333 path = concat(search_dirs[i], "/", dp->d_name);
334 found_dot_a = 0;
335 bcopy(tmp, dewey, sizeof(dewey));
336 ndewey = n;
337 *majorp = dewey[0];
338 *minorp = dewey[1];
340 closedir(dd);
342 if (found_dot_a || found_dot_so)
344 * There's a lib in this dir; take it.
346 return path;
348 #if defined(__SSP__) || defined(__SSP_ALL__)
349 free(lname);
350 #endif
351 return path;
356 * Utility functions shared with others.
361 * Like malloc but get fatal error if memory is exhausted.
363 void *
364 xmalloc(size)
365 size_t size;
367 void *result = (void *)malloc(size);
369 if (!result)
370 errx(1, "virtual memory exhausted");
372 return (result);
376 * Like realloc but get fatal error if memory is exhausted.
378 void *
379 xrealloc(ptr, size)
380 void *ptr;
381 size_t size;
383 void *result;
385 result = (ptr == NULL) ? malloc(size) : realloc(ptr, size);
386 if (result == NULL)
387 errx(1, "virtual memory exhausted");
389 return (result);
393 * Return a newly-allocated string whose contents concatenate
394 * the strings S1, S2, S3.
396 char *
397 concat(s1, s2, s3)
398 const char *s1, *s2, *s3;
400 int len1 = strlen(s1),
401 len2 = strlen(s2),
402 len3 = strlen(s3);
404 char *result = (char *)xmalloc(len1 + len2 + len3 + 1);
406 strcpy(result, s1);
407 strcpy(result + len1, s2);
408 strcpy(result + len1 + len2, s3);
409 result[len1 + len2 + len3] = 0;
411 return (result);