2 * $FreeBSD: src/libexec/rtld-elf/libmap.c,v 1.15 2006/01/31 06:08:28 peter Exp $
10 #include <sys/param.h>
16 #ifndef _PATH_LIBMAP_CONF
17 #define _PATH_LIBMAP_CONF "/etc/libmap.conf"
20 TAILQ_HEAD(lm_list
, lm
);
25 TAILQ_ENTRY(lm
) lm_link
;
28 TAILQ_HEAD(lmp_list
, lmp
) lmp_head
= TAILQ_HEAD_INITIALIZER(lmp_head
);
31 enum { T_EXACT
=0, T_BASENAME
, T_DIRECTORY
} type
;
33 TAILQ_ENTRY(lmp
) lmp_link
;
38 static void lmc_parse (FILE *);
39 static void lm_add (const char *, const char *, const char *);
40 static void lm_free (struct lm_list
*);
41 static char * lml_find (struct lm_list
*, const char *);
42 static struct lm_list
* lmp_find (const char *);
43 static struct lm_list
* lmp_init (char *);
44 static const char * quickbasename (const char *);
45 static int readstrfn (void * cookie
, char *buf
, int len
);
46 static int closestrfn (void * cookie
);
48 #define iseol(c) (((c) == '#') || ((c) == '\0') || \
49 ((c) == '\n') || ((c) == '\r'))
52 lm_init (char *libmap_override
)
56 dbg("%s(\"%s\")", __func__
, libmap_override
);
58 TAILQ_INIT(&lmp_head
);
60 fp
= fopen(_PATH_LIBMAP_CONF
, "r");
66 if (libmap_override
) {
68 /* do some character replacement to make $LIBMAP look like a
69 text file, then "open" it with funopen */
70 libmap_override
= xstrdup(libmap_override
);
72 for (p
= libmap_override
; *p
; p
++) {
80 fp
= funopen(libmap_override
, readstrfn
, NULL
, NULL
, closestrfn
);
87 return (lm_count
== 0);
95 char prog
[MAXPATHLEN
];
96 char line
[MAXPATHLEN
+ 2];
98 dbg("%s(%p)", __func__
, fp
);
101 while ((cp
= fgets(line
, MAXPATHLEN
+ 1, fp
)) != NULL
) {
104 /* Skip over leading space */
105 while (isspace(*cp
)) cp
++;
107 /* Found a comment or EOL */
108 if (iseol(*cp
)) continue;
110 /* Found a constraint selector */
114 /* Skip leading space */
115 while (isspace(*cp
)) cp
++;
117 /* Found comment, EOL or end of selector */
118 if (iseol(*cp
) || *cp
== ']')
122 /* Skip to end of word */
123 while (!isspace(*cp
) && !iseol(*cp
) && *cp
!= ']')
126 /* Skip and zero out trailing space */
127 while (isspace(*cp
)) *cp
++ = '\0';
129 /* Check if there is a closing brace */
130 if (*cp
!= ']') continue;
132 /* Terminate string if there was no trailing space */
136 * There should be nothing except whitespace or comment
137 from this point to the end of the line.
139 while(isspace(*cp
)) cp
++;
140 if (!iseol(*cp
)) continue;
147 /* Parse the 'from' candidate. */
149 while (!isspace(*cp
) && !iseol(*cp
)) cp
++;
151 /* Skip and zero out the trailing whitespace */
152 while (isspace(*cp
)) *cp
++ = '\0';
154 /* Found a comment or EOL */
155 if (iseol(*cp
)) continue;
157 /* Parse 'to' mapping */
159 while (!isspace(*cp
) && !iseol(*cp
)) cp
++;
161 /* Skip and zero out the trailing whitespace */
162 while (isspace(*cp
)) *cp
++ = '\0';
164 /* Should be no extra tokens at this point */
165 if (!iseol(*cp
)) continue;
173 lm_free (struct lm_list
*lml
)
177 dbg("%s(%p)", __func__
, lml
);
179 while (!TAILQ_EMPTY(lml
)) {
180 lm
= TAILQ_FIRST(lml
);
181 TAILQ_REMOVE(lml
, lm
, lm_link
);
194 dbg("%s()", __func__
);
196 while (!TAILQ_EMPTY(&lmp_head
)) {
197 lmp
= TAILQ_FIRST(&lmp_head
);
198 TAILQ_REMOVE(&lmp_head
, lmp
, lmp_link
);
207 lm_add (const char *p
, const char *f
, const char *t
)
215 dbg("%s(\"%s\", \"%s\", \"%s\")", __func__
, p
, f
, t
);
217 if ((lml
= lmp_find(p
)) == NULL
)
218 lml
= lmp_init(xstrdup(p
));
220 lm
= xmalloc(sizeof(struct lm
));
223 TAILQ_INSERT_HEAD(lml
, lm
, lm_link
);
228 lm_find (const char *p
, const char *f
)
233 dbg("%s(\"%s\", \"%s\")", __func__
, p
, f
);
235 if (p
!= NULL
&& (lml
= lmp_find(p
)) != NULL
) {
236 t
= lml_find(lml
, f
);
239 * Add a global mapping if we have
240 * a successful constrained match.
246 lml
= lmp_find("$DEFAULT$");
248 return (lml_find(lml
, f
));
254 lml_find (struct lm_list
*lmh
, const char *f
)
258 dbg("%s(%p, \"%s\")", __func__
, lmh
, f
);
260 TAILQ_FOREACH(lm
, lmh
, lm_link
)
261 if (strcmp(f
, lm
->f
) == 0)
266 /* Given an executable name, return a pointer to the translation list or
267 NULL if no matches */
268 static struct lm_list
*
269 lmp_find (const char *n
)
273 dbg("%s(\"%s\")", __func__
, n
);
275 TAILQ_FOREACH(lmp
, &lmp_head
, lmp_link
)
276 if ((lmp
->type
== T_EXACT
&& strcmp(n
, lmp
->p
) == 0) ||
277 (lmp
->type
== T_DIRECTORY
&& strncmp(n
, lmp
->p
, strlen(lmp
->p
)) == 0) ||
278 (lmp
->type
== T_BASENAME
&& strcmp(quickbasename(n
), lmp
->p
) == 0))
283 static struct lm_list
*
288 dbg("%s(\"%s\")", __func__
, n
);
290 lmp
= xmalloc(sizeof(struct lmp
));
292 if (n
[strlen(n
)-1] == '/')
293 lmp
->type
= T_DIRECTORY
;
294 else if (strchr(n
,'/') == NULL
)
295 lmp
->type
= T_BASENAME
;
298 TAILQ_INIT(&lmp
->lml
);
299 TAILQ_INSERT_HEAD(&lmp_head
, lmp
, lmp_link
);
304 /* libc basename is overkill. Return a pointer to the character after the
305 last /, or the original string if there are no slashes. */
307 quickbasename (const char *path
)
309 const char *p
= path
;
310 for (; *path
; path
++) {
318 readstrfn(void * cookie
, char *buf
, int len
)
320 static char *current
;
327 left
= strlen(cookie
);
329 while (*current
&& left
&& len
) {
339 closestrfn(void * cookie
)