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.8 (Berkeley) 04/04/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 330 while (*p != '\0' && isascii(*p) && isspace(*p)) 331 p++; 332 *pp = p; 333 if (*p != '\0') 334 map->map_rebuild = newstr(p); 335 } 336 337 # ifdef NIS_MAP 338 339 /* 340 ** NIS_MAP_INIT -- initialize DBM map 341 ** 342 ** Parameters: 343 ** map -- the pointer to the actual map. 344 ** mapname -- the name of the map (for error messages). 345 ** args -- a pointer to the config file line arguments. 346 ** 347 ** Returns: 348 ** TRUE -- if it could successfully open the map. 349 ** FALSE -- otherwise. 350 ** 351 ** Side Effects: 352 ** Prints an error if it can't open the map. 353 */ 354 355 bool 356 nis_map_init(map, mapname, args) 357 MAP *map; 358 char *mapname; 359 char *args; 360 { 361 int yperr; 362 char *master; 363 364 /* parse arguments */ 365 map_parseargs(map, &args); 366 if (map->map_file == NULL) 367 { 368 syserr("No NIS map name for map %s", mapname); 369 return FALSE; 370 } 371 if (map->map_domain == NULL) 372 yp_get_default_domain(&map->map_domain); 373 374 /* check to see if this map actually exists */ 375 yperr = yp_master(map->map_domain, map->map_file, &master); 376 if (yperr == 0) 377 return TRUE; 378 if (!bitset(MF_OPTIONAL, map->map_flags)) 379 syserr("Cannot bind to domain %s: %s", map->map_domain, 380 yperr_string(yperr)); 381 return FALSE; 382 } 383 /* 384 ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 385 ** 386 ** Parameters: 387 ** map -- the map to look up in. 388 ** buf -- a pointer to to the buffer containing the key. 389 ** This is a null terminated string. 390 ** bufsiz -- the size of buf -- note that this is in general 391 ** larger that strlen(buf), and buf can be changed 392 ** in place if desired. 393 ** av -- arguments from the config file (can be interpolated 394 ** into the final result). 395 ** 396 ** Returns: 397 ** A pointer to the rewritten result. 398 ** NULL if not found in the map. 399 */ 400 401 char * 402 nis_map_lookup(map, buf, bufsiz, av) 403 MAP *map; 404 char buf[]; 405 int bufsiz; 406 char **av; 407 { 408 char *vp; 409 auto int vsize; 410 411 if (!bitset(MF_NOFOLDCASE, map->map_flags)) 412 { 413 register char *p; 414 415 for (p = buf; *p != '\0'; p++) 416 if (isascii(*p) && isupper(*p)) 417 *p = tolower(*p); 418 } 419 if (yp_match(map->map_domain, map->map_file, buf, strlen(buf) + 1, 420 &vp, &vsize) != 0) 421 return NULL; 422 if (!bitset(MF_MATCHONLY, map->map_flags)) 423 map_rewrite(vp, vsize, buf, bufsiz, av); 424 return buf; 425 } 426 427 #endif /* NIS_MAP */ 428 /* 429 ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 430 ** 431 ** Parameters: 432 ** s -- the string to rewrite, NOT necessarily null terminated. 433 ** slen -- the length of s. 434 ** buf -- the place to write it. 435 ** buflen -- the length of buf. 436 ** av -- arguments to interpolate into buf. 437 ** 438 ** Returns: 439 ** none. 440 ** 441 ** Side Effects: 442 ** none. 443 */ 444 445 map_rewrite(s, slen, buf, buflen, av) 446 register char *s; 447 int slen; 448 char buf[]; 449 int buflen; 450 char **av; 451 { 452 register char *bp; 453 char *buflim; 454 register char c; 455 char **avp; 456 register char *ap; 457 458 if (tTd(23, 1)) 459 { 460 printf("map_rewrite(%.*s), av =\n", slen, s); 461 for (avp = av; *avp != NULL; avp++) 462 printf("\t%s\n", *avp); 463 } 464 465 bp = buf; 466 buflim = &buf[buflen - 2]; 467 while (--slen >= 0 && (c = *s++) != '\0') 468 { 469 if (c != '%') 470 { 471 pushc: 472 if (bp < buflim) 473 *bp++ = c; 474 continue; 475 } 476 if (--slen < 0 || (c = *s++) == '\0') 477 c = '%'; 478 if (c == '%') 479 goto pushc; 480 if (!(isascii(c) && isdigit(c))) 481 { 482 *bp++ = '%'; 483 goto pushc; 484 } 485 c -= '0'; 486 for (avp = av; --c >= 0 && *avp != NULL; avp++) 487 continue; 488 if (*avp == NULL) 489 continue; 490 491 /* transliterate argument into output string */ 492 for (ap = *avp; (c = *ap++) != '\0'; ) 493 { 494 if (bp < buflim) 495 *bp++ = c; 496 } 497 } 498 *bp++ = '\0'; 499 if (tTd(23, 1)) 500 printf("map_rewrite => %s\n", buf); 501 } 502