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