citrus_module.c revision 1.7.6.2 1 1.7.6.2 christos /* $NetBSD: citrus_module.c,v 1.7.6.2 2009/01/04 17:02:19 christos Exp $ */
2 1.7.6.2 christos
3 1.7.6.2 christos /*-
4 1.7.6.2 christos * Copyright (c)1999, 2000, 2001, 2002 Citrus Project,
5 1.7.6.2 christos * All rights reserved.
6 1.7.6.2 christos *
7 1.7.6.2 christos * Redistribution and use in source and binary forms, with or without
8 1.7.6.2 christos * modification, are permitted provided that the following conditions
9 1.7.6.2 christos * are met:
10 1.7.6.2 christos * 1. Redistributions of source code must retain the above copyright
11 1.7.6.2 christos * notice, this list of conditions and the following disclaimer.
12 1.7.6.2 christos * 2. Redistributions in binary form must reproduce the above copyright
13 1.7.6.2 christos * notice, this list of conditions and the following disclaimer in the
14 1.7.6.2 christos * documentation and/or other materials provided with the distribution.
15 1.7.6.2 christos *
16 1.7.6.2 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 1.7.6.2 christos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 1.7.6.2 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 1.7.6.2 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 1.7.6.2 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 1.7.6.2 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 1.7.6.2 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 1.7.6.2 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 1.7.6.2 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.7.6.2 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.7.6.2 christos * SUCH DAMAGE.
27 1.7.6.2 christos */
28 1.7.6.2 christos
29 1.7.6.2 christos /*-
30 1.7.6.2 christos * Copyright (c) 1998 The NetBSD Foundation, Inc.
31 1.7.6.2 christos * All rights reserved.
32 1.7.6.2 christos *
33 1.7.6.2 christos * This code is derived from software contributed to The NetBSD Foundation
34 1.7.6.2 christos * by Paul Kranenburg.
35 1.7.6.2 christos *
36 1.7.6.2 christos * Redistribution and use in source and binary forms, with or without
37 1.7.6.2 christos * modification, are permitted provided that the following conditions
38 1.7.6.2 christos * are met:
39 1.7.6.2 christos * 1. Redistributions of source code must retain the above copyright
40 1.7.6.2 christos * notice, this list of conditions and the following disclaimer.
41 1.7.6.2 christos * 2. Redistributions in binary form must reproduce the above copyright
42 1.7.6.2 christos * notice, this list of conditions and the following disclaimer in the
43 1.7.6.2 christos * documentation and/or other materials provided with the distribution.
44 1.7.6.2 christos *
45 1.7.6.2 christos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
46 1.7.6.2 christos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
47 1.7.6.2 christos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48 1.7.6.2 christos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
49 1.7.6.2 christos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
50 1.7.6.2 christos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
51 1.7.6.2 christos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
52 1.7.6.2 christos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53 1.7.6.2 christos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54 1.7.6.2 christos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55 1.7.6.2 christos * POSSIBILITY OF SUCH DAMAGE.
56 1.7.6.2 christos */
57 1.7.6.2 christos
58 1.7.6.2 christos /*-
59 1.7.6.2 christos * Copyright (c) 1993
60 1.7.6.2 christos * The Regents of the University of California. All rights reserved.
61 1.7.6.2 christos *
62 1.7.6.2 christos * This code is derived from software contributed to Berkeley by
63 1.7.6.2 christos * Paul Borman at Krystal Technologies.
64 1.7.6.2 christos *
65 1.7.6.2 christos * Redistribution and use in source and binary forms, with or without
66 1.7.6.2 christos * modification, are permitted provided that the following conditions
67 1.7.6.2 christos * are met:
68 1.7.6.2 christos * 1. Redistributions of source code must retain the above copyright
69 1.7.6.2 christos * notice, this list of conditions and the following disclaimer.
70 1.7.6.2 christos * 2. Redistributions in binary form must reproduce the above copyright
71 1.7.6.2 christos * notice, this list of conditions and the following disclaimer in the
72 1.7.6.2 christos * documentation and/or other materials provided with the distribution.
73 1.7.6.2 christos * 3. Neither the name of the University nor the names of its contributors
74 1.7.6.2 christos * may be used to endorse or promote products derived from this software
75 1.7.6.2 christos * without specific prior written permission.
76 1.7.6.2 christos *
77 1.7.6.2 christos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
78 1.7.6.2 christos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
79 1.7.6.2 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
80 1.7.6.2 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
81 1.7.6.2 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
82 1.7.6.2 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
83 1.7.6.2 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
84 1.7.6.2 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
85 1.7.6.2 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
86 1.7.6.2 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
87 1.7.6.2 christos * SUCH DAMAGE.
88 1.7.6.2 christos */
89 1.7.6.2 christos
90 1.7.6.2 christos #include <sys/cdefs.h>
91 1.7.6.2 christos #if defined(LIBC_SCCS) && !defined(lint)
92 1.7.6.2 christos __RCSID("$NetBSD: citrus_module.c,v 1.7.6.2 2009/01/04 17:02:19 christos Exp $");
93 1.7.6.2 christos #endif /* LIBC_SCCS and not lint */
94 1.7.6.2 christos
95 1.7.6.2 christos #include <assert.h>
96 1.7.6.2 christos #include <errno.h>
97 1.7.6.2 christos #include <limits.h>
98 1.7.6.2 christos #include <string.h>
99 1.7.6.2 christos #include <stdio.h>
100 1.7.6.2 christos #include <stdlib.h>
101 1.7.6.2 christos #include <unistd.h>
102 1.7.6.2 christos #include <stddef.h>
103 1.7.6.2 christos #include <paths.h>
104 1.7.6.2 christos #include "citrus_namespace.h"
105 1.7.6.2 christos #include "citrus_bcs.h"
106 1.7.6.2 christos #include "citrus_module.h"
107 1.7.6.2 christos
108 1.7.6.2 christos #include <sys/types.h>
109 1.7.6.2 christos #include <dirent.h>
110 1.7.6.2 christos #include <dlfcn.h>
111 1.7.6.2 christos
112 1.7.6.2 christos #ifdef _I18N_DYNAMIC
113 1.7.6.2 christos
114 1.7.6.2 christos static int _getdewey(int [], char *);
115 1.7.6.2 christos static int _cmpndewey(int [], int, int [], int);
116 1.7.6.2 christos static const char *_findshlib(char *, int *, int *);
117 1.7.6.2 christos
118 1.7.6.2 christos static const char *_pathI18nModule = NULL;
119 1.7.6.2 christos
120 1.7.6.2 christos /* from libexec/ld.aout_so/shlib.c */
121 1.7.6.2 christos #undef major
122 1.7.6.2 christos #undef minor
123 1.7.6.2 christos #define MAXDEWEY 3 /*ELF*/
124 1.7.6.2 christos
125 1.7.6.2 christos static int
126 1.7.6.2 christos _getdewey(int dewey[], char *cp)
127 1.7.6.2 christos {
128 1.7.6.2 christos int i, n;
129 1.7.6.2 christos
130 1.7.6.2 christos _DIAGASSERT(dewey != NULL);
131 1.7.6.2 christos _DIAGASSERT(cp != NULL);
132 1.7.6.2 christos
133 1.7.6.2 christos for (n = 0, i = 0; i < MAXDEWEY; i++) {
134 1.7.6.2 christos if (*cp == '\0')
135 1.7.6.2 christos break;
136 1.7.6.2 christos
137 1.7.6.2 christos if (*cp == '.') cp++;
138 1.7.6.2 christos if (*cp < '0' || '9' < *cp)
139 1.7.6.2 christos return 0;
140 1.7.6.2 christos
141 1.7.6.2 christos dewey[n++] = (int)_bcs_strtol(cp, &cp, 10);
142 1.7.6.2 christos }
143 1.7.6.2 christos
144 1.7.6.2 christos return n;
145 1.7.6.2 christos }
146 1.7.6.2 christos
147 1.7.6.2 christos /*
148 1.7.6.2 christos * Compare two dewey arrays.
149 1.7.6.2 christos * Return -1 if `d1' represents a smaller value than `d2'.
150 1.7.6.2 christos * Return 1 if `d1' represents a greater value than `d2'.
151 1.7.6.2 christos * Return 0 if equal.
152 1.7.6.2 christos */
153 1.7.6.2 christos static int
154 1.7.6.2 christos _cmpndewey(int d1[], int n1, int d2[], int n2)
155 1.7.6.2 christos {
156 1.7.6.2 christos register int i;
157 1.7.6.2 christos
158 1.7.6.2 christos _DIAGASSERT(d1 != NULL);
159 1.7.6.2 christos _DIAGASSERT(d2 != NULL);
160 1.7.6.2 christos
161 1.7.6.2 christos for (i = 0; i < n1 && i < n2; i++) {
162 1.7.6.2 christos if (d1[i] < d2[i])
163 1.7.6.2 christos return -1;
164 1.7.6.2 christos if (d1[i] > d2[i])
165 1.7.6.2 christos return 1;
166 1.7.6.2 christos }
167 1.7.6.2 christos
168 1.7.6.2 christos if (n1 == n2)
169 1.7.6.2 christos return 0;
170 1.7.6.2 christos
171 1.7.6.2 christos if (i == n1)
172 1.7.6.2 christos return -1;
173 1.7.6.2 christos
174 1.7.6.2 christos if (i == n2)
175 1.7.6.2 christos return 1;
176 1.7.6.2 christos
177 1.7.6.2 christos /* XXX cannot happen */
178 1.7.6.2 christos return 0;
179 1.7.6.2 christos }
180 1.7.6.2 christos
181 1.7.6.2 christos static const char *
182 1.7.6.2 christos _findshlib(char *name, int *majorp, int *minorp)
183 1.7.6.2 christos {
184 1.7.6.2 christos int dewey[MAXDEWEY];
185 1.7.6.2 christos int ndewey;
186 1.7.6.2 christos int tmp[MAXDEWEY];
187 1.7.6.2 christos int i;
188 1.7.6.2 christos int len;
189 1.7.6.2 christos char *lname;
190 1.7.6.2 christos static char path[PATH_MAX];
191 1.7.6.2 christos int major, minor;
192 1.7.6.2 christos const char *search_dirs[1];
193 1.7.6.2 christos const int n_search_dirs = 1;
194 1.7.6.2 christos
195 1.7.6.2 christos _DIAGASSERT(name != NULL);
196 1.7.6.2 christos _DIAGASSERT(majorp != NULL);
197 1.7.6.2 christos _DIAGASSERT(minorp != NULL);
198 1.7.6.2 christos
199 1.7.6.2 christos major = *majorp;
200 1.7.6.2 christos minor = *minorp;
201 1.7.6.2 christos path[0] = '\0';
202 1.7.6.2 christos search_dirs[0] = _pathI18nModule;
203 1.7.6.2 christos len = strlen(name);
204 1.7.6.2 christos lname = name;
205 1.7.6.2 christos
206 1.7.6.2 christos ndewey = 0;
207 1.7.6.2 christos
208 1.7.6.2 christos for (i = 0; i < n_search_dirs; i++) {
209 1.7.6.2 christos DIR *dd = opendir(search_dirs[i]);
210 1.7.6.2 christos struct dirent *dp;
211 1.7.6.2 christos int found_dot_a = 0;
212 1.7.6.2 christos int found_dot_so = 0;
213 1.7.6.2 christos
214 1.7.6.2 christos if (dd == NULL)
215 1.7.6.2 christos continue;
216 1.7.6.2 christos
217 1.7.6.2 christos while ((dp = readdir(dd)) != NULL) {
218 1.7.6.2 christos int n;
219 1.7.6.2 christos
220 1.7.6.2 christos if (dp->d_namlen < len + 4)
221 1.7.6.2 christos continue;
222 1.7.6.2 christos if (strncmp(dp->d_name, lname, (size_t)len) != 0)
223 1.7.6.2 christos continue;
224 1.7.6.2 christos if (strncmp(dp->d_name+len, ".so.", 4) != 0)
225 1.7.6.2 christos continue;
226 1.7.6.2 christos
227 1.7.6.2 christos if ((n = _getdewey(tmp, dp->d_name+len+4)) == 0)
228 1.7.6.2 christos continue;
229 1.7.6.2 christos
230 1.7.6.2 christos if (major != -1 && found_dot_a)
231 1.7.6.2 christos found_dot_a = 0;
232 1.7.6.2 christos
233 1.7.6.2 christos /* XXX should verify the library is a.out/ELF? */
234 1.7.6.2 christos
235 1.7.6.2 christos if (major == -1 && minor == -1) {
236 1.7.6.2 christos goto compare_version;
237 1.7.6.2 christos } else if (major != -1 && minor == -1) {
238 1.7.6.2 christos if (tmp[0] == major)
239 1.7.6.2 christos goto compare_version;
240 1.7.6.2 christos } else if (major != -1 && minor != -1) {
241 1.7.6.2 christos if (tmp[0] == major) {
242 1.7.6.2 christos if (n == 1 || tmp[1] >= minor)
243 1.7.6.2 christos goto compare_version;
244 1.7.6.2 christos }
245 1.7.6.2 christos }
246 1.7.6.2 christos
247 1.7.6.2 christos /* else, this file does not qualify */
248 1.7.6.2 christos continue;
249 1.7.6.2 christos
250 1.7.6.2 christos compare_version:
251 1.7.6.2 christos if (_cmpndewey(tmp, n, dewey, ndewey) <= 0)
252 1.7.6.2 christos continue;
253 1.7.6.2 christos
254 1.7.6.2 christos /* We have a better version */
255 1.7.6.2 christos found_dot_so = 1;
256 1.7.6.2 christos snprintf(path, sizeof(path), "%s/%s", search_dirs[i],
257 1.7.6.2 christos dp->d_name);
258 1.7.6.2 christos found_dot_a = 0;
259 1.7.6.2 christos bcopy(tmp, dewey, sizeof(dewey));
260 1.7.6.2 christos ndewey = n;
261 1.7.6.2 christos *majorp = dewey[0];
262 1.7.6.2 christos *minorp = dewey[1];
263 1.7.6.2 christos }
264 1.7.6.2 christos closedir(dd);
265 1.7.6.2 christos
266 1.7.6.2 christos if (found_dot_a || found_dot_so)
267 1.7.6.2 christos /*
268 1.7.6.2 christos * There's a lib in this dir; take it.
269 1.7.6.2 christos */
270 1.7.6.2 christos return path[0] ? path : NULL;
271 1.7.6.2 christos }
272 1.7.6.2 christos
273 1.7.6.2 christos return path[0] ? path : NULL;
274 1.7.6.2 christos }
275 1.7.6.2 christos
276 1.7.6.2 christos void *
277 1.7.6.2 christos _citrus_find_getops(_citrus_module_t handle, const char *modname,
278 1.7.6.2 christos const char *ifname)
279 1.7.6.2 christos {
280 1.7.6.2 christos char name[PATH_MAX];
281 1.7.6.2 christos void *p;
282 1.7.6.2 christos
283 1.7.6.2 christos _DIAGASSERT(handle != NULL);
284 1.7.6.2 christos _DIAGASSERT(modname != NULL);
285 1.7.6.2 christos _DIAGASSERT(ifname != NULL);
286 1.7.6.2 christos
287 1.7.6.2 christos snprintf(name, sizeof(name), _C_LABEL_STRING("_citrus_%s_%s_getops"),
288 1.7.6.2 christos modname, ifname);
289 1.7.6.2 christos p = dlsym((void *)handle, name);
290 1.7.6.2 christos return p;
291 1.7.6.2 christos }
292 1.7.6.2 christos
293 1.7.6.2 christos int
294 1.7.6.2 christos _citrus_load_module(_citrus_module_t *rhandle, const char *encname)
295 1.7.6.2 christos {
296 1.7.6.2 christos const char *p;
297 1.7.6.2 christos char path[PATH_MAX];
298 1.7.6.2 christos int maj, min;
299 1.7.6.2 christos void *handle;
300 1.7.6.2 christos
301 1.7.6.2 christos _DIAGASSERT(rhandle != NULL);
302 1.7.6.2 christos
303 1.7.6.2 christos if (_pathI18nModule == NULL) {
304 1.7.6.2 christos p = getenv("PATH_I18NMODULE");
305 1.7.6.2 christos if (p != NULL && !issetugid()) {
306 1.7.6.2 christos _pathI18nModule = strdup(p);
307 1.7.6.2 christos if (_pathI18nModule == NULL)
308 1.7.6.2 christos return ENOMEM;
309 1.7.6.2 christos } else
310 1.7.6.2 christos _pathI18nModule = _PATH_I18NMODULE;
311 1.7.6.2 christos }
312 1.7.6.2 christos
313 1.7.6.2 christos (void)snprintf(path, sizeof(path), "lib%s", encname);
314 1.7.6.2 christos maj = I18NMODULE_MAJOR;
315 1.7.6.2 christos min = -1;
316 1.7.6.2 christos p = _findshlib(path, &maj, &min);
317 1.7.6.2 christos if (!p)
318 1.7.6.2 christos return (EINVAL);
319 1.7.6.2 christos handle = dlopen(p, RTLD_LAZY);
320 1.7.6.2 christos if (!handle)
321 1.7.6.2 christos return (EINVAL);
322 1.7.6.2 christos
323 1.7.6.2 christos *rhandle = (_citrus_module_t)handle;
324 1.7.6.2 christos
325 1.7.6.2 christos return (0);
326 1.7.6.2 christos }
327 1.7.6.2 christos
328 1.7.6.2 christos void
329 1.7.6.2 christos _citrus_unload_module(_citrus_module_t handle)
330 1.7.6.2 christos {
331 1.7.6.2 christos if (handle)
332 1.7.6.2 christos dlclose((void *)handle);
333 1.7.6.2 christos }
334 1.7.6.2 christos #else
335 1.7.6.2 christos /* !_I18N_DYNAMIC */
336 1.7.6.2 christos
337 1.7.6.2 christos void *
338 1.7.6.2 christos /*ARGSUSED*/
339 1.7.6.2 christos _citrus_find_getops(_citrus_module_t handle, const char *modname,
340 1.7.6.2 christos const char *ifname)
341 1.7.6.2 christos {
342 1.7.6.2 christos return (NULL);
343 1.7.6.2 christos }
344 1.7.6.2 christos
345 1.7.6.2 christos int
346 1.7.6.2 christos /*ARGSUSED*/
347 1.7.6.2 christos _citrus_load_module(_citrus_module_t *rhandle, char const *modname)
348 1.7.6.2 christos {
349 1.7.6.2 christos return (EINVAL);
350 1.7.6.2 christos }
351 1.7.6.2 christos
352 1.7.6.2 christos void
353 1.7.6.2 christos /*ARGSUSED*/
354 1.7.6.2 christos _citrus_unload_module(_citrus_module_t handle)
355 1.7.6.2 christos {
356 1.7.6.2 christos }
357 1.7.6.2 christos #endif
358