libmap.c revision 115445
1/* 2 * $FreeBSD: head/libexec/rtld-elf/libmap.c 115445 2003-05-31 14:46:38Z mdodd $ 3 */ 4 5#include <stdio.h> 6#include <ctype.h> 7#include <string.h> 8#include <stdlib.h> 9#include <sys/queue.h> 10#include <sys/param.h> 11 12#include "debug.h" 13#include "rtld.h" 14 15#ifndef _PATH_LIBMAP_CONF 16#define _PATH_LIBMAP_CONF "/etc/libmap.conf" 17#endif 18 19TAILQ_HEAD(lm_list, lm); 20struct lm { 21 char *f; 22 char *t; 23 24 TAILQ_ENTRY(lm) lm_link; 25}; 26 27TAILQ_HEAD(lmp_list, lmp) lmp_head = TAILQ_HEAD_INITIALIZER(lmp_head); 28struct lmp { 29 char *p; 30 struct lm_list lml; 31 TAILQ_ENTRY(lmp) lmp_link; 32}; 33 34static void lm_add (const char *, const char *, const char *); 35static void lm_free (struct lm_list *); 36static char * lml_find (struct lm_list *, const char *); 37static struct lm_list * lmp_find (const char *); 38static struct lm_list * lmp_init (char *); 39 40#define iseol(c) (((c) == '#') || ((c) == '\0') || \ 41 ((c) == '\n') || ((c) == '\r')) 42 43void 44lm_init (void) 45{ 46 FILE *fp; 47 char *cp; 48 char *f, *t, *p, *c; 49 char prog[MAXPATHLEN]; 50 char line[MAXPATHLEN + 2]; 51 52 dbg("%s()", __func__); 53 54 TAILQ_INIT(&lmp_head); 55 56 if ((fp = fopen(_PATH_LIBMAP_CONF, "r")) == NULL) 57 return; 58 59 p = NULL; 60 while ((cp = fgets(line, MAXPATHLEN + 1, fp)) != NULL) { 61 t = f = c = NULL; 62 63 /* Skip over leading space */ 64 while (isspace(*cp)) cp++; 65 66 /* Found a comment or EOL */ 67 if (iseol(*cp)) continue; 68 69 /* Found a constraint selector */ 70 if (*cp == '[') { 71 cp++; 72 73 /* Skip leading space */ 74 while (isspace(*cp)) cp++; 75 76 /* Found comment, EOL or end of selector */ 77 if (iseol(*cp) || *cp == ']') 78 continue; 79 80 c = cp++; 81 /* Skip to end of word */ 82 while (!isspace(*cp) && !iseol(*cp) && *cp != ']') 83 cp++; 84 85 /* Skip and zero out trailing space */ 86 while (isspace(*cp)) *cp++ = '\0'; 87 88 /* Check if there is a closing brace */ 89 if (*cp != ']') continue; 90 91 /* Terminate string if there was no trailing space */ 92 *cp++ = '\0'; 93 94 /* 95 * There should be nothing except whitespace or comment 96 from this point to the end of the line. 97 */ 98 while(isspace(*cp)) *cp++; 99 if (!iseol(*cp)) continue; 100 101 strcpy(prog, c); 102 p = prog; 103 continue; 104 } 105 106 /* Parse the 'from' candidate. */ 107 f = cp++; 108 while (!isspace(*cp) && !iseol(*cp)) cp++; 109 110 /* Skip and zero out the trailing whitespace */ 111 while (isspace(*cp)) *cp++ = '\0'; 112 113 /* Found a comment or EOL */ 114 if (iseol(*cp)) continue; 115 116 /* Parse 'to' mapping */ 117 t = cp++; 118 while (!isspace(*cp) && !iseol(*cp)) cp++; 119 120 /* Skip and zero out the trailing whitespace */ 121 while (isspace(*cp)) *cp++ = '\0'; 122 123 /* Should be no extra tokens at this point */ 124 if (!iseol(*cp)) continue; 125 126 *cp = '\0'; 127 lm_add(p, f, t); 128 } 129 fclose(fp); 130 return; 131} 132 133static void 134lm_free (struct lm_list *lml) 135{ 136 struct lm *lm; 137 138 dbg("%s(%p)", __func__, lml); 139 140 while (!TAILQ_EMPTY(lml)) { 141 lm = TAILQ_FIRST(lml); 142 TAILQ_REMOVE(lml, lm, lm_link); 143 free(lm->f); 144 free(lm->t); 145 free(lm); 146 } 147 return; 148} 149 150void 151lm_fini (void) 152{ 153 struct lmp *lmp; 154 155 dbg("%s()", __func__); 156 157 while (!TAILQ_EMPTY(&lmp_head)) { 158 lmp = TAILQ_FIRST(&lmp_head); 159 TAILQ_REMOVE(&lmp_head, lmp, lmp_link); 160 free(lmp->p); 161 lm_free(&lmp->lml); 162 free(lmp); 163 } 164 return; 165} 166 167static void 168lm_add (const char *p, const char *f, const char *t) 169{ 170 struct lm_list *lml; 171 struct lm *lm; 172 173 if (p == NULL) 174 p = "$DEFAULT$"; 175 176 dbg("%s(\"%s\", \"%s\", \"%s\")", __func__, p, f, t); 177 178 if ((lml = lmp_find(p)) == NULL) 179 lml = lmp_init(xstrdup(p)); 180 181 lm = xmalloc(sizeof(struct lm)); 182 lm->f = xstrdup(f); 183 lm->t = xstrdup(t); 184 TAILQ_INSERT_HEAD(lml, lm, lm_link); 185} 186 187char * 188lm_find (const char *p, const char *f) 189{ 190 struct lm_list *lml; 191 char *t; 192 193 dbg("%s(\"%s\", \"%s\")", __func__, p, f); 194 195 if (p != NULL && (lml = lmp_find(p)) != NULL) { 196 t = lml_find(lml, f); 197 if (t != NULL) { 198 /* 199 * Add a global mapping if we have 200 * a successful constrained match. 201 */ 202 lm_add(NULL, f, t); 203 return (t); 204 } 205 } 206 lml = lmp_find("$DEFAULT$"); 207 if (lml != NULL) 208 return (lml_find(lml, f)); 209 else 210 return (NULL); 211} 212 213static char * 214lml_find (struct lm_list *lmh, const char *f) 215{ 216 struct lm *lm; 217 218 dbg("%s(%p, \"%s\")", __func__, lmh, f); 219 220 TAILQ_FOREACH(lm, lmh, lm_link) 221 if ((strncmp(f, lm->f, strlen(lm->f)) == 0) && 222 (strlen(f) == strlen(lm->f))) 223 return (lm->t); 224 return NULL; 225} 226 227static struct lm_list * 228lmp_find (const char *n) 229{ 230 struct lmp *lmp; 231 232 dbg("%s(\"%s\")", __func__, n); 233 234 TAILQ_FOREACH(lmp, &lmp_head, lmp_link) 235 if ((strncmp(n, lmp->p, strlen(lmp->p)) == 0) && 236 (strlen(n) == strlen(lmp->p))) 237 return (&lmp->lml); 238 return (NULL); 239} 240 241static struct lm_list * 242lmp_init (char *n) 243{ 244 struct lmp *lmp; 245 246 dbg("%s(\"%s\")", __func__, n); 247 248 lmp = xmalloc(sizeof(struct lmp)); 249 lmp->p = n; 250 TAILQ_INIT(&lmp->lml); 251 TAILQ_INSERT_HEAD(&lmp_head, lmp, lmp_link); 252 253 return (&lmp->lml); 254} 255