129ade362SMatthew N. Dodd /* 229ade362SMatthew N. Dodd * $FreeBSD$ 329ade362SMatthew N. Dodd */ 429ade362SMatthew N. Dodd 529ade362SMatthew N. Dodd #include <stdio.h> 629ade362SMatthew N. Dodd #include <ctype.h> 729ade362SMatthew N. Dodd #include <string.h> 829ade362SMatthew N. Dodd #include <stdlib.h> 929ade362SMatthew N. Dodd #include <sys/queue.h> 1029ade362SMatthew N. Dodd #include <sys/param.h> 1129ade362SMatthew N. Dodd 123467e8b8SMatthew N. Dodd #include "debug.h" 133467e8b8SMatthew N. Dodd #include "rtld.h" 143467e8b8SMatthew N. Dodd 1529ade362SMatthew N. Dodd #ifndef _PATH_LIBMAP_CONF 1629ade362SMatthew N. Dodd #define _PATH_LIBMAP_CONF "/etc/libmap.conf" 1729ade362SMatthew N. Dodd #endif 1829ade362SMatthew N. Dodd 1929ade362SMatthew N. Dodd TAILQ_HEAD(lm_list, lm); 2029ade362SMatthew N. Dodd struct lm { 2129ade362SMatthew N. Dodd char *f; 2229ade362SMatthew N. Dodd char *t; 2329ade362SMatthew N. Dodd 2429ade362SMatthew N. Dodd TAILQ_ENTRY(lm) lm_link; 2529ade362SMatthew N. Dodd }; 2629ade362SMatthew N. Dodd 2729ade362SMatthew N. Dodd TAILQ_HEAD(lmp_list, lmp) lmp_head = TAILQ_HEAD_INITIALIZER(lmp_head); 2829ade362SMatthew N. Dodd struct lmp { 2929ade362SMatthew N. Dodd char *p; 3029ade362SMatthew N. Dodd struct lm_list lml; 3129ade362SMatthew N. Dodd TAILQ_ENTRY(lmp) lmp_link; 3229ade362SMatthew N. Dodd }; 3329ade362SMatthew N. Dodd 3429ade362SMatthew N. Dodd static void lm_add (char *, char *, char *); 3529ade362SMatthew N. Dodd static void lm_free (struct lm_list *); 3629ade362SMatthew N. Dodd static char * lml_find (struct lm_list *, const char *); 3729ade362SMatthew N. Dodd static struct lm_list * lmp_find (const char *); 3829ade362SMatthew N. Dodd static struct lm_list * lmp_init (char *); 3929ade362SMatthew N. Dodd 40623b6bd2SMatthew N. Dodd #define iseol(c) (((c) == '#') || ((c) == '\0') || \ 41623b6bd2SMatthew N. Dodd ((c) == '\n') || ((c) == '\r')) 42623b6bd2SMatthew N. Dodd 4329ade362SMatthew N. Dodd void 4429ade362SMatthew N. Dodd lm_init (void) 4529ade362SMatthew N. Dodd { 4629ade362SMatthew N. Dodd FILE *fp; 4729ade362SMatthew N. Dodd char *cp; 4829ade362SMatthew N. Dodd char *f, *t, *p; 4929ade362SMatthew N. Dodd char prog[MAXPATHLEN]; 5029ade362SMatthew N. Dodd char line[MAXPATHLEN + 2]; 5129ade362SMatthew N. Dodd 5229ade362SMatthew N. Dodd TAILQ_INIT(&lmp_head); 5329ade362SMatthew N. Dodd 5429ade362SMatthew N. Dodd if ((fp = fopen(_PATH_LIBMAP_CONF, "r")) == NULL) 5529ade362SMatthew N. Dodd return; 5629ade362SMatthew N. Dodd 5729ade362SMatthew N. Dodd p = NULL; 5829ade362SMatthew N. Dodd while ((cp = fgets(line, MAXPATHLEN + 1, fp)) != NULL) { 5929ade362SMatthew N. Dodd t = f = NULL; 60623b6bd2SMatthew N. Dodd 6129ade362SMatthew N. Dodd /* Skip over leading space */ 62623b6bd2SMatthew N. Dodd while (isspace(*cp)) cp++; 63623b6bd2SMatthew N. Dodd 6429ade362SMatthew N. Dodd /* Found a comment or EOL */ 65486089f0SAlexander Kabaev if (iseol(*cp)) continue; 66623b6bd2SMatthew N. Dodd 67623b6bd2SMatthew N. Dodd /* Found a constraint selector */ 6829ade362SMatthew N. Dodd if (*cp == '[') { 6929ade362SMatthew N. Dodd cp++; 70623b6bd2SMatthew N. Dodd 7129ade362SMatthew N. Dodd /* Skip leading space */ 72623b6bd2SMatthew N. Dodd while (isspace(*cp)) cp++; 73623b6bd2SMatthew N. Dodd 7429ade362SMatthew N. Dodd /* Found comment, EOL or end of selector */ 75486089f0SAlexander Kabaev if (iseol(*cp) || *cp == ']') 76486089f0SAlexander Kabaev continue; 77623b6bd2SMatthew N. Dodd 78486089f0SAlexander Kabaev p = cp++; 7929ade362SMatthew N. Dodd /* Skip to end of word */ 80486089f0SAlexander Kabaev while (!isspace(*cp) && !iseol(*cp) && *cp != ']') 81486089f0SAlexander Kabaev cp++; 82623b6bd2SMatthew N. Dodd 83623b6bd2SMatthew N. Dodd /* Skip and zero out trailing space */ 84623b6bd2SMatthew N. Dodd while (isspace(*cp)) *cp++ = '\0'; 85623b6bd2SMatthew N. Dodd 86623b6bd2SMatthew N. Dodd /* Check if there is a closing brace */ 87486089f0SAlexander Kabaev if (*cp != ']') continue; 88623b6bd2SMatthew N. Dodd 89623b6bd2SMatthew N. Dodd /* Terminate string if there was no trailing space */ 9029ade362SMatthew N. Dodd *cp++ = '\0'; 91623b6bd2SMatthew N. Dodd 92623b6bd2SMatthew N. Dodd /* 93623b6bd2SMatthew N. Dodd * There should be nothing except whitespace or comment 94623b6bd2SMatthew N. Dodd * from this point to the end of the line. 95623b6bd2SMatthew N. Dodd */ 96623b6bd2SMatthew N. Dodd while(isspace(*cp++)); 97486089f0SAlexander Kabaev if (!iseol(*cp)) continue; 98623b6bd2SMatthew N. Dodd 99486089f0SAlexander Kabaev strcpy(prog, p); 10029ade362SMatthew N. Dodd p = prog; 101486089f0SAlexander Kabaev continue; 102623b6bd2SMatthew N. Dodd } 103623b6bd2SMatthew N. Dodd 104623b6bd2SMatthew N. Dodd /* Parse the 'from' candidate. */ 105486089f0SAlexander Kabaev f = cp++; 106623b6bd2SMatthew N. Dodd while (!isspace(*cp) && !iseol(*cp)) cp++; 10729ade362SMatthew N. Dodd 108623b6bd2SMatthew N. Dodd /* Skip and zero out the trailing whitespace */ 109623b6bd2SMatthew N. Dodd while (isspace(*cp)) *cp++ = '\0'; 110623b6bd2SMatthew N. Dodd 111623b6bd2SMatthew N. Dodd /* Found a comment or EOL */ 112486089f0SAlexander Kabaev if (iseol(*cp)) continue; 113623b6bd2SMatthew N. Dodd 114623b6bd2SMatthew N. Dodd /* Parse 'to' mapping */ 115486089f0SAlexander Kabaev t = cp++; 116623b6bd2SMatthew N. Dodd while (!isspace(*cp) && !iseol(*cp)) cp++; 117623b6bd2SMatthew N. Dodd 118486089f0SAlexander Kabaev /* Skip and zero out the trailing whitespace */ 119486089f0SAlexander Kabaev while (isspace(*cp)) *cp++ = '\0'; 120486089f0SAlexander Kabaev 121486089f0SAlexander Kabaev /* Should be no extra tokens at this point */ 122486089f0SAlexander Kabaev if (!iseol(*cp)) continue; 123486089f0SAlexander Kabaev 124486089f0SAlexander Kabaev *cp = '\0'; 1253467e8b8SMatthew N. Dodd lm_add(p, xstrdup(f), xstrdup(t)); 12629ade362SMatthew N. Dodd } 127486089f0SAlexander Kabaev fclose(fp); 12829ade362SMatthew N. Dodd return; 12929ade362SMatthew N. Dodd } 13029ade362SMatthew N. Dodd 13129ade362SMatthew N. Dodd static void 13229ade362SMatthew N. Dodd lm_free (struct lm_list *lml) 13329ade362SMatthew N. Dodd { 13429ade362SMatthew N. Dodd struct lm *lm; 13529ade362SMatthew N. Dodd 13629ade362SMatthew N. Dodd while (!TAILQ_EMPTY(lml)) { 13729ade362SMatthew N. Dodd lm = TAILQ_FIRST(lml); 13829ade362SMatthew N. Dodd TAILQ_REMOVE(lml, lm, lm_link); 13929ade362SMatthew N. Dodd free(lm->f); 14029ade362SMatthew N. Dodd free(lm->t); 14129ade362SMatthew N. Dodd free(lm); 14229ade362SMatthew N. Dodd } 14329ade362SMatthew N. Dodd return; 14429ade362SMatthew N. Dodd } 14529ade362SMatthew N. Dodd 14629ade362SMatthew N. Dodd void 14729ade362SMatthew N. Dodd lm_fini (void) 14829ade362SMatthew N. Dodd { 14929ade362SMatthew N. Dodd struct lmp *lmp; 15029ade362SMatthew N. Dodd 15129ade362SMatthew N. Dodd while (!TAILQ_EMPTY(&lmp_head)) { 15229ade362SMatthew N. Dodd lmp = TAILQ_FIRST(&lmp_head); 15329ade362SMatthew N. Dodd TAILQ_REMOVE(&lmp_head, lmp, lmp_link); 15429ade362SMatthew N. Dodd free(lmp->p); 15529ade362SMatthew N. Dodd lm_free(&lmp->lml); 15629ade362SMatthew N. Dodd free(lmp); 15729ade362SMatthew N. Dodd } 15829ade362SMatthew N. Dodd return; 15929ade362SMatthew N. Dodd } 16029ade362SMatthew N. Dodd 16129ade362SMatthew N. Dodd static void 16229ade362SMatthew N. Dodd lm_add (char *p, char *f, char *t) 16329ade362SMatthew N. Dodd { 16429ade362SMatthew N. Dodd struct lm_list *lml; 16529ade362SMatthew N. Dodd struct lm *lm; 16629ade362SMatthew N. Dodd 16729ade362SMatthew N. Dodd if (p == NULL) 16829ade362SMatthew N. Dodd p = "$DEFAULT$"; 16929ade362SMatthew N. Dodd 17029ade362SMatthew N. Dodd #if 0 17129ade362SMatthew N. Dodd printf("%s(\"%s\", \"%s\", \"%s\")\n", __func__, p, f, t); 17229ade362SMatthew N. Dodd #endif 17329ade362SMatthew N. Dodd 17429ade362SMatthew N. Dodd if ((lml = lmp_find(p)) == NULL) 1753467e8b8SMatthew N. Dodd lml = lmp_init(xstrdup(p)); 17629ade362SMatthew N. Dodd 1773467e8b8SMatthew N. Dodd lm = xmalloc(sizeof(struct lm)); 17829ade362SMatthew N. Dodd lm->f = f; 17929ade362SMatthew N. Dodd lm->t = t; 18029ade362SMatthew N. Dodd TAILQ_INSERT_HEAD(lml, lm, lm_link); 18129ade362SMatthew N. Dodd } 18229ade362SMatthew N. Dodd 18329ade362SMatthew N. Dodd char * 18429ade362SMatthew N. Dodd lm_find (const char *p, const char *f) 18529ade362SMatthew N. Dodd { 18629ade362SMatthew N. Dodd struct lm_list *lml; 18729ade362SMatthew N. Dodd char *t; 18829ade362SMatthew N. Dodd 18929ade362SMatthew N. Dodd if (p != NULL && (lml = lmp_find(p)) != NULL) { 19029ade362SMatthew N. Dodd t = lml_find(lml, f); 1913467e8b8SMatthew N. Dodd if (t != NULL) { 1923467e8b8SMatthew N. Dodd /* 1933467e8b8SMatthew N. Dodd * Add a global mapping if we have 1943467e8b8SMatthew N. Dodd * a successful constrained match. 1953467e8b8SMatthew N. Dodd */ 1963467e8b8SMatthew N. Dodd lm_add(NULL, xstrdup(f), xstrdup(t)); 19729ade362SMatthew N. Dodd return (t); 19829ade362SMatthew N. Dodd } 1993467e8b8SMatthew N. Dodd } 20029ade362SMatthew N. Dodd lml = lmp_find("$DEFAULT$"); 20129ade362SMatthew N. Dodd if (lml != NULL) 20229ade362SMatthew N. Dodd return (lml_find(lml, f)); 20329ade362SMatthew N. Dodd else 20429ade362SMatthew N. Dodd return (NULL); 20529ade362SMatthew N. Dodd } 20629ade362SMatthew N. Dodd 20729ade362SMatthew N. Dodd static char * 20829ade362SMatthew N. Dodd lml_find (struct lm_list *lmh, const char *f) 20929ade362SMatthew N. Dodd { 21029ade362SMatthew N. Dodd struct lm *lm; 21129ade362SMatthew N. Dodd 21229ade362SMatthew N. Dodd TAILQ_FOREACH(lm, lmh, lm_link) 21329ade362SMatthew N. Dodd if ((strncmp(f, lm->f, strlen(lm->f)) == 0) && 21429ade362SMatthew N. Dodd (strlen(f) == strlen(lm->f))) 21529ade362SMatthew N. Dodd return (lm->t); 21629ade362SMatthew N. Dodd return NULL; 21729ade362SMatthew N. Dodd } 21829ade362SMatthew N. Dodd 21929ade362SMatthew N. Dodd static struct lm_list * 22029ade362SMatthew N. Dodd lmp_find (const char *n) 22129ade362SMatthew N. Dodd { 22229ade362SMatthew N. Dodd struct lmp *lmp; 22329ade362SMatthew N. Dodd 22429ade362SMatthew N. Dodd TAILQ_FOREACH(lmp, &lmp_head, lmp_link) 22529ade362SMatthew N. Dodd if ((strncmp(n, lmp->p, strlen(lmp->p)) == 0) && 22629ade362SMatthew N. Dodd (strlen(n) == strlen(lmp->p))) 22729ade362SMatthew N. Dodd return (&lmp->lml); 22829ade362SMatthew N. Dodd return (NULL); 22929ade362SMatthew N. Dodd } 23029ade362SMatthew N. Dodd 23129ade362SMatthew N. Dodd static struct lm_list * 23229ade362SMatthew N. Dodd lmp_init (char *n) 23329ade362SMatthew N. Dodd { 23429ade362SMatthew N. Dodd struct lmp *lmp; 23529ade362SMatthew N. Dodd 2363467e8b8SMatthew N. Dodd lmp = xmalloc(sizeof(struct lmp)); 23729ade362SMatthew N. Dodd lmp->p = n; 23829ade362SMatthew N. Dodd TAILQ_INIT(&lmp->lml); 23929ade362SMatthew N. Dodd TAILQ_INSERT_HEAD(&lmp_head, lmp, lmp_link); 24029ade362SMatthew N. Dodd 24129ade362SMatthew N. Dodd return (&lmp->lml); 24229ade362SMatthew N. Dodd } 243