10 #include <sys/param.h>
16 #ifndef _PATH_LIBMAP_CONF
17 #define _PATH_LIBMAP_CONF "/etc/libmap.conf"
21 #undef _PATH_LIBMAP_CONF
22 #define _PATH_LIBMAP_CONF "/etc/libmap32.conf"
25 TAILQ_HEAD(lm_list
, lm
);
30 TAILQ_ENTRY(lm
) lm_link
;
33 TAILQ_HEAD(lmp_list
, lmp
) lmp_head
= TAILQ_HEAD_INITIALIZER(lmp_head
);
36 enum { T_EXACT
=0, T_BASENAME
, T_DIRECTORY
} type
;
38 TAILQ_ENTRY(lmp
) lmp_link
;
43 static void lmc_parse (FILE *);
44 static void lm_add (const char *, const char *, const char *);
45 static void lm_free (struct lm_list
*);
46 static char * lml_find (struct lm_list
*, const char *);
47 static struct lm_list
* lmp_find (const char *);
48 static struct lm_list
* lmp_init (char *);
49 static const char * quickbasename (const char *);
50 static int readstrfn (void * cookie
, char *buf
, int len
);
51 static int closestrfn (void * cookie
);
53 #define iseol(c) (((c) == '#') || ((c) == '\0') || \
54 ((c) == '\n') || ((c) == '\r'))
57 lm_init (char *libmap_override
)
61 dbg("%s(\"%s\")", __func__
, libmap_override
);
63 TAILQ_INIT(&lmp_head
);
65 fp
= fopen(_PATH_LIBMAP_CONF
, "r");
71 if (libmap_override
) {
73 /* do some character replacement to make $LIBMAP look like a
74 text file, then "open" it with funopen */
75 libmap_override
= xstrdup(libmap_override
);
77 for (p
= libmap_override
; *p
; p
++) {
85 fp
= funopen(libmap_override
, readstrfn
, NULL
, NULL
, closestrfn
);
92 return (lm_count
== 0);
100 char prog
[MAXPATHLEN
];
101 char line
[MAXPATHLEN
+ 2];
103 dbg("%s(%p)", __func__
, fp
);
106 while ((cp
= fgets(line
, MAXPATHLEN
+ 1, fp
)) != NULL
) {
109 /* Skip over leading space */
110 while (isspace(*cp
)) cp
++;
112 /* Found a comment or EOL */
113 if (iseol(*cp
)) continue;
115 /* Found a constraint selector */
119 /* Skip leading space */
120 while (isspace(*cp
)) cp
++;
122 /* Found comment, EOL or end of selector */
123 if (iseol(*cp
) || *cp
== ']')
127 /* Skip to end of word */
128 while (!isspace(*cp
) && !iseol(*cp
) && *cp
!= ']')
131 /* Skip and zero out trailing space */
132 while (isspace(*cp
)) *cp
++ = '\0';
134 /* Check if there is a closing brace */
135 if (*cp
!= ']') continue;
137 /* Terminate string if there was no trailing space */
141 * There should be nothing except whitespace or comment
142 from this point to the end of the line.
144 while(isspace(*cp
)) cp
++;
145 if (!iseol(*cp
)) continue;
152 /* Parse the 'from' candidate. */
154 while (!isspace(*cp
) && !iseol(*cp
)) cp
++;
156 /* Skip and zero out the trailing whitespace */
157 while (isspace(*cp
)) *cp
++ = '\0';
159 /* Found a comment or EOL */
160 if (iseol(*cp
)) continue;
162 /* Parse 'to' mapping */
164 while (!isspace(*cp
) && !iseol(*cp
)) cp
++;
166 /* Skip and zero out the trailing whitespace */
167 while (isspace(*cp
)) *cp
++ = '\0';
169 /* Should be no extra tokens at this point */
170 if (!iseol(*cp
)) continue;
178 lm_free (struct lm_list
*lml
)
182 dbg("%s(%p)", __func__
, lml
);
184 while (!TAILQ_EMPTY(lml
)) {
185 lm
= TAILQ_FIRST(lml
);
186 TAILQ_REMOVE(lml
, lm
, lm_link
);
199 dbg("%s()", __func__
);
201 while (!TAILQ_EMPTY(&lmp_head
)) {
202 lmp
= TAILQ_FIRST(&lmp_head
);
203 TAILQ_REMOVE(&lmp_head
, lmp
, lmp_link
);
212 lm_add (const char *p
, const char *f
, const char *t
)
220 dbg("%s(\"%s\", \"%s\", \"%s\")", __func__
, p
, f
, t
);
222 if ((lml
= lmp_find(p
)) == NULL
)
223 lml
= lmp_init(xstrdup(p
));
225 lm
= xmalloc(sizeof(struct lm
));
228 TAILQ_INSERT_HEAD(lml
, lm
, lm_link
);
233 lm_find (const char *p
, const char *f
)
238 dbg("%s(\"%s\", \"%s\")", __func__
, p
, f
);
240 if (p
!= NULL
&& (lml
= lmp_find(p
)) != NULL
) {
241 t
= lml_find(lml
, f
);
244 * Add a global mapping if we have
245 * a successful constrained match.
251 lml
= lmp_find("$DEFAULT$");
253 return (lml_find(lml
, f
));
258 /* Given a libmap translation list and a library name, return the
259 replacement library, or NULL */
262 lm_findn (const char *p
, const char *f
, const int n
)
264 char pathbuf
[64], *s
, *t
;
266 if (n
< sizeof(pathbuf
) - 1)
280 lml_find (struct lm_list
*lmh
, const char *f
)
284 dbg("%s(%p, \"%s\")", __func__
, lmh
, f
);
286 TAILQ_FOREACH(lm
, lmh
, lm_link
)
287 if (strcmp(f
, lm
->f
) == 0)
292 /* Given an executable name, return a pointer to the translation list or
293 NULL if no matches */
294 static struct lm_list
*
295 lmp_find (const char *n
)
299 dbg("%s(\"%s\")", __func__
, n
);
301 TAILQ_FOREACH(lmp
, &lmp_head
, lmp_link
)
302 if ((lmp
->type
== T_EXACT
&& strcmp(n
, lmp
->p
) == 0) ||
303 (lmp
->type
== T_DIRECTORY
&& strncmp(n
, lmp
->p
, strlen(lmp
->p
)) == 0) ||
304 (lmp
->type
== T_BASENAME
&& strcmp(quickbasename(n
), lmp
->p
) == 0))
309 static struct lm_list
*
314 dbg("%s(\"%s\")", __func__
, n
);
316 lmp
= xmalloc(sizeof(struct lmp
));
318 if (n
[strlen(n
)-1] == '/')
319 lmp
->type
= T_DIRECTORY
;
320 else if (strchr(n
,'/') == NULL
)
321 lmp
->type
= T_BASENAME
;
324 TAILQ_INIT(&lmp
->lml
);
325 TAILQ_INSERT_HEAD(&lmp_head
, lmp
, lmp_link
);
330 /* libc basename is overkill. Return a pointer to the character after the
331 last /, or the original string if there are no slashes. */
333 quickbasename (const char *path
)
335 const char *p
= path
;
336 for (; *path
; path
++) {
344 readstrfn(void * cookie
, char *buf
, int len
)
346 static char *current
;
353 left
= strlen(cookie
);
355 while (*current
&& left
&& len
) {
365 closestrfn(void * cookie
)