1*84d9c625SLionel Sambuc /* $NetBSD: paths.c,v 1.41 2013/05/06 08:02:20 skrll Exp $ */
2e83f7ba2SBen Gras
3e83f7ba2SBen Gras /*
4e83f7ba2SBen Gras * Copyright 1996 Matt Thomas <matt@3am-software.com>
5e83f7ba2SBen Gras * Copyright 2002 Charles M. Hannum <root@ihack.net>
6e83f7ba2SBen Gras * All rights reserved.
7e83f7ba2SBen Gras *
8e83f7ba2SBen Gras * Redistribution and use in source and binary forms, with or without
9e83f7ba2SBen Gras * modification, are permitted provided that the following conditions
10e83f7ba2SBen Gras * are met:
11e83f7ba2SBen Gras * 1. Redistributions of source code must retain the above copyright
12e83f7ba2SBen Gras * notice, this list of conditions and the following disclaimer.
13e83f7ba2SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
14e83f7ba2SBen Gras * notice, this list of conditions and the following disclaimer in the
15e83f7ba2SBen Gras * documentation and/or other materials provided with the distribution.
16e83f7ba2SBen Gras * 3. The name of the author may not be used to endorse or promote products
17e83f7ba2SBen Gras * derived from this software without specific prior written permission.
18e83f7ba2SBen Gras *
19e83f7ba2SBen Gras * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20e83f7ba2SBen Gras * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21e83f7ba2SBen Gras * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22e83f7ba2SBen Gras * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23e83f7ba2SBen Gras * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24e83f7ba2SBen Gras * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25e83f7ba2SBen Gras * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26e83f7ba2SBen Gras * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27e83f7ba2SBen Gras * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28e83f7ba2SBen Gras * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29e83f7ba2SBen Gras */
30e83f7ba2SBen Gras
31e83f7ba2SBen Gras #include <sys/cdefs.h>
32e83f7ba2SBen Gras #ifndef lint
33*84d9c625SLionel Sambuc __RCSID("$NetBSD: paths.c,v 1.41 2013/05/06 08:02:20 skrll Exp $");
34e83f7ba2SBen Gras #endif /* not lint */
35e83f7ba2SBen Gras
36e83f7ba2SBen Gras #include <err.h>
37e83f7ba2SBen Gras #include <errno.h>
38e83f7ba2SBen Gras #include <fcntl.h>
39e83f7ba2SBen Gras #include <stdarg.h>
40e83f7ba2SBen Gras #include <stdio.h>
41e83f7ba2SBen Gras #include <stdlib.h>
42e83f7ba2SBen Gras #include <string.h>
43e83f7ba2SBen Gras #include <unistd.h>
44e83f7ba2SBen Gras #include <sys/types.h>
45e83f7ba2SBen Gras #include <sys/param.h>
46e83f7ba2SBen Gras #include <sys/sysctl.h>
47e83f7ba2SBen Gras #include <sys/mman.h>
48e83f7ba2SBen Gras #include <sys/stat.h>
49e83f7ba2SBen Gras #include <sys/gmon.h>
50e83f7ba2SBen Gras #include <sys/socket.h>
51e83f7ba2SBen Gras #include <sys/mount.h>
52e83f7ba2SBen Gras #include <sys/mbuf.h>
53e83f7ba2SBen Gras #include <sys/resource.h>
54e83f7ba2SBen Gras #include <machine/cpu.h>
55e83f7ba2SBen Gras
56e83f7ba2SBen Gras #include "debug.h"
57e83f7ba2SBen Gras #include "rtld.h"
58e83f7ba2SBen Gras
59e83f7ba2SBen Gras static Search_Path *_rtld_find_path(Search_Path *, const char *, size_t);
60e83f7ba2SBen Gras static Search_Path **_rtld_append_path(Search_Path **, Search_Path **,
61e83f7ba2SBen Gras const char *, const char *, const char *);
62e83f7ba2SBen Gras static void _rtld_process_mapping(Library_Xform **, const char *,
63e83f7ba2SBen Gras const char *);
64e83f7ba2SBen Gras static char *exstrdup(const char *, const char *);
65e83f7ba2SBen Gras static const char *getstr(const char **, const char *, const char *);
66e83f7ba2SBen Gras static const char *getcstr(const char **, const char *, const char *);
67e83f7ba2SBen Gras static const char *getword(const char **, const char *, const char *);
68e83f7ba2SBen Gras static int matchstr(const char *, const char *, const char *);
69e83f7ba2SBen Gras
70e83f7ba2SBen Gras static const char WS[] = " \t\n";
71e83f7ba2SBen Gras
72e83f7ba2SBen Gras /*
73e83f7ba2SBen Gras * Like xstrdup(), but takes end of string as a argument.
74e83f7ba2SBen Gras */
75e83f7ba2SBen Gras static char *
exstrdup(const char * bp,const char * ep)76e83f7ba2SBen Gras exstrdup(const char *bp, const char *ep)
77e83f7ba2SBen Gras {
78e83f7ba2SBen Gras char *cp;
79e83f7ba2SBen Gras size_t len = ep - bp;
80e83f7ba2SBen Gras
81e83f7ba2SBen Gras cp = xmalloc(len + 1);
82e83f7ba2SBen Gras memcpy(cp, bp, len);
83e83f7ba2SBen Gras cp[len] = '\0';
84e83f7ba2SBen Gras return (cp);
85e83f7ba2SBen Gras }
86e83f7ba2SBen Gras
87e83f7ba2SBen Gras /*
88e83f7ba2SBen Gras * Like strsep(), but takes end of string and doesn't put any NUL. To
89e83f7ba2SBen Gras * detect empty string, compare `*p' and return value.
90e83f7ba2SBen Gras */
91e83f7ba2SBen Gras static const char *
getstr(const char ** p,const char * ep,const char * delim)92e83f7ba2SBen Gras getstr(const char **p, const char *ep, const char *delim)
93e83f7ba2SBen Gras {
94e83f7ba2SBen Gras const char *cp = *p, *q, *r;
95e83f7ba2SBen Gras
96e83f7ba2SBen Gras if (ep < cp)
97e83f7ba2SBen Gras /* End of string */
98e83f7ba2SBen Gras return (NULL);
99e83f7ba2SBen Gras
100e83f7ba2SBen Gras for (q = cp; q < ep; q++)
101e83f7ba2SBen Gras for (r = delim; *r != 0; r++)
102e83f7ba2SBen Gras if (*r == *q)
103e83f7ba2SBen Gras goto done;
104e83f7ba2SBen Gras
105e83f7ba2SBen Gras done:
106e83f7ba2SBen Gras *p = q;
107e83f7ba2SBen Gras return (cp);
108e83f7ba2SBen Gras }
109e83f7ba2SBen Gras
110e83f7ba2SBen Gras /*
111e83f7ba2SBen Gras * Like getstr() above, but delim[] is complemented.
112e83f7ba2SBen Gras */
113e83f7ba2SBen Gras static const char *
getcstr(const char ** p,const char * ep,const char * delim)114e83f7ba2SBen Gras getcstr(const char **p, const char *ep, const char *delim)
115e83f7ba2SBen Gras {
116e83f7ba2SBen Gras const char *cp = *p, *q, *r;
117e83f7ba2SBen Gras
118e83f7ba2SBen Gras if (ep < cp)
119e83f7ba2SBen Gras /* End of string */
120e83f7ba2SBen Gras return (NULL);
121e83f7ba2SBen Gras
122e83f7ba2SBen Gras for (q = cp; q < ep; q++)
123e83f7ba2SBen Gras for (r = delim; *r != *q; r++)
124e83f7ba2SBen Gras if (*r == 0)
125e83f7ba2SBen Gras goto done;
126e83f7ba2SBen Gras
127e83f7ba2SBen Gras done:
128e83f7ba2SBen Gras *p = q;
129e83f7ba2SBen Gras return (cp);
130e83f7ba2SBen Gras }
131e83f7ba2SBen Gras
132e83f7ba2SBen Gras static const char *
getword(const char ** p,const char * ep,const char * delim)133e83f7ba2SBen Gras getword(const char **p, const char *ep, const char *delim)
134e83f7ba2SBen Gras {
135e83f7ba2SBen Gras
136e83f7ba2SBen Gras (void)getcstr(p, ep, delim);
137e83f7ba2SBen Gras
138e83f7ba2SBen Gras /*
139e83f7ba2SBen Gras * Now, we're looking non-delim, or end of string.
140e83f7ba2SBen Gras */
141e83f7ba2SBen Gras
142e83f7ba2SBen Gras return (getstr(p, ep, delim));
143e83f7ba2SBen Gras }
144e83f7ba2SBen Gras
145e83f7ba2SBen Gras /*
146e83f7ba2SBen Gras * Match `bp' against NUL terminated string pointed by `p'.
147e83f7ba2SBen Gras */
148e83f7ba2SBen Gras static int
matchstr(const char * p,const char * bp,const char * ep)149e83f7ba2SBen Gras matchstr(const char *p, const char *bp, const char *ep)
150e83f7ba2SBen Gras {
151e83f7ba2SBen Gras int c;
152e83f7ba2SBen Gras
153e83f7ba2SBen Gras while (bp < ep)
154e83f7ba2SBen Gras if ((c = *p++) == 0 || c != *bp++)
155e83f7ba2SBen Gras return (0);
156e83f7ba2SBen Gras
157e83f7ba2SBen Gras return (*p == 0);
158e83f7ba2SBen Gras }
159e83f7ba2SBen Gras
160e83f7ba2SBen Gras static Search_Path *
_rtld_find_path(Search_Path * path,const char * pathstr,size_t pathlen)161e83f7ba2SBen Gras _rtld_find_path(Search_Path *path, const char *pathstr, size_t pathlen)
162e83f7ba2SBen Gras {
163e83f7ba2SBen Gras
164e83f7ba2SBen Gras for (; path != NULL; path = path->sp_next) {
165e83f7ba2SBen Gras if (pathlen == path->sp_pathlen &&
166e83f7ba2SBen Gras memcmp(path->sp_path, pathstr, pathlen) == 0)
167e83f7ba2SBen Gras return path;
168e83f7ba2SBen Gras }
169e83f7ba2SBen Gras return NULL;
170e83f7ba2SBen Gras }
171e83f7ba2SBen Gras
172e83f7ba2SBen Gras static Search_Path **
_rtld_append_path(Search_Path ** head_p,Search_Path ** path_p,const char * execname,const char * bp,const char * ep)173e83f7ba2SBen Gras _rtld_append_path(Search_Path **head_p, Search_Path **path_p,
174e83f7ba2SBen Gras const char *execname, const char *bp, const char *ep)
175e83f7ba2SBen Gras {
176e83f7ba2SBen Gras Search_Path *path;
177e83f7ba2SBen Gras char epath[MAXPATHLEN];
178e83f7ba2SBen Gras size_t len;
179e83f7ba2SBen Gras
180e83f7ba2SBen Gras len = _rtld_expand_path(epath, sizeof(epath), execname, bp, ep);
181e83f7ba2SBen Gras if (len == 0)
182e83f7ba2SBen Gras return path_p;
183e83f7ba2SBen Gras
184e83f7ba2SBen Gras if (_rtld_find_path(*head_p, bp, ep - bp) != NULL)
185e83f7ba2SBen Gras return path_p;
186e83f7ba2SBen Gras
187e83f7ba2SBen Gras path = NEW(Search_Path);
188e83f7ba2SBen Gras path->sp_pathlen = len;
189e83f7ba2SBen Gras path->sp_path = exstrdup(epath, epath + len);
190e83f7ba2SBen Gras path->sp_next = (*path_p);
191e83f7ba2SBen Gras (*path_p) = path;
192e83f7ba2SBen Gras path_p = &path->sp_next;
193e83f7ba2SBen Gras
194e83f7ba2SBen Gras dbg((" added path \"%s\"", path->sp_path));
195e83f7ba2SBen Gras return path_p;
196e83f7ba2SBen Gras }
197e83f7ba2SBen Gras
198e83f7ba2SBen Gras void
_rtld_add_paths(const char * execname,Search_Path ** path_p,const char * pathstr)199e83f7ba2SBen Gras _rtld_add_paths(const char *execname, Search_Path **path_p, const char *pathstr)
200e83f7ba2SBen Gras {
201e83f7ba2SBen Gras Search_Path **head_p = path_p;
202e83f7ba2SBen Gras
203e83f7ba2SBen Gras if (pathstr == NULL)
204e83f7ba2SBen Gras return;
205e83f7ba2SBen Gras
206e83f7ba2SBen Gras if (pathstr[0] == ':') {
207e83f7ba2SBen Gras /*
208e83f7ba2SBen Gras * Leading colon means append to current path
209e83f7ba2SBen Gras */
210e83f7ba2SBen Gras while ((*path_p) != NULL)
211e83f7ba2SBen Gras path_p = &(*path_p)->sp_next;
212e83f7ba2SBen Gras pathstr++;
213e83f7ba2SBen Gras }
214e83f7ba2SBen Gras
215e83f7ba2SBen Gras for (;;) {
216e83f7ba2SBen Gras const char *bp = pathstr;
217e83f7ba2SBen Gras const char *ep = strchr(bp, ':');
218e83f7ba2SBen Gras if (ep == NULL)
219e83f7ba2SBen Gras ep = &pathstr[strlen(pathstr)];
220e83f7ba2SBen Gras
221e83f7ba2SBen Gras path_p = _rtld_append_path(head_p, path_p, execname, bp, ep);
222e83f7ba2SBen Gras
223e83f7ba2SBen Gras if (ep[0] == '\0')
224e83f7ba2SBen Gras break;
225e83f7ba2SBen Gras pathstr = ep + 1;
226e83f7ba2SBen Gras }
227e83f7ba2SBen Gras }
228e83f7ba2SBen Gras
229e83f7ba2SBen Gras /*
230e83f7ba2SBen Gras * Process library mappings of the form:
231e83f7ba2SBen Gras * <library_name> <machdep_variable> <value,...:library_name,...> ...
232e83f7ba2SBen Gras */
233e83f7ba2SBen Gras static void
_rtld_process_mapping(Library_Xform ** lib_p,const char * bp,const char * ep)234e83f7ba2SBen Gras _rtld_process_mapping(Library_Xform **lib_p, const char *bp, const char *ep)
235e83f7ba2SBen Gras {
236e83f7ba2SBen Gras Library_Xform *hwptr = NULL;
237e83f7ba2SBen Gras const char *ptr, *key, *ekey, *lib, *elib, *l;
238e83f7ba2SBen Gras int i, j;
239e83f7ba2SBen Gras
240e83f7ba2SBen Gras dbg((" processing mapping \"%.*s\"", (int)(ep - bp), bp));
241e83f7ba2SBen Gras
242e83f7ba2SBen Gras if ((ptr = getword(&bp, ep, WS)) == NULL || ptr == bp)
243e83f7ba2SBen Gras return;
244e83f7ba2SBen Gras
245e83f7ba2SBen Gras dbg((" library \"%.*s\"", (int)(bp - ptr), ptr));
246e83f7ba2SBen Gras
247e83f7ba2SBen Gras hwptr = xmalloc(sizeof(*hwptr));
248e83f7ba2SBen Gras memset(hwptr, 0, sizeof(*hwptr));
249e83f7ba2SBen Gras hwptr->name = exstrdup(ptr, bp);
250e83f7ba2SBen Gras
251e83f7ba2SBen Gras bp++;
252e83f7ba2SBen Gras
253e83f7ba2SBen Gras if ((ptr = getword(&bp, ep, WS)) == NULL || ptr == bp) {
254e83f7ba2SBen Gras xwarnx("missing sysctl variable name");
255e83f7ba2SBen Gras goto cleanup;
256e83f7ba2SBen Gras }
257e83f7ba2SBen Gras
258e83f7ba2SBen Gras dbg((" sysctl \"%.*s\"", (int)(bp - ptr), ptr));
259e83f7ba2SBen Gras
260e83f7ba2SBen Gras hwptr->ctlname = exstrdup(ptr, bp);
261e83f7ba2SBen Gras
262e83f7ba2SBen Gras for (i = 0; bp++, (ptr = getword(&bp, ep, WS)) != NULL;) {
263e83f7ba2SBen Gras dbg((" ptr = %.*s", (int)(bp - ptr), ptr));
264e83f7ba2SBen Gras if (ptr == bp)
265e83f7ba2SBen Gras continue;
266e83f7ba2SBen Gras
267e83f7ba2SBen Gras if (i == RTLD_MAX_ENTRY) {
268e83f7ba2SBen Gras no_more:
269e83f7ba2SBen Gras xwarnx("maximum library entries exceeded `%s'",
270e83f7ba2SBen Gras hwptr->name);
271e83f7ba2SBen Gras goto cleanup;
272e83f7ba2SBen Gras }
273e83f7ba2SBen Gras if ((key = getstr(&ptr, bp, ":")) == NULL) {
274e83f7ba2SBen Gras xwarnx("missing sysctl variable value for `%s'",
275e83f7ba2SBen Gras hwptr->name);
276e83f7ba2SBen Gras goto cleanup;
277e83f7ba2SBen Gras }
278e83f7ba2SBen Gras ekey = ptr++;
279e83f7ba2SBen Gras if ((lib = getstr(&ptr, bp, ":")) == NULL) {
280e83f7ba2SBen Gras xwarnx("missing sysctl library list for `%s'",
281e83f7ba2SBen Gras hwptr->name);
282e83f7ba2SBen Gras goto cleanup;
283e83f7ba2SBen Gras }
284e83f7ba2SBen Gras elib = ptr; /* No need to advance */
285e83f7ba2SBen Gras for (j = 0; (l = getstr(&lib, elib, ",")) != NULL;
286e83f7ba2SBen Gras j++, lib++) {
287e83f7ba2SBen Gras if (j == RTLD_MAX_LIBRARY) {
288e83f7ba2SBen Gras xwarnx("maximum library entries exceeded `%s'",
289e83f7ba2SBen Gras hwptr->name);
290e83f7ba2SBen Gras goto cleanup;
291e83f7ba2SBen Gras }
292e83f7ba2SBen Gras dbg((" library \"%.*s\"", (int)(lib - l), l));
293e83f7ba2SBen Gras hwptr->entry[i].library[j] = exstrdup(l, lib);
294e83f7ba2SBen Gras }
295e83f7ba2SBen Gras if (j == 0) {
296e83f7ba2SBen Gras xwarnx("No library map entries for `%s/%.*s'",
297e83f7ba2SBen Gras hwptr->name, (int)(bp - ptr), ptr);
298e83f7ba2SBen Gras goto cleanup;
299e83f7ba2SBen Gras }
300e83f7ba2SBen Gras j = i;
301e83f7ba2SBen Gras for (; (l = getstr(&key, ekey, ",")) != NULL; i++, key++) {
302e83f7ba2SBen Gras /*
303e83f7ba2SBen Gras * Allow empty key (it is valid as string
304e83f7ba2SBen Gras * value). Thus, we loop at least once and
305e83f7ba2SBen Gras * `i' is incremented.
306e83f7ba2SBen Gras */
307e83f7ba2SBen Gras
308e83f7ba2SBen Gras dbg((" key \"%.*s\"", (int)(key - l), l));
309e83f7ba2SBen Gras if (i == RTLD_MAX_ENTRY)
310e83f7ba2SBen Gras goto no_more;
311e83f7ba2SBen Gras if (i != j)
312e83f7ba2SBen Gras (void)memcpy(hwptr->entry[i].library,
313e83f7ba2SBen Gras hwptr->entry[j].library,
314e83f7ba2SBen Gras sizeof(hwptr->entry[j].library));
315e83f7ba2SBen Gras hwptr->entry[i].value = exstrdup(l, key);
316e83f7ba2SBen Gras }
317e83f7ba2SBen Gras }
318e83f7ba2SBen Gras
319e83f7ba2SBen Gras if (i == 0) {
320e83f7ba2SBen Gras xwarnx("No library entries for `%s'", hwptr->name);
321e83f7ba2SBen Gras goto cleanup;
322e83f7ba2SBen Gras }
323e83f7ba2SBen Gras
324e83f7ba2SBen Gras hwptr->next = *lib_p;
325e83f7ba2SBen Gras *lib_p = hwptr;
326e83f7ba2SBen Gras
327e83f7ba2SBen Gras return;
328e83f7ba2SBen Gras
329e83f7ba2SBen Gras cleanup:
330e83f7ba2SBen Gras if (hwptr->name)
331e83f7ba2SBen Gras xfree(hwptr->name);
332e83f7ba2SBen Gras xfree(hwptr);
333e83f7ba2SBen Gras }
334e83f7ba2SBen Gras
335e83f7ba2SBen Gras void
_rtld_process_hints(const char * execname,Search_Path ** path_p,Library_Xform ** lib_p,const char * fname)336e83f7ba2SBen Gras _rtld_process_hints(const char *execname, Search_Path **path_p,
337e83f7ba2SBen Gras Library_Xform **lib_p, const char *fname)
338e83f7ba2SBen Gras {
339e83f7ba2SBen Gras int fd;
340e83f7ba2SBen Gras char *buf, small[128];
341e83f7ba2SBen Gras const char *b, *ep, *ptr;
342e83f7ba2SBen Gras struct stat st;
343e83f7ba2SBen Gras ssize_t sz;
344e83f7ba2SBen Gras Search_Path **head_p = path_p;
345f14fb602SLionel Sambuc
346e83f7ba2SBen Gras if ((fd = open(fname, O_RDONLY)) == -1) {
347e83f7ba2SBen Gras /* Don't complain */
348e83f7ba2SBen Gras return;
349e83f7ba2SBen Gras }
350e83f7ba2SBen Gras
351e83f7ba2SBen Gras /* Try to avoid mmap/stat on the file. */
352e83f7ba2SBen Gras buf = small;
353e83f7ba2SBen Gras buf[0] = '\0';
354e83f7ba2SBen Gras sz = read(fd, buf, sizeof(small));
355e83f7ba2SBen Gras if (sz == -1) {
356e83f7ba2SBen Gras xwarn("read: %s", fname);
357e83f7ba2SBen Gras (void)close(fd);
358e83f7ba2SBen Gras return;
359e83f7ba2SBen Gras }
360e83f7ba2SBen Gras if (sz >= (ssize_t)sizeof(small)) {
361e83f7ba2SBen Gras if (fstat(fd, &st) == -1) {
362e83f7ba2SBen Gras /* Complain */
363e83f7ba2SBen Gras xwarn("fstat: %s", fname);
364e83f7ba2SBen Gras (void)close(fd);
365e83f7ba2SBen Gras return;
366e83f7ba2SBen Gras }
367e83f7ba2SBen Gras
368e83f7ba2SBen Gras sz = (ssize_t) st.st_size;
369e83f7ba2SBen Gras
370e83f7ba2SBen Gras buf = mmap(0, sz, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
371e83f7ba2SBen Gras if (buf == MAP_FAILED) {
372e83f7ba2SBen Gras xwarn("mmap: %s", fname);
373e83f7ba2SBen Gras (void)close(fd);
374e83f7ba2SBen Gras return;
375e83f7ba2SBen Gras }
376e83f7ba2SBen Gras }
377e83f7ba2SBen Gras (void)close(fd);
378e83f7ba2SBen Gras
379e83f7ba2SBen Gras while ((*path_p) != NULL)
380e83f7ba2SBen Gras path_p = &(*path_p)->sp_next;
381e83f7ba2SBen Gras
382e83f7ba2SBen Gras for (b = buf, ep = buf + sz; b < ep; b++) {
383e83f7ba2SBen Gras (void)getcstr(&b, ep, WS);
384e83f7ba2SBen Gras if (b == ep)
385e83f7ba2SBen Gras break;
386e83f7ba2SBen Gras
387e83f7ba2SBen Gras ptr = getstr(&b, ep, "\n#");
388e83f7ba2SBen Gras if (*ptr == '/') {
389e83f7ba2SBen Gras /*
390e83f7ba2SBen Gras * Since '/' != '\n' and != '#', we know ptr <
391e83f7ba2SBen Gras * b. And we will stop when b[-1] == '/'.
392e83f7ba2SBen Gras */
393e83f7ba2SBen Gras while (b[-1] == ' ' || b[-1] == '\t')
394e83f7ba2SBen Gras b--;
395e83f7ba2SBen Gras path_p = _rtld_append_path(head_p, path_p, execname,
396e83f7ba2SBen Gras ptr, b);
397e83f7ba2SBen Gras } else
398e83f7ba2SBen Gras _rtld_process_mapping(lib_p, ptr, b);
399e83f7ba2SBen Gras
400e83f7ba2SBen Gras /*
401e83f7ba2SBen Gras * b points one of ' ', \t, \n, # or equal to ep. So,
402e83f7ba2SBen Gras * make sure we are at newline or end of string.
403e83f7ba2SBen Gras */
404e83f7ba2SBen Gras (void)getstr(&b, ep, "\n");
405e83f7ba2SBen Gras }
406e83f7ba2SBen Gras
407e83f7ba2SBen Gras if (buf != small)
408e83f7ba2SBen Gras (void)munmap(buf, sz);
409e83f7ba2SBen Gras }
410e83f7ba2SBen Gras
411e83f7ba2SBen Gras /* Basic name -> sysctl MIB translation */
412e83f7ba2SBen Gras int
_rtld_sysctl(const char * name,void * oldp,size_t * oldlen)413e83f7ba2SBen Gras _rtld_sysctl(const char *name, void *oldp, size_t *oldlen)
414e83f7ba2SBen Gras {
415e83f7ba2SBen Gras const char *node, *ep;
416e83f7ba2SBen Gras struct sysctlnode query, *result, *newresult;
417e83f7ba2SBen Gras int mib[CTL_MAXNAME], r;
418e83f7ba2SBen Gras size_t res_size, n, i;
419e83f7ba2SBen Gras u_int miblen = 0;
420e83f7ba2SBen Gras
421e83f7ba2SBen Gras /* Start with 16 entries, will grow it up as needed. */
422e83f7ba2SBen Gras res_size = 16 * sizeof(struct sysctlnode);
423e83f7ba2SBen Gras result = xmalloc(res_size);
424e83f7ba2SBen Gras if (result == NULL)
425e83f7ba2SBen Gras return (-1);
426e83f7ba2SBen Gras
427e83f7ba2SBen Gras ep = name + strlen(name);
428e83f7ba2SBen Gras do {
429e83f7ba2SBen Gras i = ~0ul;
430e83f7ba2SBen Gras while (*name == '/' || *name == '.')
431e83f7ba2SBen Gras name++;
432e83f7ba2SBen Gras if (name >= ep)
433e83f7ba2SBen Gras break;
434e83f7ba2SBen Gras
435e83f7ba2SBen Gras mib[miblen] = CTL_QUERY;
436e83f7ba2SBen Gras memset(&query, 0, sizeof(query));
437e83f7ba2SBen Gras query.sysctl_flags = SYSCTL_VERSION;
438e83f7ba2SBen Gras
439e83f7ba2SBen Gras n = res_size;
440e83f7ba2SBen Gras if (sysctl(mib, miblen + 1, result, &n, &query,
441e83f7ba2SBen Gras sizeof(query)) == -1) {
442e83f7ba2SBen Gras if (errno != ENOMEM)
443e83f7ba2SBen Gras goto bad;
444e83f7ba2SBen Gras /* Grow up result */
445e83f7ba2SBen Gras res_size = n;
446e83f7ba2SBen Gras newresult = xrealloc(result, res_size);
447e83f7ba2SBen Gras if (newresult == NULL)
448e83f7ba2SBen Gras goto bad;
449e83f7ba2SBen Gras result = newresult;
450e83f7ba2SBen Gras if (sysctl(mib, miblen + 1, result, &n, &query,
451e83f7ba2SBen Gras sizeof(query)) == -1)
452e83f7ba2SBen Gras goto bad;
453e83f7ba2SBen Gras }
454e83f7ba2SBen Gras n /= sizeof(struct sysctlnode);
455e83f7ba2SBen Gras
456e83f7ba2SBen Gras node = getstr(&name, ep, "./");
457e83f7ba2SBen Gras
458e83f7ba2SBen Gras for (i = 0; i < n; i++)
459e83f7ba2SBen Gras if (matchstr(result[i].sysctl_name, node, name)) {
460e83f7ba2SBen Gras mib[miblen] = result[i].sysctl_num;
461e83f7ba2SBen Gras miblen++;
462e83f7ba2SBen Gras break;
463e83f7ba2SBen Gras }
464e83f7ba2SBen Gras } while (name < ep && miblen <= CTL_MAXNAME);
465e83f7ba2SBen Gras
466e83f7ba2SBen Gras if (name < ep || i == ~0ul)
467e83f7ba2SBen Gras goto bad;
468e83f7ba2SBen Gras r = SYSCTL_TYPE(result[i].sysctl_flags);
469e83f7ba2SBen Gras
470e83f7ba2SBen Gras xfree(result);
471e83f7ba2SBen Gras if (sysctl(mib, miblen, oldp, oldlen, NULL, 0) == -1)
472e83f7ba2SBen Gras return (-1);
473e83f7ba2SBen Gras return r;
474e83f7ba2SBen Gras
475e83f7ba2SBen Gras bad:
476e83f7ba2SBen Gras xfree(result);
477e83f7ba2SBen Gras return (-1);
478e83f7ba2SBen Gras }
479