acctwatch() timeout:
[unix-history] / gnu / usr.bin / ld / shlib.c
CommitLineData
1136f72d
PR
1/*
2 * $Id: shlib.c,v 1.3 1993/10/23 00:34:26 pk Exp $
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' */
51 while ((cp = strtok(paths, ":")) != NULL) {
52 paths = NULL;
53 add_search_dir(cp);
54 }
55
56 /* Append standard search directories */
57 n = sizeof standard_search_dirs / sizeof standard_search_dirs[0];
58 for (i = 0; i < n; i++)
59 add_search_dir(standard_search_dirs[i]);
60}
61
62/*
63 * Return true if CP points to a valid dewey number.
64 * Decode and leave the result in the array DEWEY.
65 * Return the number of decoded entries in DEWEY.
66 */
67
68int
69getdewey(dewey, cp)
70int dewey[];
71char *cp;
72{
73 int i, n;
74
75 for (n = 0, i = 0; i < MAXDEWEY; i++) {
76 if (*cp == '\0')
77 break;
78
79 if (*cp == '.') cp++;
80 if (!isdigit(*cp))
81 return 0;
82
83 dewey[n++] = strtol(cp, &cp, 10);
84 }
85
86 return n;
87}
88
89/*
90 * Compare two dewey arrays.
91 * Return -1 if `d1' represents a smaller value than `d2'.
92 * Return 1 if `d1' represents a greater value than `d2'.
93 * Return 0 if equal.
94 */
95int
96cmpndewey(d1, n1, d2, n2)
97int d1[], d2[];
98int n1, n2;
99{
100 int i;
101
102 for (i = 0; i < n1 && i < n2; i++) {
103 if (d1[i] < d2[i])
104 return -1;
105 if (d1[i] > d2[i])
106 return 1;
107 }
108
109 if (n1 == n2)
110 return 0;
111
112 if (i == n1)
113 return -1;
114
115 if (i == n2)
116 return 1;
117}
118
119/*
120 * Search directories for a shared library matching the given
121 * major and minor version numbers.
122 *
123 * MAJOR == -1 && MINOR == -1 --> find highest version
124 * MAJOR != -1 && MINOR == -1 --> find highest minor version
125 * MAJOR == -1 && MINOR != -1 --> invalid
126 * MAJOR != -1 && MINOR != -1 --> find highest micro version
127 */
128
129/* Not interested in devices right now... */
130#undef major
131#undef minor
132
133char *
134findshlib(name, majorp, minorp)
135char *name;
136int *majorp, *minorp;
137{
138 int dewey[MAXDEWEY];
139 int ndewey;
140 int tmp[MAXDEWEY];
141 int i;
142 int len;
143 char *lname, *path = NULL;
144 int major = *majorp, minor = *minorp;
145
146 len = strlen(name);
147 lname = (char *)alloca(len + sizeof("lib"));
148 sprintf(lname, "lib%s", name);
149 len += 3;
150
151 ndewey = 0;
152
153 for (i = 0; i < n_search_dirs; i++) {
154 DIR *dd = opendir(search_dirs[i]);
155 struct dirent *dp;
156
157 if (dd == NULL)
158 continue;
159
160 while ((dp = readdir(dd)) != NULL) {
161 int n, j, might_take_it = 0;
162
163 if (dp->d_namlen < len + 4)
164 continue;
165 if (strncmp(dp->d_name, lname, len) != 0)
166 continue;
167 if (strncmp(dp->d_name+len, ".so.", 4) != 0)
168 continue;
169
170 if ((n = getdewey(tmp, dp->d_name+len+4)) == 0)
171 continue;
172
173 if (major == -1 && minor == -1) {
174 might_take_it = 1;
175 } else if (major != -1 && minor == -1) {
176 if (tmp[0] == major)
177 might_take_it = 1;
178 } else if (major != -1 && minor != -1) {
179 if (tmp[0] == major)
180 if (n == 1 || tmp[1] >= minor)
181 might_take_it = 1;
182 }
183
184 if (!might_take_it)
185 continue;
186
187 if (cmpndewey(tmp, n, dewey, ndewey) <= 0)
188 continue;
189
190 /* We have a better version */
191 if (path)
192 free(path);
193 path = concat(search_dirs[i], "/", dp->d_name);
194 bcopy(tmp, dewey, sizeof(dewey));
195 ndewey = n;
196 *majorp = dewey[0];
197 *minorp = dewey[1];
198 }
199 closedir(dd);
200 }
201
202 return path;
203}