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;
41 static void lm_add (const char *, const char *, const char *);
42 static void lm_free (struct lm_list *);
43 static char * lml_find (struct lm_list *, const char *);
44 static struct lm_list * lmp_find (const char *);
45 static struct lm_list * lmp_init (char *);
46 static const char * quickbasename (const char *);
48 #define iseol(c) (((c) == '#') || ((c) == '\0') || \
49 ((c) == '\n') || ((c) == '\r'))
57 char prog[MAXPATHLEN];
58 char line[MAXPATHLEN + 2];
60 dbg("%s()", __func__);
62 TAILQ_INIT(&lmp_head);
64 if ((fp = fopen(_PATH_LIBMAP_CONF, "r")) == NULL)
68 while ((cp = fgets(line, MAXPATHLEN + 1, fp)) != NULL) {
71 /* Skip over leading space */
72 while (isspace(*cp)) cp++;
74 /* Found a comment or EOL */
75 if (iseol(*cp)) continue;
77 /* Found a constraint selector */
81 /* Skip leading space */
82 while (isspace(*cp)) cp++;
84 /* Found comment, EOL or end of selector */
85 if (iseol(*cp) || *cp == ']')
89 /* Skip to end of word */
90 while (!isspace(*cp) && !iseol(*cp) && *cp != ']')
93 /* Skip and zero out trailing space */
94 while (isspace(*cp)) *cp++ = '\0';
96 /* Check if there is a closing brace */
97 if (*cp != ']') continue;
99 /* Terminate string if there was no trailing space */
103 * There should be nothing except whitespace or comment
104 from this point to the end of the line.
106 while(isspace(*cp)) cp++;
107 if (!iseol(*cp)) continue;
114 /* Parse the 'from' candidate. */
116 while (!isspace(*cp) && !iseol(*cp)) cp++;
118 /* Skip and zero out the trailing whitespace */
119 while (isspace(*cp)) *cp++ = '\0';
121 /* Found a comment or EOL */
122 if (iseol(*cp)) continue;
124 /* Parse 'to' mapping */
126 while (!isspace(*cp) && !iseol(*cp)) cp++;
128 /* Skip and zero out the trailing whitespace */
129 while (isspace(*cp)) *cp++ = '\0';
131 /* Should be no extra tokens at this point */
132 if (!iseol(*cp)) continue;
142 lm_free (struct lm_list *lml)
146 dbg("%s(%p)", __func__, lml);
148 while (!TAILQ_EMPTY(lml)) {
149 lm = TAILQ_FIRST(lml);
150 TAILQ_REMOVE(lml, lm, lm_link);
163 dbg("%s()", __func__);
165 while (!TAILQ_EMPTY(&lmp_head)) {
166 lmp = TAILQ_FIRST(&lmp_head);
167 TAILQ_REMOVE(&lmp_head, lmp, lmp_link);
176 lm_add (const char *p, const char *f, const char *t)
184 dbg("%s(\"%s\", \"%s\", \"%s\")", __func__, p, f, t);
186 if ((lml = lmp_find(p)) == NULL)
187 lml = lmp_init(xstrdup(p));
189 lm = xmalloc(sizeof(struct lm));
192 TAILQ_INSERT_HEAD(lml, lm, lm_link);
196 lm_find (const char *p, const char *f)
201 dbg("%s(\"%s\", \"%s\")", __func__, p, f);
203 if (p != NULL && (lml = lmp_find(p)) != NULL) {
204 t = lml_find(lml, f);
207 * Add a global mapping if we have
208 * a successful constrained match.
214 lml = lmp_find("$DEFAULT$");
216 return (lml_find(lml, f));
221 /* Given a libmap translation list and a library name, return the
222 replacement library, or NULL */
225 lm_findn (const char *p, const char *f, const int n)
227 char pathbuf[64], *s, *t;
229 if (n < sizeof(pathbuf) - 1) {
230 memcpy(pathbuf, f, n);
245 lml_find (struct lm_list *lmh, const char *f)
249 dbg("%s(%p, \"%s\")", __func__, lmh, f);
251 TAILQ_FOREACH(lm, lmh, lm_link)
252 if (strcmp(f, lm->f) == 0)
257 /* Given an executable name, return a pointer to the translation list or
258 NULL if no matches */
259 static struct lm_list *
260 lmp_find (const char *n)
264 dbg("%s(\"%s\")", __func__, n);
266 TAILQ_FOREACH(lmp, &lmp_head, lmp_link)
267 if ((lmp->type == T_EXACT && strcmp(n, lmp->p) == 0) ||
268 (lmp->type == T_DIRECTORY && strncmp(n, lmp->p, strlen(lmp->p)) == 0) ||
269 (lmp->type == T_BASENAME && strcmp(quickbasename(n), lmp->p) == 0))
274 static struct lm_list *
279 dbg("%s(\"%s\")", __func__, n);
281 lmp = xmalloc(sizeof(struct lmp));
283 if (n[strlen(n)-1] == '/')
284 lmp->type = T_DIRECTORY;
285 else if (strchr(n,'/') == NULL)
286 lmp->type = T_BASENAME;
289 TAILQ_INIT(&lmp->lml);
290 TAILQ_INSERT_HEAD(&lmp_head, lmp, lmp_link);
295 /* libc basename is overkill. Return a pointer to the character after the
296 last /, or the original string if there are no slashes. */
298 quickbasename (const char *path)
300 const char *p = path;
301 for (; *path; path++)