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.3 (Berkeley) 01/28/93"; 11 #endif /* not lint */ 12 13 #include "sendmail.h" 14 #include <sys/file.h> 15 #include <sys/fcntl.h> 16 17 #ifdef DBM_MAP 18 #include <ndbm.h> 19 #endif 20 #if defined(HASH_MAP) || defined(BTREE_MAP) 21 #include <db.h> 22 #endif 23 #ifdef NIS_MAP 24 #include <rpcsvc/ypclnt.h> 25 #endif 26 27 28 #ifdef DBM_MAP 29 30 /* 31 ** DBM_MAP_INIT -- DBM-style map initialization 32 ** 33 ** Parameters: 34 ** map -- the pointer to the actual map 35 ** mapname -- the name of the map (for error messages) 36 ** args -- a pointer to the config file line arguments 37 ** 38 ** Returns: 39 ** TRUE -- if it could successfully open the map. 40 ** FALSE -- otherwise. 41 ** 42 ** Side Effects: 43 ** Gives an error if it can't open the map. 44 */ 45 46 bool 47 dbm_map_init(map, mapname, args) 48 MAP *map; 49 char *mapname; 50 char *args; 51 { 52 DBM *dbm; 53 54 map_parseargs(map, &args); 55 if (map->map_file == NULL) 56 { 57 syserr("No file name for DBM map %s", mapname); 58 return FALSE; 59 } 60 dbm = dbm_open(map->map_file, O_RDONLY, 0644); 61 if (dbm == NULL) 62 { 63 if (!bitset(MF_OPTIONAL, map->map_flags)) 64 syserr("Cannot open DBM database %s", map->map_file); 65 return FALSE; 66 } 67 map->map_db = (void *) dbm; 68 return TRUE; 69 } 70 /* 71 ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 72 ** 73 ** Parameters: 74 ** map -- the map to look up in. 75 ** buf -- a pointer to to the buffer containing the key. 76 ** This is a null terminated string. 77 ** bufsiz -- the size of buf -- note that this is in general 78 ** larger that strlen(buf), and buf can be changed 79 ** in place if desired. 80 ** av -- arguments from the config file (can be interpolated 81 ** into the final result). 82 ** 83 ** Returns: 84 ** A pointer to the rewritten result. 85 ** NULL if not found in the map. 86 */ 87 88 char * 89 dbm_map_lookup(map, buf, bufsiz, av) 90 MAP *map; 91 char buf[]; 92 int bufsiz; 93 char **av; 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 (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 ** 224 ** Returns: 225 ** A pointer to the rewritten result. 226 ** NULL if not found in the map. 227 */ 228 229 char * 230 db_map_lookup(map, buf, bufsiz, av) 231 MAP *map; 232 char buf[]; 233 int bufsiz; 234 char **av; 235 { 236 DBT key, val; 237 238 key.data = buf; 239 key.size = strlen(buf); 240 if (!bitset(MF_NOFOLDCASE, map->map_flags)) 241 { 242 register char *p; 243 244 for (p = buf; *p != '\0'; p++) 245 if (isupper(*p)) 246 *p = tolower(*p); 247 } 248 if (bitset(MF_INCLNULL, map->map_flags)) 249 key.size++; 250 if (((DB *) map->map_db)->get((DB *) map->map_db, &key, &val, 0) != 0) 251 return NULL; 252 if (!bitset(MF_MATCHONLY, map->map_flags)) 253 map_rewrite(val.data, val.size, buf, bufsiz, av); 254 return buf; 255 } 256 257 #endif /* BTREE_MAP || HASH_MAP */ 258 /* 259 ** MAP_PARSEARGS -- parse config line arguments for database lookup 260 ** 261 ** Parameters: 262 ** map -- the map being initialized. 263 ** pp -- an indirect pointer to the config line. It will 264 ** be replaced with a pointer to the next field 265 ** on the line. 266 ** 267 ** Returns: 268 ** none 269 ** 270 ** Side Effects: 271 ** null terminates the filename; stores it in map 272 */ 273 274 map_parseargs(map, pp) 275 MAP *map; 276 char **pp; 277 { 278 register char *p = *pp; 279 280 for (;;) 281 { 282 while (isspace(*p)) 283 p++; 284 if (*p != '-') 285 break; 286 switch (*++p) 287 { 288 case 'N': 289 map->map_flags |= MF_INCLNULL; 290 break; 291 292 case 'o': 293 map->map_flags |= MF_OPTIONAL; 294 break; 295 296 case 'f': 297 map->map_flags |= MF_NOFOLDCASE; 298 break; 299 300 case 'm': 301 map->map_flags |= MF_MATCHONLY; 302 break; 303 304 case 'a': 305 map->map_app = ++p; 306 break; 307 308 case 'd': 309 map->map_domain = ++p; 310 break; 311 } 312 while (*p != '\0' && !isspace(*p)) 313 p++; 314 if (*p != '\0') 315 *p++ = 0; 316 } 317 if (map->map_app != NULL) 318 map->map_app = newstr(map->map_app); 319 if (map->map_domain != NULL) 320 map->map_domain = newstr(map->map_domain); 321 322 if (*p == '\0') 323 return NULL; 324 map->map_file = p; 325 while (*p != '\0' && !isspace(*p)) 326 p++; 327 if (*p != '\0') 328 *p++ = '\0'; 329 map->map_file = newstr(map->map_file); 330 *pp = p; 331 } 332 333 # ifdef NIS_MAP 334 335 /* 336 ** NIS_MAP_INIT -- initialize DBM map 337 ** 338 ** Parameters: 339 ** map -- the pointer to the actual map. 340 ** mapname -- the name of the map (for error messages). 341 ** args -- a pointer to the config file line arguments. 342 ** 343 ** Returns: 344 ** TRUE -- if it could successfully open the map. 345 ** FALSE -- otherwise. 346 ** 347 ** Side Effects: 348 ** Prints an error if it can't open the map. 349 */ 350 351 bool 352 nis_map_init(map, mapname, args) 353 MAP *map; 354 char *mapname; 355 char *args; 356 { 357 int yperr; 358 char *master; 359 360 /* parse arguments */ 361 map_parseargs(map, &args); 362 if (map->map_file == NULL) 363 { 364 syserr("No NIS map name for map %s", mapname); 365 return FALSE; 366 } 367 if (map->map_domain == NULL) 368 yp_get_default_domain(&map->map_domain); 369 370 /* check to see if this map actually exists */ 371 yperr = yp_master(map->map_domain, map->map_file, &master); 372 if (yperr == 0) 373 return TRUE; 374 if (!bitset(MF_OPTIONAL, map->map_flags)) 375 syserr("Cannot bind to domain %s: %s", map->map_domain, 376 yperr_string(yperr)); 377 return FALSE; 378 } 379 /* 380 ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 381 ** 382 ** Parameters: 383 ** map -- the map to look up in. 384 ** buf -- a pointer to to the buffer containing the key. 385 ** This is a null terminated string. 386 ** bufsiz -- the size of buf -- note that this is in general 387 ** larger that strlen(buf), and buf can be changed 388 ** in place if desired. 389 ** av -- arguments from the config file (can be interpolated 390 ** into the final result). 391 ** 392 ** Returns: 393 ** A pointer to the rewritten result. 394 ** NULL if not found in the map. 395 */ 396 397 char * 398 nis_map_lookup(map, buf, bufsiz, av) 399 MAP *map; 400 char buf[]; 401 int bufsiz; 402 char **av; 403 { 404 char *vp; 405 auto int vsize; 406 407 if (!bitset(MF_NOFOLDCASE, map->map_flags)) 408 { 409 register char *p; 410 411 for (p = buf; *p != '\0'; p++) 412 if (isupper(*p)) 413 *p = tolower(*p); 414 } 415 if (yp_match(map->map_domain, map->map_file, buf, strlen(buf) + 1, 416 &vp, &vsize) != 0) 417 return NULL; 418 if (!bitset(MF_MATCHONLY, map->map_flags)) 419 map_rewrite(vp, vsize, buf, bufsiz, av); 420 return buf; 421 } 422 423 #endif /* NIS_MAP */ 424 /* 425 ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 426 ** 427 ** Parameters: 428 ** s -- the string to rewrite, NOT necessarily null terminated. 429 ** slen -- the length of s. 430 ** buf -- the place to write it. 431 ** buflen -- the length of buf. 432 ** av -- arguments to interpolate into buf. 433 ** 434 ** Returns: 435 ** none. 436 ** 437 ** Side Effects: 438 ** none. 439 */ 440 441 map_rewrite(s, slen, buf, buflen, av) 442 register char *s; 443 int slen; 444 char buf[]; 445 int buflen; 446 char **av; 447 { 448 register char *bp; 449 char *buflim; 450 register char c; 451 char **avp; 452 register char *ap; 453 454 if (tTd(23, 1)) 455 { 456 printf("map_rewrite(%.*s), av =\n", slen, s); 457 for (avp = av; *avp != NULL; avp++) 458 printf("\t%s\n", *avp); 459 } 460 461 bp = buf; 462 buflim = &buf[buflen - 2]; 463 while (--slen >= 0 && (c = *s++) != '\0') 464 { 465 if (c != '%') 466 { 467 pushc: 468 if (bp < buflim) 469 *bp++ = c; 470 continue; 471 } 472 if (--slen < 0 || (c = *s++) == '\0') 473 c = '%'; 474 if (c == '%') 475 goto pushc; 476 if (!isdigit(c)) 477 { 478 *bp++ = '%'; 479 goto pushc; 480 } 481 c -= '0'; 482 for (avp = av; --c >= 0 && *avp != NULL; avp++) 483 continue; 484 if (*avp == NULL) 485 continue; 486 487 /* transliterate argument into output string */ 488 for (ap = *avp; (c = *ap++) != '\0'; ) 489 { 490 if (bp < buflim) 491 *bp++ = c; 492 } 493 } 494 *bp++ = '\0'; 495 if (tTd(23, 1)) 496 printf("map_rewrite => %s\n", buf); 497 } 498