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