1 /* 2 * Copyright (c) 1992 Eric P. Allman. 3 * Copyright (c) 1992 Regents of the University of California. 4 * All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #ifndef lint 10 static char sccsid[] = "@(#)map.c 6.5 (Berkeley) 02/18/93"; 11 #endif /* not lint */ 12 13 #include "sendmail.h" 14 #include <fcntl.h> 15 16 #ifdef DBM_MAP 17 #include <ndbm.h> 18 #endif 19 #if defined(HASH_MAP) || defined(BTREE_MAP) 20 #include <db.h> 21 #endif 22 #ifdef NIS_MAP 23 #include <rpcsvc/ypclnt.h> 24 #endif 25 26 27 #ifdef DBM_MAP 28 29 /* 30 ** DBM_MAP_INIT -- DBM-style map initialization 31 ** 32 ** Parameters: 33 ** map -- the pointer to the actual map 34 ** mapname -- the name of the map (for error messages) 35 ** args -- a pointer to the config file line arguments 36 ** 37 ** Returns: 38 ** TRUE -- if it could successfully open the map. 39 ** FALSE -- otherwise. 40 ** 41 ** Side Effects: 42 ** Gives an error if it can't open the map. 43 */ 44 45 bool 46 dbm_map_init(map, mapname, args) 47 MAP *map; 48 char *mapname; 49 char *args; 50 { 51 DBM *dbm; 52 53 map_parseargs(map, &args); 54 if (map->map_file == NULL) 55 { 56 syserr("No file name for DBM map %s", mapname); 57 return FALSE; 58 } 59 dbm = dbm_open(map->map_file, O_RDONLY, 0644); 60 if (dbm == NULL) 61 { 62 if (!bitset(MF_OPTIONAL, map->map_flags)) 63 syserr("Cannot open DBM database %s", map->map_file); 64 return FALSE; 65 } 66 map->map_db = (void *) dbm; 67 return TRUE; 68 } 69 /* 70 ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 71 ** 72 ** Parameters: 73 ** map -- the map to look up in. 74 ** buf -- a pointer to to the buffer containing the key. 75 ** This is a null terminated string. 76 ** bufsiz -- the size of buf -- note that this is in general 77 ** larger that strlen(buf), and buf can be changed 78 ** in place if desired. 79 ** av -- arguments from the config file (can be interpolated 80 ** into the final result). 81 ** 82 ** Returns: 83 ** A pointer to the rewritten result. 84 ** NULL if not found in the map. 85 */ 86 87 char * 88 dbm_map_lookup(map, buf, bufsiz, av) 89 MAP *map; 90 char buf[]; 91 int bufsiz; 92 char **av; 93 { 94 datum key, val; 95 96 key.dptr = buf; 97 key.dsize = strlen(buf); 98 if (!bitset(MF_NOFOLDCASE, map->map_flags)) 99 { 100 register char *p; 101 102 for (p = buf; *p != '\0'; p++) 103 if (isascii(*p) && isupper(*p)) 104 *p = tolower(*p); 105 } 106 if (bitset(MF_INCLNULL, map->map_flags)) 107 key.dsize++; 108 val = dbm_fetch(map->map_db, key); 109 if (val.dptr == NULL) 110 return NULL; 111 if (!bitset(MF_MATCHONLY, map->map_flags)) 112 map_rewrite(val.dptr, val.dsize, buf, bufsiz, av); 113 return buf; 114 } 115 116 #endif /* DBM_MAP */ 117 118 #ifdef BTREE_MAP 119 120 /* 121 ** BTREE_MAP_INIT -- BTREE-style map initialization 122 ** 123 ** Parameters: 124 ** map -- the pointer to the actual map 125 ** mapname -- the name of the map (for error messages) 126 ** args -- a pointer to the config file line arguments 127 ** 128 ** Returns: 129 ** TRUE -- if it could successfully open the map. 130 ** FALSE -- otherwise. 131 ** 132 ** Side Effects: 133 ** Gives an error if it can't open the map. 134 */ 135 136 bool 137 bt_map_init(map, mapname, args) 138 MAP *map; 139 char *mapname; 140 char *args; 141 { 142 DB *db; 143 144 map_parseargs(map, &args); 145 if (map->map_file == NULL) 146 { 147 syserr("No file name for BTREE map %s", mapname); 148 return FALSE; 149 } 150 db = dbopen(map->map_file, O_RDONLY, 0644, DB_BTREE, NULL); 151 if (db == NULL) 152 { 153 if (!bitset(MF_OPTIONAL, map->map_flags)) 154 syserr("Cannot open BTREE database %s", map->map_file); 155 return FALSE; 156 } 157 map->map_db = (void *) db; 158 return TRUE; 159 } 160 161 #endif /* BTREE_MAP */ 162 163 #ifdef HASH_MAP 164 165 /* 166 ** HASH_MAP_INIT -- HASH-style map initialization 167 ** 168 ** Parameters: 169 ** map -- the pointer to the actual map 170 ** mapname -- the name of the map (for error messages) 171 ** args -- a pointer to the config file line arguments 172 ** 173 ** Returns: 174 ** TRUE -- if it could successfully open the map. 175 ** FALSE -- otherwise. 176 ** 177 ** Side Effects: 178 ** Gives an error if it can't open the map. 179 */ 180 181 bool 182 hash_map_init(map, mapname, args) 183 MAP *map; 184 char *mapname; 185 char *args; 186 { 187 DB *db; 188 189 map_parseargs(map, &args); 190 if (map->map_file == NULL) 191 { 192 syserr("No file name for HASH map %s", mapname); 193 return FALSE; 194 } 195 db = dbopen(map->map_file, O_RDONLY, 0644, DB_HASH, NULL); 196 if (db == NULL) 197 { 198 if (!bitset(MF_OPTIONAL, map->map_flags)) 199 syserr("Cannot open HASH database %s", map->map_file); 200 return FALSE; 201 } 202 map->map_db = (void *) db; 203 return TRUE; 204 } 205 206 #endif /* HASH_MAP */ 207 208 #if defined(BTREE_MAP) || defined(HASH_MAP) 209 210 /* 211 ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 212 ** 213 ** Parameters: 214 ** map -- the map to look up in. 215 ** buf -- a pointer to to the buffer containing the key. 216 ** This is a null terminated string. 217 ** bufsiz -- the size of buf -- note that this is in general 218 ** larger that strlen(buf), and buf can be changed 219 ** in place if desired. 220 ** av -- arguments from the config file (can be interpolated 221 ** into the final result). 222 ** 223 ** Returns: 224 ** A pointer to the rewritten result. 225 ** NULL if not found in the map. 226 */ 227 228 char * 229 db_map_lookup(map, buf, bufsiz, av) 230 MAP *map; 231 char buf[]; 232 int bufsiz; 233 char **av; 234 { 235 DBT key, val; 236 237 key.data = buf; 238 key.size = strlen(buf); 239 if (!bitset(MF_NOFOLDCASE, map->map_flags)) 240 { 241 register char *p; 242 243 for (p = buf; *p != '\0'; p++) 244 if (isascii(*p) && isupper(*p)) 245 *p = tolower(*p); 246 } 247 if (bitset(MF_INCLNULL, map->map_flags)) 248 key.size++; 249 if (((DB *) map->map_db)->get((DB *) map->map_db, &key, &val, 0) != 0) 250 return NULL; 251 if (!bitset(MF_MATCHONLY, map->map_flags)) 252 map_rewrite(val.data, val.size, buf, bufsiz, av); 253 return buf; 254 } 255 256 #endif /* BTREE_MAP || HASH_MAP */ 257 /* 258 ** MAP_PARSEARGS -- parse config line arguments for database lookup 259 ** 260 ** Parameters: 261 ** map -- the map being initialized. 262 ** pp -- an indirect pointer to the config line. It will 263 ** be replaced with a pointer to the next field 264 ** on the line. 265 ** 266 ** Returns: 267 ** none 268 ** 269 ** Side Effects: 270 ** null terminates the filename; stores it in map 271 */ 272 273 map_parseargs(map, pp) 274 MAP *map; 275 char **pp; 276 { 277 register char *p = *pp; 278 279 for (;;) 280 { 281 while (isascii(*p) && isspace(*p)) 282 p++; 283 if (*p != '-') 284 break; 285 switch (*++p) 286 { 287 case 'N': 288 map->map_flags |= MF_INCLNULL; 289 break; 290 291 case 'o': 292 map->map_flags |= MF_OPTIONAL; 293 break; 294 295 case 'f': 296 map->map_flags |= MF_NOFOLDCASE; 297 break; 298 299 case 'm': 300 map->map_flags |= MF_MATCHONLY; 301 break; 302 303 case 'a': 304 map->map_app = ++p; 305 break; 306 307 case 'd': 308 map->map_domain = ++p; 309 break; 310 } 311 while (*p != '\0' && !(isascii(*p) && isspace(*p))) 312 p++; 313 if (*p != '\0') 314 *p++ = 0; 315 } 316 if (map->map_app != NULL) 317 map->map_app = newstr(map->map_app); 318 if (map->map_domain != NULL) 319 map->map_domain = newstr(map->map_domain); 320 321 if (*p == '\0') 322 return NULL; 323 map->map_file = p; 324 while (*p != '\0' && !(isascii(*p) && isspace(*p))) 325 p++; 326 if (*p != '\0') 327 *p++ = '\0'; 328 map->map_file = newstr(map->map_file); 329 *pp = p; 330 } 331 332 # ifdef NIS_MAP 333 334 /* 335 ** NIS_MAP_INIT -- initialize DBM map 336 ** 337 ** Parameters: 338 ** map -- the pointer to the actual map. 339 ** mapname -- the name of the map (for error messages). 340 ** args -- a pointer to the config file line arguments. 341 ** 342 ** Returns: 343 ** TRUE -- if it could successfully open the map. 344 ** FALSE -- otherwise. 345 ** 346 ** Side Effects: 347 ** Prints an error if it can't open the map. 348 */ 349 350 bool 351 nis_map_init(map, mapname, args) 352 MAP *map; 353 char *mapname; 354 char *args; 355 { 356 int yperr; 357 char *master; 358 359 /* parse arguments */ 360 map_parseargs(map, &args); 361 if (map->map_file == NULL) 362 { 363 syserr("No NIS map name for map %s", mapname); 364 return FALSE; 365 } 366 if (map->map_domain == NULL) 367 yp_get_default_domain(&map->map_domain); 368 369 /* check to see if this map actually exists */ 370 yperr = yp_master(map->map_domain, map->map_file, &master); 371 if (yperr == 0) 372 return TRUE; 373 if (!bitset(MF_OPTIONAL, map->map_flags)) 374 syserr("Cannot bind to domain %s: %s", map->map_domain, 375 yperr_string(yperr)); 376 return FALSE; 377 } 378 /* 379 ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 380 ** 381 ** Parameters: 382 ** map -- the map to look up in. 383 ** buf -- a pointer to to the buffer containing the key. 384 ** This is a null terminated string. 385 ** bufsiz -- the size of buf -- note that this is in general 386 ** larger that strlen(buf), and buf can be changed 387 ** in place if desired. 388 ** av -- arguments from the config file (can be interpolated 389 ** into the final result). 390 ** 391 ** Returns: 392 ** A pointer to the rewritten result. 393 ** NULL if not found in the map. 394 */ 395 396 char * 397 nis_map_lookup(map, buf, bufsiz, av) 398 MAP *map; 399 char buf[]; 400 int bufsiz; 401 char **av; 402 { 403 char *vp; 404 auto int vsize; 405 406 if (!bitset(MF_NOFOLDCASE, map->map_flags)) 407 { 408 register char *p; 409 410 for (p = buf; *p != '\0'; p++) 411 if (isascii(*p) && isupper(*p)) 412 *p = tolower(*p); 413 } 414 if (yp_match(map->map_domain, map->map_file, buf, strlen(buf) + 1, 415 &vp, &vsize) != 0) 416 return NULL; 417 if (!bitset(MF_MATCHONLY, map->map_flags)) 418 map_rewrite(vp, vsize, buf, bufsiz, av); 419 return buf; 420 } 421 422 #endif /* NIS_MAP */ 423 /* 424 ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 425 ** 426 ** Parameters: 427 ** s -- the string to rewrite, NOT necessarily null terminated. 428 ** slen -- the length of s. 429 ** buf -- the place to write it. 430 ** buflen -- the length of buf. 431 ** av -- arguments to interpolate into buf. 432 ** 433 ** Returns: 434 ** none. 435 ** 436 ** Side Effects: 437 ** none. 438 */ 439 440 map_rewrite(s, slen, buf, buflen, av) 441 register char *s; 442 int slen; 443 char buf[]; 444 int buflen; 445 char **av; 446 { 447 register char *bp; 448 char *buflim; 449 register char c; 450 char **avp; 451 register char *ap; 452 453 if (tTd(23, 1)) 454 { 455 printf("map_rewrite(%.*s), av =\n", slen, s); 456 for (avp = av; *avp != NULL; avp++) 457 printf("\t%s\n", *avp); 458 } 459 460 bp = buf; 461 buflim = &buf[buflen - 2]; 462 while (--slen >= 0 && (c = *s++) != '\0') 463 { 464 if (c != '%') 465 { 466 pushc: 467 if (bp < buflim) 468 *bp++ = c; 469 continue; 470 } 471 if (--slen < 0 || (c = *s++) == '\0') 472 c = '%'; 473 if (c == '%') 474 goto pushc; 475 if (!(isascii(c) && isdigit(c))) 476 { 477 *bp++ = '%'; 478 goto pushc; 479 } 480 c -= '0'; 481 for (avp = av; --c >= 0 && *avp != NULL; avp++) 482 continue; 483 if (*avp == NULL) 484 continue; 485 486 /* transliterate argument into output string */ 487 for (ap = *avp; (c = *ap++) != '\0'; ) 488 { 489 if (bp < buflim) 490 *bp++ = c; 491 } 492 } 493 *bp++ = '\0'; 494 if (tTd(23, 1)) 495 printf("map_rewrite => %s\n", buf); 496 } 497