1 /* $NetBSD: aliaslist.c,v 1.4 2014/12/10 04:37:55 christos Exp $ */ 2 3 #ifndef lint 4 static char *rcsid = "Id: aliaslist.c,v 1.1 2003/06/04 00:25:47 marka Exp "; 5 #endif 6 7 /* 8 * Copyright (c) 2002 Japan Network Information Center. All rights reserved. 9 * 10 * By using this file, you agree to the terms and conditions set forth bellow. 11 * 12 * LICENSE TERMS AND CONDITIONS 13 * 14 * The following License Terms and Conditions apply, unless a different 15 * license is obtained from Japan Network Information Center ("JPNIC"), 16 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda, 17 * Chiyoda-ku, Tokyo 101-0047, Japan. 18 * 19 * 1. Use, Modification and Redistribution (including distribution of any 20 * modified or derived work) in source and/or binary forms is permitted 21 * under this License Terms and Conditions. 22 * 23 * 2. Redistribution of source code must retain the copyright notices as they 24 * appear in each source code file, this License Terms and Conditions. 25 * 26 * 3. Redistribution in binary form must reproduce the Copyright Notice, 27 * this License Terms and Conditions, in the documentation and/or other 28 * materials provided with the distribution. For the purposes of binary 29 * distribution the "Copyright Notice" refers to the following language: 30 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved." 31 * 32 * 4. The name of JPNIC may not be used to endorse or promote products 33 * derived from this Software without specific prior written approval of 34 * JPNIC. 35 * 36 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC 37 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 38 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 39 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE 40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 41 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 42 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 44 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 45 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 46 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 47 */ 48 49 #include <config.h> 50 51 #include <stddef.h> 52 #include <stdlib.h> 53 #include <stdio.h> 54 #include <string.h> 55 #include <ctype.h> 56 57 #include <idn/aliaslist.h> 58 #include <idn/assert.h> 59 #include <idn/logmacro.h> 60 #include <idn/result.h> 61 62 struct aliasitem { 63 char *pattern; /* name pattern */ 64 char *encoding; /* MIME-preferred charset name */ 65 struct aliasitem *next; 66 }; 67 typedef struct aliasitem *aliasitem_t; 68 69 struct idn__aliaslist { 70 aliasitem_t first_item; /* first item of the list */ 71 }; 72 73 static idn_result_t 74 additem_to_top(idn__aliaslist_t list, 75 const char *pattern, const char *encoding); 76 77 static idn_result_t 78 additem_to_bottom(idn__aliaslist_t list, 79 const char *pattern, const char *encoding); 80 81 static int match(const char *pattern, const char *str); 82 83 static idn_result_t create_item(const char *pattern, const char *encoding, 84 aliasitem_t *itemp); 85 86 #ifdef DEBUG 87 static void dump_list(idn__aliaslist_t list); 88 #endif 89 90 idn_result_t 91 idn__aliaslist_create(idn__aliaslist_t *listp) { 92 static int size = sizeof(struct idn__aliaslist); 93 94 TRACE(("idn__aliaslist_create()\n")); 95 96 assert(listp != NULL); 97 98 if ((*listp = malloc(size)) == NULL) { 99 return (idn_nomemory); 100 } 101 (*listp)->first_item = NULL; 102 103 return (idn_success); 104 } 105 106 void 107 idn__aliaslist_destroy(idn__aliaslist_t list) { 108 aliasitem_t current; 109 aliasitem_t next; 110 111 TRACE(("idn__aliaslist_destroy()\n")); 112 113 assert(list != NULL); 114 115 current = list->first_item; 116 while (current != NULL) { 117 if (current->pattern != NULL) { 118 free(current->pattern); 119 } 120 if (current->encoding != NULL) { 121 free(current->encoding); 122 } 123 next = current->next; 124 free(current); 125 current = next; 126 } 127 free(list); 128 } 129 130 idn_result_t 131 idn__aliaslist_aliasfile(idn__aliaslist_t list, const char *path) { 132 FILE *fp; 133 int line_no; 134 idn_result_t r = idn_success; 135 char line[200], alias[200], real[200]; 136 137 assert(path != NULL); 138 139 TRACE(("idn__aliaslist_aliasfile(path=%s)\n", path)); 140 141 if ((fp = fopen(path, "r")) == NULL) { 142 return (idn_nofile); 143 } 144 for (line_no = 1; fgets(line, sizeof(line), fp) != NULL; line_no++) { 145 unsigned char *p = (unsigned char *)line; 146 147 while (isascii(*p) && isspace(*p)) 148 p++; 149 if (*p == '#' || *p == '\n') 150 continue; 151 if (sscanf((char *)p, "%s %s", alias, real) == 2) { 152 r = additem_to_bottom(list, alias, real); 153 if (r != idn_success) 154 break; 155 } else { 156 INFO(("idn__aliaslist_aliasfile: file %s has " 157 "invalid contents at line %d\n", 158 path, line_no)); 159 r = idn_invalid_syntax; 160 break; 161 } 162 } 163 fclose(fp); 164 165 #ifdef DEBUG 166 dump_list(list); 167 #endif 168 169 return (r); 170 } 171 172 idn_result_t 173 idn__aliaslist_additem(idn__aliaslist_t list, 174 const char *pattern, const char *encoding, 175 int first_item) { 176 if (first_item) { 177 return additem_to_top(list, pattern, encoding); 178 } else { 179 return additem_to_bottom(list, pattern, encoding); 180 } 181 } 182 183 static idn_result_t 184 additem_to_top(idn__aliaslist_t list, 185 const char *pattern, const char *encoding) { 186 aliasitem_t new_item; 187 idn_result_t r; 188 189 TRACE(("additem_to_top()\n")); 190 191 assert(list != NULL); 192 assert(pattern != NULL); 193 assert(encoding != NULL); 194 195 if ((r = create_item(pattern, encoding, &new_item)) 196 != idn_success) { 197 WARNING(("additem_to_top: malloc failed\n")); 198 return (r); 199 } 200 201 new_item->next = list->first_item; 202 list->first_item = new_item; 203 204 #ifdef DEBUG 205 dump_list(list); 206 #endif 207 208 return (idn_success); 209 } 210 211 static idn_result_t 212 additem_to_bottom(idn__aliaslist_t list, 213 const char *pattern, const char *encoding) { 214 aliasitem_t new_item; 215 idn_result_t r; 216 217 TRACE(("additem_to_bottom()\n")); 218 219 assert(list != NULL); 220 assert(pattern != NULL); 221 assert(encoding != NULL); 222 223 r = create_item(pattern, encoding, &new_item); 224 if (r != idn_success) { 225 WARNING(("additem_to_bottom: malloc failed\n")); 226 return r; 227 } 228 229 if (list->first_item == NULL) { 230 list->first_item = new_item; 231 } else { 232 aliasitem_t cur_item = list->first_item; 233 for (;;) { 234 if (cur_item->next == NULL) { 235 break; 236 } 237 cur_item = cur_item->next; 238 } 239 cur_item->next = new_item; 240 } 241 242 return (idn_success); 243 } 244 245 idn_result_t 246 idn__aliaslist_find(idn__aliaslist_t list, 247 const char *pattern, char **encodingp) { 248 aliasitem_t current; 249 250 TRACE(("idn__aliaslist_find()\n")); 251 252 assert(list != NULL); 253 assert(pattern != NULL); 254 255 #ifdef DEBUG 256 DUMP(("target pattern: %s\n", pattern)); 257 #endif 258 current = list->first_item; 259 while (current != NULL) { 260 #ifdef DEBUG 261 DUMP(("current pattern: %s, encoding: %s\n", 262 current->pattern, current->encoding)); 263 #endif 264 if (match(current->pattern, pattern)) { 265 *encodingp = current->encoding; 266 return (idn_success); 267 } 268 current = current->next; 269 } 270 271 TRACE(("idn__aliaslist_find(): not found\n")); 272 *encodingp = (char *)pattern; 273 return (idn_notfound); 274 } 275 276 /* 277 * Wild card matching function that supports only '*'. 278 */ 279 static int 280 match(const char *pattern, const char *str) { 281 for (;;) { 282 int c; 283 284 switch (c = *pattern++) { 285 case '\0': 286 return (*str == '\0'); 287 case '*': 288 while (!match(pattern, str)) { 289 if (*str == '\0') 290 return (0); 291 str++; 292 } 293 return (1); 294 break; 295 default: 296 if (*str++ != c) 297 return (0); 298 break; 299 } 300 } 301 } 302 303 /* 304 * List item creation. 305 * pattern and encoding must not be NULL. 306 */ 307 static idn_result_t 308 create_item(const char *pattern, const char *encoding, 309 aliasitem_t *itemp) { 310 static size_t size = sizeof(struct aliasitem); 311 312 assert(pattern != NULL); 313 assert(encoding != NULL); 314 315 if ((*itemp = malloc(size)) == NULL) 316 return (idn_nomemory); 317 318 if (((*itemp)->pattern = malloc(strlen(pattern) + 1)) == NULL) { 319 free(*itemp); 320 *itemp = NULL; 321 return (idn_nomemory); 322 } 323 324 if (((*itemp)->encoding = malloc(strlen(encoding) + 1)) == NULL) { 325 free((*itemp)->pattern); 326 free(*itemp); 327 *itemp = NULL; 328 return (idn_nomemory); 329 } 330 331 (void)strcpy((*itemp)->pattern, pattern); 332 (void)strcpy((*itemp)->encoding, encoding); 333 (*itemp)->next = NULL; 334 335 return (idn_success); 336 } 337 338 #ifdef DEBUG 339 static void 340 dump_list(idn__aliaslist_t list) { 341 aliasitem_t item; 342 int i; 343 344 TRACE(("dump_list()\n")); 345 if (list == NULL) { 346 TRACE(("list is NULL\n")); 347 return; 348 } 349 item = list->first_item; 350 i = 0; 351 while (item != NULL) { 352 DUMP(("%d: %s\t%s\n", i, item->pattern, item->encoding)); 353 item = item->next; 354 i++; 355 } 356 } 357 #endif 358