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.7 (Berkeley) 03/25/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 ** 81 ** Returns: 82 ** A pointer to the rewritten result. 83 ** NULL if not found in the map. 84 */ 85 86 char * 87 dbm_map_lookup(map, buf, bufsiz, av) 88 MAP *map; 89 char buf[]; 90 int bufsiz; 91 char **av; 92 { 93 datum key, val; 94 95 key.dptr = buf; 96 key.dsize = strlen(buf); 97 if (!bitset(MF_NOFOLDCASE, map->map_flags)) 98 { 99 register char *p; 100 101 for (p = buf; *p != '\0'; p++) 102 if (isascii(*p) && isupper(*p)) 103 *p = tolower(*p); 104 } 105 if (bitset(MF_INCLNULL, map->map_flags)) 106 key.dsize++; 107 val = dbm_fetch(map->map_db, key); 108 if (val.dptr == NULL) 109 return NULL; 110 if (!bitset(MF_MATCHONLY, map->map_flags)) 111 map_rewrite(val.dptr, val.dsize, buf, bufsiz, av); 112 return buf; 113 } 114 115 #endif /* DBM_MAP */ 116 117 #ifdef BTREE_MAP 118 119 /* 120 ** BTREE_MAP_INIT -- BTREE-style map initialization 121 ** 122 ** Parameters: 123 ** map -- the pointer to the actual map 124 ** mapname -- the name of the map (for error messages) 125 ** args -- a pointer to the config file line arguments 126 ** 127 ** Returns: 128 ** TRUE -- if it could successfully open the map. 129 ** FALSE -- otherwise. 130 ** 131 ** Side Effects: 132 ** Gives an error if it can't open the map. 133 */ 134 135 bool 136 bt_map_init(map, mapname, args) 137 MAP *map; 138 char *mapname; 139 char *args; 140 { 141 DB *db; 142 143 map_parseargs(map, &args); 144 if (map->map_file == NULL) 145 { 146 syserr("No file name for BTREE map %s", mapname); 147 return FALSE; 148 } 149 db = dbopen(map->map_file, O_RDONLY, 0644, DB_BTREE, NULL); 150 if (db == NULL) 151 { 152 if (!bitset(MF_OPTIONAL, map->map_flags)) 153 syserr("Cannot open BTREE database %s", map->map_file); 154 return FALSE; 155 } 156 map->map_db = (void *) db; 157 return TRUE; 158 } 159 160 #endif /* BTREE_MAP */ 161 162 #ifdef HASH_MAP 163 164 /* 165 ** HASH_MAP_INIT -- HASH-style map initialization 166 ** 167 ** Parameters: 168 ** map -- the pointer to the actual map 169 ** mapname -- the name of the map (for error messages) 170 ** args -- a pointer to the config file line arguments 171 ** 172 ** Returns: 173 ** TRUE -- if it could successfully open the map. 174 ** FALSE -- otherwise. 175 ** 176 ** Side Effects: 177 ** Gives an error if it can't open the map. 178 */ 179 180 bool 181 hash_map_init(map, mapname, args) 182 MAP *map; 183 char *mapname; 184 char *args; 185 { 186 DB *db; 187 188 map_parseargs(map, &args); 189 if (map->map_file == NULL) 190 { 191 syserr("No file name for HASH map %s", mapname); 192 return FALSE; 193 } 194 db = dbopen(map->map_file, O_RDONLY, 0644, DB_HASH, NULL); 195 if (db == NULL) 196 { 197 if (!bitset(MF_OPTIONAL, map->map_flags)) 198 syserr("Cannot open HASH database %s", map->map_file); 199 return FALSE; 200 } 201 map->map_db = (void *) db; 202 return TRUE; 203 } 204 205 #endif /* HASH_MAP */ 206 207 #if defined(BTREE_MAP) || defined(HASH_MAP) 208 209 /* 210 ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 211 ** 212 ** Parameters: 213 ** map -- the map to look up in. 214 ** buf -- a pointer to to the buffer containing the key. 215 ** This is a null terminated string. 216 ** bufsiz -- the size of buf -- note that this is in general 217 ** larger that strlen(buf), and buf can be changed 218 ** in place if desired. 219 ** av -- arguments from the config file (can be interpolated 220 ** into the final result). 221 ** 222 ** Returns: 223 ** A pointer to the rewritten result. 224 ** NULL if not found in the map. 225 */ 226 227 char * 228 db_map_lookup(map, buf, bufsiz, av) 229 MAP *map; 230 char buf[]; 231 int bufsiz; 232 char **av; 233 { 234 DBT key, val; 235 236 key.data = buf; 237 key.size = strlen(buf); 238 if (!bitset(MF_NOFOLDCASE, map->map_flags)) 239 { 240 register char *p; 241 242 for (p = buf; *p != '\0'; p++) 243 if (isascii(*p) && isupper(*p)) 244 *p = tolower(*p); 245 } 246 if (bitset(MF_INCLNULL, map->map_flags)) 247 key.size++; 248 if (((DB *) map->map_db)->get((DB *) map->map_db, &key, &val, 0) != 0) 249 return NULL; 250 if (!bitset(MF_MATCHONLY, map->map_flags)) 251 map_rewrite(val.data, val.size, buf, bufsiz, av); 252 return buf; 253 } 254 255 #endif /* BTREE_MAP || HASH_MAP */ 256 /* 257 ** MAP_PARSEARGS -- parse config line arguments for database lookup 258 ** 259 ** Parameters: 260 ** map -- the map being initialized. 261 ** pp -- an indirect pointer to the config line. It will 262 ** be replaced with a pointer to the next field 263 ** on the line. 264 ** 265 ** Returns: 266 ** none 267 ** 268 ** Side Effects: 269 ** null terminates the filename; stores it in map 270 */ 271 272 map_parseargs(map, pp) 273 MAP *map; 274 char **pp; 275 { 276 register char *p = *pp; 277 278 for (;;) 279 { 280 while (isascii(*p) && isspace(*p)) 281 p++; 282 if (*p != '-') 283 break; 284 switch (*++p) 285 { 286 case 'N': 287 map->map_flags |= MF_INCLNULL; 288 break; 289 290 case 'o': 291 map->map_flags |= MF_OPTIONAL; 292 break; 293 294 case 'f': 295 map->map_flags |= MF_NOFOLDCASE; 296 break; 297 298 case 'm': 299 map->map_flags |= MF_MATCHONLY; 300 break; 301 302 case 'a': 303 map->map_app = ++p; 304 break; 305 306 case 'd': 307 map->map_domain = ++p; 308 break; 309 } 310 while (*p != '\0' && !(isascii(*p) && isspace(*p))) 311 p++; 312 if (*p != '\0') 313 *p++ = '\0'; 314 } 315 if (map->map_app != NULL) 316 map->map_app = newstr(map->map_app); 317 if (map->map_domain != NULL) 318 map->map_domain = newstr(map->map_domain); 319 320 if (*p != '\0') 321 { 322 map->map_file = p; 323 while (*p != '\0' && !(isascii(*p) && isspace(*p))) 324 p++; 325 if (*p != '\0') 326 *p++ = '\0'; 327 map->map_file = newstr(map->map_file); 328 } 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