156822Seric /* 256822Seric * Copyright (c) 1992 Eric P. Allman. 356822Seric * Copyright (c) 1992 Regents of the University of California. 456822Seric * All rights reserved. 556822Seric * 656822Seric * %sccs.include.redist.c% 756822Seric */ 856822Seric 956822Seric #ifndef lint 10*60537Seric static char sccsid[] = "@(#)map.c 6.22 (Berkeley) 05/28/93"; 1156822Seric #endif /* not lint */ 1256822Seric 1356822Seric #include "sendmail.h" 1456822Seric 1560089Seric #ifdef NDBM 1656822Seric #include <ndbm.h> 1756822Seric #endif 1860089Seric #ifdef NEWDB 1956822Seric #include <db.h> 2056822Seric #endif 2160089Seric #ifdef NIS 2257208Seric #include <rpcsvc/ypclnt.h> 2357208Seric #endif 2456822Seric 2556822Seric /* 2660089Seric ** MAP.C -- implementations for various map classes. 2756822Seric ** 2860089Seric ** Each map class implements a series of functions: 2960089Seric ** 3060089Seric ** bool map_parse(MAP *map, char *args) 3160089Seric ** Parse the arguments from the config file. Return TRUE 3260089Seric ** if they were ok, FALSE otherwise. Fill in map with the 3360089Seric ** values. 3460089Seric ** 3560222Seric ** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 3660222Seric ** Look up the key in the given map. If found, do any 3760222Seric ** rewriting the map wants (including "args" if desired) 3860089Seric ** and return the value. Set *pstat to the appropriate status 3960222Seric ** on error and return NULL. Args will be NULL if called 4060222Seric ** from the alias routines, although this should probably 4160222Seric ** not be relied upon. It is suggested you call map_rewrite 4260222Seric ** to return the results -- it takes care of null termination 4360222Seric ** and uses a dynamically expanded buffer as needed. 4460089Seric ** 4560089Seric ** void map_store(MAP *map, char *key, char *value) 4660089Seric ** Store the key:value pair in the map. 4760089Seric ** 4860089Seric ** bool map_open(MAP *map, int mode) 4960222Seric ** Open the map for the indicated mode. Mode should 5060222Seric ** be either O_RDONLY or O_RDWR. Return TRUE if it 5160222Seric ** was opened successfully, FALSE otherwise. If the open 5260222Seric ** failed an the MF_OPTIONAL flag is not set, it should 5360222Seric ** also print an error. If the MF_ALIAS bit is set 5460222Seric ** and this map class understands the @:@ convention, it 5560222Seric ** should call aliaswait() before returning. 5660089Seric ** 5760089Seric ** void map_close(MAP *map) 5860089Seric ** Close the map. 5960089Seric */ 6060089Seric 6160089Seric #define DBMMODE 0644 6260089Seric /* 6360089Seric ** MAP_PARSEARGS -- parse config line arguments for database lookup 6460089Seric ** 6560089Seric ** This is a generic version of the map_parse method. 6660089Seric ** 6756822Seric ** Parameters: 6860089Seric ** map -- the map being initialized. 6960089Seric ** ap -- a pointer to the args on the config line. 7056822Seric ** 7156822Seric ** Returns: 7260089Seric ** TRUE -- if everything parsed OK. 7356822Seric ** FALSE -- otherwise. 7456822Seric ** 7556822Seric ** Side Effects: 7660089Seric ** null terminates the filename; stores it in map 7756822Seric */ 7856822Seric 7956822Seric bool 8060089Seric map_parseargs(map, ap) 8156822Seric MAP *map; 8260089Seric char *ap; 8356822Seric { 8460089Seric register char *p = ap; 8556822Seric 8660089Seric for (;;) 8760089Seric { 8860089Seric while (isascii(*p) && isspace(*p)) 8960089Seric p++; 9060089Seric if (*p != '-') 9160089Seric break; 9260089Seric switch (*++p) 9360089Seric { 9460089Seric case 'N': 9560207Seric map->map_mflags |= MF_INCLNULL; 9660089Seric break; 9760089Seric 9860089Seric case 'o': 9960207Seric map->map_mflags |= MF_OPTIONAL; 10060089Seric break; 10160089Seric 10260089Seric case 'f': 10360207Seric map->map_mflags |= MF_NOFOLDCASE; 10460089Seric break; 10560089Seric 10660089Seric case 'm': 10760207Seric map->map_mflags |= MF_MATCHONLY; 10860089Seric break; 10960089Seric 11060089Seric case 'a': 11160089Seric map->map_app = ++p; 11260089Seric break; 11360089Seric } 11460089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 11560089Seric p++; 11660089Seric if (*p != '\0') 11760089Seric *p++ = '\0'; 11860089Seric } 11960089Seric if (map->map_app != NULL) 12060089Seric map->map_app = newstr(map->map_app); 12160089Seric 12260089Seric if (*p != '\0') 12360089Seric { 12460089Seric map->map_file = p; 12560089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 12660089Seric p++; 12760089Seric if (*p != '\0') 12860089Seric *p++ = '\0'; 12960089Seric map->map_file = newstr(map->map_file); 13060089Seric } 13160089Seric 13260089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 13360089Seric p++; 13460089Seric if (*p != '\0') 13560089Seric map->map_rebuild = newstr(p); 13660089Seric 13756822Seric if (map->map_file == NULL) 13857208Seric { 13960089Seric syserr("No file name for %s map %s", 14060089Seric map->map_class->map_cname, map->map_mname); 14156822Seric return FALSE; 14257208Seric } 14360089Seric return TRUE; 14460089Seric } 14560089Seric /* 14660089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 14760089Seric ** 14860089Seric ** It also adds the map_app string. It can be used as a utility 14960089Seric ** in the map_lookup method. 15060089Seric ** 15160089Seric ** Parameters: 15260089Seric ** map -- the map that causes this. 15360089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 15460089Seric ** slen -- the length of s. 15560089Seric ** av -- arguments to interpolate into buf. 15660089Seric ** 15760089Seric ** Returns: 15860089Seric ** Pointer to rewritten result. 15960089Seric ** 16060089Seric ** Side Effects: 16160089Seric ** none. 16260089Seric */ 16360089Seric 16460492Seric struct rwbuf 16560492Seric { 16660492Seric int rwb_len; /* size of buffer */ 16760492Seric char *rwb_buf; /* ptr to buffer */ 16860492Seric }; 16960492Seric 17060492Seric struct rwbuf RwBufs[2]; /* buffers for rewriting output */ 17160492Seric 17260089Seric char * 17360089Seric map_rewrite(map, s, slen, av) 17460089Seric register MAP *map; 17560089Seric register char *s; 17660089Seric int slen; 17760089Seric char **av; 17860089Seric { 17960089Seric register char *bp; 18060089Seric register char c; 18160089Seric char **avp; 18260089Seric register char *ap; 18360492Seric register struct rwbuf *rwb; 18460089Seric int i; 18560089Seric int len; 18660089Seric 187*60537Seric if (tTd(39, 1)) 18860089Seric { 18960256Seric printf("map_rewrite(%.*s), av =", slen, s); 19060256Seric if (av == NULL) 19160256Seric printf(" (nullv)"); 19260256Seric else 19360256Seric { 19460256Seric for (avp = av; *avp != NULL; avp++) 19560256Seric printf("\n\t%s", *avp); 19660256Seric } 19760256Seric printf("\n"); 19860089Seric } 19960089Seric 20060492Seric rwb = RwBufs; 20160492Seric if (av == NULL) 20260492Seric rwb++; 20360492Seric 20460089Seric /* count expected size of output (can safely overestimate) */ 20560089Seric i = len = slen; 20660089Seric if (av != NULL) 20760089Seric { 20860089Seric bp = s; 20960089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 21060089Seric { 21160089Seric if (c != '%') 21260089Seric continue; 21360089Seric if (--i < 0) 21460089Seric break; 21560089Seric c = *bp++; 21660089Seric if (!(isascii(c) && isdigit(c))) 21760089Seric continue; 21860089Seric c -= 0; 21960089Seric for (avp = av; --c >= 0 && *avp != NULL; avp++) 22060089Seric continue; 22160089Seric if (*avp == NULL) 22260089Seric continue; 22360089Seric len += strlen(*avp); 22460089Seric } 22560089Seric } 22660089Seric if (map->map_app != NULL) 22760089Seric len += strlen(map->map_app); 22860492Seric if (rwb->rwb_len < ++len) 22960089Seric { 23060089Seric /* need to malloc additional space */ 23160492Seric rwb->rwb_len = len; 23260492Seric if (rwb->rwb_buf != NULL) 23360492Seric free(rwb->rwb_buf); 23460492Seric rwb->rwb_buf = xalloc(rwb->rwb_len); 23560089Seric } 23660089Seric 23760492Seric bp = rwb->rwb_buf; 23860089Seric if (av == NULL) 23960089Seric { 24060089Seric bcopy(s, bp, slen); 24160089Seric bp += slen; 24260089Seric } 24360089Seric else 24460089Seric { 24560089Seric while (--slen >= 0 && (c = *s++) != '\0') 24660089Seric { 24760089Seric if (c != '%') 24860089Seric { 24960089Seric pushc: 25060089Seric *bp++ = c; 25160089Seric continue; 25260089Seric } 25360089Seric if (--slen < 0 || (c = *s++) == '\0') 25460089Seric c = '%'; 25560089Seric if (c == '%') 25660089Seric goto pushc; 25760089Seric if (!(isascii(c) && isdigit(c))) 25860089Seric { 25960089Seric *bp++ = '%'; 26060089Seric goto pushc; 26160089Seric } 26260089Seric c -= '0'; 26360089Seric for (avp = av; --c >= 0 && *avp != NULL; avp++) 26460089Seric continue; 26560089Seric if (*avp == NULL) 26660089Seric continue; 26760089Seric 26860089Seric /* transliterate argument into output string */ 26960089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 27060089Seric *bp++ = c; 27160089Seric } 27260089Seric } 27360089Seric if (map->map_app != NULL) 27460089Seric strcpy(bp, map->map_app); 27560089Seric else 27660089Seric *bp = '\0'; 277*60537Seric if (tTd(39, 1)) 27860492Seric printf("map_rewrite => %s\n", rwb->rwb_buf); 27960492Seric return rwb->rwb_buf; 28060089Seric } 28160089Seric /* 282*60537Seric ** INITMAPS -- initialize for aliasing 283*60537Seric ** 284*60537Seric ** Parameters: 285*60537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 286*60537Seric ** e -- current envelope. 287*60537Seric ** 288*60537Seric ** Returns: 289*60537Seric ** none. 290*60537Seric ** 291*60537Seric ** Side Effects: 292*60537Seric ** initializes aliases: 293*60537Seric ** if NDBM: opens the database. 294*60537Seric ** if ~NDBM: reads the aliases into the symbol table. 295*60537Seric */ 296*60537Seric 297*60537Seric initmaps(rebuild, e) 298*60537Seric bool rebuild; 299*60537Seric register ENVELOPE *e; 300*60537Seric { 301*60537Seric extern void map_init(); 302*60537Seric 303*60537Seric CurEnv = e; 304*60537Seric stabapply(map_init, rebuild); 305*60537Seric } 306*60537Seric 307*60537Seric void 308*60537Seric map_init(s, rebuild) 309*60537Seric register STAB *s; 310*60537Seric int rebuild; 311*60537Seric { 312*60537Seric register MAP *map; 313*60537Seric 314*60537Seric /* has to be a map */ 315*60537Seric if (s->s_type != ST_MAP) 316*60537Seric return; 317*60537Seric 318*60537Seric map = &s->s_map; 319*60537Seric if (!bitset(MF_VALID, map->map_mflags)) 320*60537Seric return; 321*60537Seric 322*60537Seric if (tTd(38, 2)) 323*60537Seric printf("map_init(%s:%s)\n", 324*60537Seric map->map_class->map_cname, map->map_file); 325*60537Seric 326*60537Seric /* if already open, close it (for nested open) */ 327*60537Seric if (bitset(MF_OPEN, map->map_mflags)) 328*60537Seric { 329*60537Seric map->map_class->map_close(map); 330*60537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 331*60537Seric } 332*60537Seric 333*60537Seric if (rebuild) 334*60537Seric { 335*60537Seric if (bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 336*60537Seric rebuildaliases(map, FALSE); 337*60537Seric } 338*60537Seric else 339*60537Seric { 340*60537Seric if (map->map_class->map_open(map, O_RDONLY)) 341*60537Seric { 342*60537Seric if (tTd(38, 4)) 343*60537Seric printf("%s:%s: valid\n", 344*60537Seric map->map_class->map_cname, 345*60537Seric map->map_file); 346*60537Seric map->map_mflags |= MF_OPEN; 347*60537Seric } 348*60537Seric else if (tTd(38, 4)) 349*60537Seric printf("%s:%s: invalid: %s\n", 350*60537Seric map->map_class->map_cname, 351*60537Seric map->map_file, 352*60537Seric errstring(errno)); 353*60537Seric } 354*60537Seric } 355*60537Seric /* 35660089Seric ** NDBM modules 35760089Seric */ 35860089Seric 35960089Seric #ifdef NDBM 36060089Seric 36160089Seric /* 36260089Seric ** DBM_MAP_OPEN -- DBM-style map open 36360089Seric */ 36460089Seric 36560089Seric bool 36660089Seric ndbm_map_open(map, mode) 36760089Seric MAP *map; 36860089Seric int mode; 36960089Seric { 37060089Seric DBM *dbm; 37160089Seric 372*60537Seric if (tTd(38, 2)) 37360089Seric printf("ndbm_map_open(%s, %d)\n", map->map_file, mode); 37460089Seric 37560207Seric if (mode == O_RDWR) 37660207Seric mode |= O_CREAT|O_TRUNC; 37760207Seric 37860089Seric /* open the database */ 37960089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 38056822Seric if (dbm == NULL) 38156822Seric { 38260207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 38356836Seric syserr("Cannot open DBM database %s", map->map_file); 38456822Seric return FALSE; 38556822Seric } 38660089Seric map->map_db1 = (void *) dbm; 38760207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 38860207Seric aliaswait(map, ".dir"); 38956822Seric return TRUE; 39056822Seric } 39160089Seric 39260089Seric 39360089Seric /* 39456822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 39556822Seric */ 39656822Seric 39756822Seric char * 39860089Seric ndbm_map_lookup(map, name, av, statp) 39956822Seric MAP *map; 40060089Seric char *name; 40156822Seric char **av; 40259084Seric int *statp; 40356822Seric { 40456822Seric datum key, val; 40560089Seric char keybuf[MAXNAME + 1]; 40656822Seric 407*60537Seric if (tTd(38, 20)) 40860089Seric printf("ndbm_map_lookup(%s)\n", name); 40960089Seric 41060089Seric key.dptr = name; 41160089Seric key.dsize = strlen(name); 41260207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 41357014Seric { 41460089Seric if (key.dsize > sizeof keybuf - 1) 41560089Seric key.dsize = sizeof keybuf - 1; 41660089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 41760089Seric makelower(keybuf); 41860089Seric key.dptr = keybuf; 41957014Seric } 42060207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 42156822Seric key.dsize++; 42260089Seric (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH); 42360089Seric val = dbm_fetch((DBM *) map->map_db1, key); 42460089Seric (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN); 42556822Seric if (val.dptr == NULL) 42656822Seric return NULL; 42760207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 42860089Seric av = NULL; 42960089Seric return map_rewrite(map, val.dptr, val.dsize, av); 43056822Seric } 43156822Seric 43256822Seric 43356822Seric /* 43460089Seric ** DBM_MAP_STORE -- store a datum in the database 43556822Seric */ 43656822Seric 43760089Seric void 43860089Seric ndbm_map_store(map, lhs, rhs) 43960089Seric register MAP *map; 44060089Seric char *lhs; 44160089Seric char *rhs; 44260089Seric { 44360089Seric datum key; 44460089Seric datum data; 44560089Seric int stat; 44660089Seric 447*60537Seric if (tTd(38, 12)) 44860089Seric printf("ndbm_map_store(%s, %s)\n", lhs, rhs); 44960089Seric 45060089Seric key.dsize = strlen(lhs); 45160089Seric key.dptr = lhs; 45260089Seric 45360089Seric data.dsize = strlen(rhs); 45460089Seric data.dptr = rhs; 45560089Seric 45660207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 45760089Seric { 45860089Seric key.dsize++; 45960089Seric data.dsize++; 46060089Seric } 46160089Seric 46260089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 46360089Seric if (stat > 0) 46460089Seric { 46560089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 46660089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 46760089Seric } 46860089Seric if (stat != 0) 46960089Seric syserr("readaliases: dbm put (%s)", lhs); 47060089Seric } 47160089Seric 47260089Seric 47360089Seric /* 47460207Seric ** NDBM_MAP_CLOSE -- close the database 47560089Seric */ 47660089Seric 47760089Seric void 47860089Seric ndbm_map_close(map) 47960089Seric register MAP *map; 48060089Seric { 48160207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 48260089Seric { 48360089Seric #ifdef YPCOMPAT 48460089Seric char buf[200]; 48560089Seric 48660089Seric (void) sprintf(buf, "%010ld", curtime()); 48760089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 48860089Seric 48960089Seric (void) myhostname(buf, sizeof buf); 49060089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 49160089Seric #endif 49260089Seric 49360089Seric /* write out the distinguished alias */ 49460089Seric ndbm_map_store(map, "@", "@"); 49560089Seric } 49660089Seric dbm_close((DBM *) map->map_db1); 49760089Seric } 49860089Seric 49960089Seric #endif 50060089Seric /* 50160089Seric ** HASH (NEWDB) Modules 50260089Seric */ 50360089Seric 50460089Seric #ifdef NEWDB 50560089Seric 50660089Seric /* 50760089Seric ** BTREE_MAP_PARSE -- BTREE-style map initialization 50860089Seric */ 50960089Seric 51056822Seric bool 51160089Seric bt_map_open(map, mode) 51256822Seric MAP *map; 51360089Seric int mode; 51456822Seric { 51556822Seric DB *db; 51660228Seric int i; 51760089Seric char buf[MAXNAME]; 51856822Seric 519*60537Seric if (tTd(38, 2)) 52060089Seric printf("bt_map_open(%s, %d)\n", map->map_file, mode); 52160089Seric 52260207Seric if (mode == O_RDWR) 52360207Seric mode |= O_CREAT|O_TRUNC; 52460207Seric 52560228Seric (void) strcpy(buf, map->map_file); 52660228Seric i = strlen(buf); 52760228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 52860228Seric (void) strcat(buf, ".db"); 52960222Seric db = dbopen(buf, mode, DBMMODE, DB_BTREE, NULL); 53056822Seric if (db == NULL) 53156822Seric { 53260207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 53356836Seric syserr("Cannot open BTREE database %s", map->map_file); 53456822Seric return FALSE; 53556822Seric } 53660089Seric map->map_db2 = (void *) db; 53760207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 53860207Seric aliaswait(map, ".db"); 53956822Seric return TRUE; 54056822Seric } 54156822Seric 54256822Seric 54356822Seric /* 54456822Seric ** HASH_MAP_INIT -- HASH-style map initialization 54556822Seric */ 54656822Seric 54756822Seric bool 54860089Seric hash_map_open(map, mode) 54956822Seric MAP *map; 55060089Seric int mode; 55156822Seric { 55256822Seric DB *db; 55360228Seric int i; 55460089Seric char buf[MAXNAME]; 55556822Seric 556*60537Seric if (tTd(38, 2)) 55760089Seric printf("hash_map_open(%s, %d)\n", map->map_file, mode); 55860089Seric 55960207Seric if (mode == O_RDWR) 56060207Seric mode |= O_CREAT|O_TRUNC; 56160207Seric 56260228Seric (void) strcpy(buf, map->map_file); 56360228Seric i = strlen(buf); 56460228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 56560228Seric (void) strcat(buf, ".db"); 56660222Seric db = dbopen(buf, mode, DBMMODE, DB_HASH, NULL); 56756822Seric if (db == NULL) 56856822Seric { 56960207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 57056836Seric syserr("Cannot open HASH database %s", map->map_file); 57156822Seric return FALSE; 57256822Seric } 57360089Seric map->map_db2 = (void *) db; 57460207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 57560207Seric aliaswait(map, ".db"); 57656822Seric return TRUE; 57756822Seric } 57856822Seric 57956822Seric 58056822Seric /* 58156822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 58256822Seric */ 58356822Seric 58456822Seric char * 58560089Seric db_map_lookup(map, name, av, statp) 58656822Seric MAP *map; 58760089Seric char *name; 58856822Seric char **av; 58959084Seric int *statp; 59056822Seric { 59156822Seric DBT key, val; 59260422Seric register DB *db = (DB *) map->map_db2; 59360422Seric int st; 59460422Seric int saveerrno; 59560089Seric char keybuf[MAXNAME + 1]; 59656822Seric 597*60537Seric if (tTd(38, 20)) 59860089Seric printf("db_map_lookup(%s)\n", name); 59960089Seric 60060089Seric key.size = strlen(name); 60160089Seric if (key.size > sizeof keybuf - 1) 60260089Seric key.size = sizeof keybuf - 1; 60360089Seric key.data = keybuf; 60460089Seric bcopy(name, keybuf, key.size + 1); 60560207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 60660089Seric makelower(keybuf); 60760207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 60856822Seric key.size++; 60960422Seric #ifndef OLD_NEWDB 61060422Seric (void) lockfile(db->fd(db), map->map_file, LOCK_SH); 61160422Seric #endif 61260422Seric st = db->get(db, &key, &val, 0); 61360422Seric saveerrno = errno; 61460422Seric #ifndef OLD_NEWDB 61560422Seric (void) lockfile(db->fd(db), map->map_file, LOCK_UN); 61660422Seric #endif 61760422Seric if (st != 0) 61860422Seric { 61960422Seric errno = saveerrno; 62060422Seric if (st < 0) 62160422Seric syserr("db_map_lookup: get (%s)", name); 62256822Seric return NULL; 62360422Seric } 62460207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 62560089Seric av = NULL; 62660089Seric return map_rewrite(map, val.data, val.size, av); 62756822Seric } 62856822Seric 62960089Seric 63060089Seric /* 63160089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 63256822Seric */ 63356822Seric 63460089Seric void 63560089Seric db_map_store(map, lhs, rhs) 63660089Seric register MAP *map; 63760089Seric char *lhs; 63860089Seric char *rhs; 63956822Seric { 64060089Seric int stat; 64160089Seric DBT key; 64260089Seric DBT data; 64360089Seric register DB *db = map->map_db2; 64456822Seric 645*60537Seric if (tTd(38, 20)) 64660089Seric printf("db_map_store(%s, %s)\n", lhs, rhs); 64760089Seric 64860089Seric key.size = strlen(lhs); 64960089Seric key.data = lhs; 65060089Seric 65160089Seric data.size = strlen(rhs); 65260089Seric data.data = rhs; 65360089Seric 65460207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 65556822Seric { 65660089Seric key.size++; 65760089Seric data.size++; 65860089Seric } 65956836Seric 66060089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 66160089Seric if (stat > 0) 66260089Seric { 66360089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 66460089Seric stat = db->put(db, &key, &data, 0); 66560089Seric } 66660089Seric if (stat != 0) 66760089Seric syserr("readaliases: db put (%s)", lhs); 66860089Seric } 66956836Seric 67056847Seric 67160089Seric /* 67260089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 67360089Seric */ 67460089Seric 67560089Seric void 67660089Seric db_map_close(map) 67760089Seric MAP *map; 67860089Seric { 67960089Seric register DB *db = map->map_db2; 68060089Seric 681*60537Seric if (tTd(38, 9)) 68260207Seric printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags); 68360089Seric 68460207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 68558804Seric { 68660089Seric /* write out the distinguished alias */ 68760089Seric db_map_store(map, "@", "@"); 68858804Seric } 68958963Seric 69060089Seric if (db->close(db) != 0) 69160089Seric syserr("readaliases: db close failure"); 69256822Seric } 69357208Seric 69460089Seric #endif 69560089Seric /* 69660089Seric ** NIS Modules 69760089Seric */ 69860089Seric 69960089Seric # ifdef NIS 70060089Seric 70157208Seric /* 70260089Seric ** NIS_MAP_OPEN -- open DBM map 70357208Seric */ 70457208Seric 70557208Seric bool 70660089Seric nis_map_open(map, mode) 70757208Seric MAP *map; 70860089Seric int mode; 70957208Seric { 71057216Seric int yperr; 71160215Seric register char *p; 71260215Seric auto char *vp; 71360215Seric auto int vsize; 71457216Seric char *master; 71557216Seric 716*60537Seric if (tTd(38, 2)) 71760089Seric printf("nis_map_open(%s)\n", map->map_file); 71860089Seric 71960207Seric if (mode != O_RDONLY) 72060207Seric { 72160207Seric errno = ENODEV; 72260207Seric return FALSE; 72360207Seric } 72460207Seric 72560089Seric p = strchr(map->map_file, '@'); 72660089Seric if (p != NULL) 72760089Seric { 72860089Seric *p++ = '\0'; 72960089Seric if (*p != '\0') 73060089Seric map->map_domain = p; 73160089Seric } 73260215Seric 73360089Seric if (map->map_domain == NULL) 73460089Seric yp_get_default_domain(&map->map_domain); 73560089Seric 73660089Seric if (*map->map_file == '\0') 73760089Seric map->map_file = "mail.aliases"; 73860089Seric 73960215Seric /* check to see if this map actually exists */ 74060089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 74160089Seric &vp, &vsize); 742*60537Seric if (tTd(38, 10)) 74360089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 74460089Seric map->map_domain, map->map_file, yperr_string(yperr)); 74560089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 74660089Seric return TRUE; 74760215Seric 74860215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 74960215Seric syserr("Cannot bind to domain %s: %s", map->map_domain, 75060215Seric yperr_string(yperr)); 75160215Seric 75260089Seric return FALSE; 75360089Seric } 75460089Seric 75560089Seric 75660089Seric /* 75757208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 75857208Seric */ 75957208Seric 76057208Seric char * 76160089Seric nis_map_lookup(map, name, av, statp) 76257208Seric MAP *map; 76360089Seric char *name; 76457208Seric char **av; 76559084Seric int *statp; 76657208Seric { 76757208Seric char *vp; 76857642Seric auto int vsize; 76959274Seric int buflen; 77060215Seric int yperr; 77160089Seric char keybuf[MAXNAME + 1]; 77257208Seric 773*60537Seric if (tTd(38, 20)) 77460089Seric printf("nis_map_lookup(%s)\n", name); 77560089Seric 77660089Seric buflen = strlen(name); 77760089Seric if (buflen > sizeof keybuf - 1) 77860089Seric buflen = sizeof keybuf - 1; 77960089Seric bcopy(name, keybuf, buflen + 1); 78060207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 78160089Seric makelower(keybuf); 78260207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 78359274Seric buflen++; 78460089Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 78560089Seric &vp, &vsize); 78660089Seric if (yperr != 0) 78760089Seric { 78860089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 78960215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 79057208Seric return NULL; 79160089Seric } 79260207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 79360089Seric av = NULL; 79460215Seric return map_rewrite(map, vp, vsize, av); 79557208Seric } 79657208Seric 79760089Seric 79860089Seric /* 79960207Seric ** NIS_MAP_STORE 80060089Seric */ 80160089Seric 80260089Seric void 80360089Seric nis_map_store(map, lhs, rhs) 80460089Seric MAP *map; 80560089Seric char *lhs; 80660089Seric char *rhs; 80760089Seric { 80860089Seric /* nothing */ 80960089Seric } 81060089Seric 81160089Seric 81260089Seric /* 81360207Seric ** NIS_MAP_CLOSE 81460089Seric */ 81560089Seric 81660089Seric void 81760089Seric nis_map_close(map) 81860089Seric MAP *map; 81960089Seric { 82060089Seric /* nothing */ 82160089Seric } 82260089Seric 82360089Seric #endif /* NIS */ 82457208Seric /* 82560089Seric ** STAB (Symbol Table) Modules 82660089Seric */ 82760089Seric 82860089Seric 82960089Seric /* 83060207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 83160089Seric */ 83260089Seric 83360089Seric char * 83460089Seric stab_map_lookup(map, name) 83560089Seric register MAP *map; 83660089Seric char *name; 83760089Seric { 83860089Seric register STAB *s; 83960089Seric 840*60537Seric if (tTd(38, 20)) 84160089Seric printf("stab_lookup(%s)\n", name); 84260089Seric 84360089Seric s = stab(name, ST_ALIAS, ST_FIND); 84460089Seric if (s != NULL) 84560089Seric return (s->s_alias); 84660089Seric return (NULL); 84760089Seric } 84860089Seric 84960089Seric 85060089Seric /* 85160207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 85260089Seric */ 85360089Seric 85460089Seric void 85560089Seric stab_map_store(map, lhs, rhs) 85660089Seric register MAP *map; 85760089Seric char *lhs; 85860089Seric char *rhs; 85960089Seric { 86060089Seric register STAB *s; 86160089Seric 86260089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 86360089Seric s->s_alias = newstr(rhs); 86460089Seric } 86560089Seric 86660089Seric 86760089Seric /* 86860207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 86960207Seric ** 87060207Seric ** This is a wierd case -- it is only intended as a fallback for 87160207Seric ** aliases. For this reason, opens for write (only during a 87260207Seric ** "newaliases") always fails, and opens for read open the 87360207Seric ** actual underlying text file instead of the database. 87460089Seric */ 87560089Seric 87660089Seric bool 87760089Seric stab_map_open(map, mode) 87860089Seric register MAP *map; 87960089Seric int mode; 88060089Seric { 88160089Seric FILE *af; 88260089Seric 883*60537Seric if (tTd(38, 2)) 88460089Seric printf("stab_map_open(%s)\n", map->map_file); 88560089Seric 88660089Seric if (mode != O_RDONLY) 88760207Seric { 88860207Seric errno = ENODEV; 88960089Seric return FALSE; 89060207Seric } 89160089Seric 89260089Seric return TRUE; 89360089Seric } 89460089Seric 89560089Seric 89660089Seric /* 89760207Seric ** STAB_MAP_CLOSE -- close symbol table (???) 89860089Seric */ 89960089Seric 90060089Seric void 90160089Seric stab_map_close(map) 90260089Seric MAP *map; 90360089Seric { 90460089Seric /* ignore it */ 90560089Seric } 90660089Seric /* 90760089Seric ** Implicit Modules 90856822Seric ** 90960089Seric ** Tries several types. For back compatibility of aliases. 91056822Seric */ 91156822Seric 91260089Seric 91360089Seric /* 91460207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 91560089Seric */ 91660089Seric 91760089Seric char * 91860089Seric impl_map_lookup(map, name, av, pstat) 91960089Seric MAP *map; 92060089Seric char *name; 92156822Seric char **av; 92260089Seric int *pstat; 92356822Seric { 924*60537Seric if (tTd(38, 20)) 92560089Seric printf("impl_map_lookup(%s)\n", name); 92656822Seric 92760089Seric #ifdef NEWDB 92860207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 92960089Seric return db_map_lookup(map, name, av, pstat); 93060089Seric #endif 93160089Seric #ifdef NDBM 93260207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 93360089Seric return ndbm_map_lookup(map, name, av, pstat); 93460089Seric #endif 93560089Seric return stab_map_lookup(map, name, av, pstat); 93660089Seric } 93760089Seric 93860089Seric /* 93960207Seric ** IMPL_MAP_STORE -- store in open databases 94060089Seric */ 94160089Seric 94260089Seric void 94360089Seric impl_map_store(map, lhs, rhs) 94460089Seric MAP *map; 94560089Seric char *lhs; 94660089Seric char *rhs; 94760089Seric { 94860089Seric #ifdef NEWDB 94960207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 95060089Seric db_map_store(map, lhs, rhs); 95160089Seric #endif 95260089Seric #ifdef NDBM 95360207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 95460089Seric ndbm_map_store(map, lhs, rhs); 95560089Seric #endif 95660089Seric stab_map_store(map, lhs, rhs); 95760089Seric } 95860089Seric 95960089Seric /* 96060089Seric ** IMPL_MAP_OPEN -- implicit database open 96160089Seric */ 96260089Seric 96360089Seric bool 96460089Seric impl_map_open(map, mode) 96560089Seric MAP *map; 96660089Seric int mode; 96760089Seric { 96860089Seric struct stat stb; 96960089Seric 970*60537Seric if (tTd(38, 2)) 97160089Seric printf("impl_map_open(%s)\n", map->map_file); 97260089Seric 97360089Seric if (stat(map->map_file, &stb) < 0) 97456822Seric { 97560089Seric /* no alias file at all */ 97660089Seric return FALSE; 97756822Seric } 97856822Seric 97960089Seric #ifdef NEWDB 98060207Seric map->map_mflags |= MF_IMPL_HASH; 98160089Seric if (hash_map_open(map, mode)) 98256822Seric { 98360207Seric #if defined(NDBM) && defined(YPCOMPAT) 98460207Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) == 0) 98560207Seric #endif 98660207Seric return TRUE; 98760089Seric } 98860207Seric else 98960207Seric map->map_mflags &= ~MF_IMPL_HASH; 99060089Seric #endif 99160089Seric #ifdef NDBM 99260207Seric map->map_mflags |= MF_IMPL_NDBM; 99360089Seric if (ndbm_map_open(map, mode)) 99460089Seric { 99560089Seric return TRUE; 99660089Seric } 99760207Seric else 99860207Seric map->map_mflags &= ~MF_IMPL_NDBM; 99960089Seric #endif 100056822Seric 100160207Seric #if !defined(NEWDB) && !defined(NDBM) 100260089Seric if (Verbose) 100360089Seric message("WARNING: cannot open alias database %s", map->map_file); 100460207Seric #endif 100560089Seric 100660207Seric return stab_map_open(map, mode); 100756822Seric } 100860089Seric 100960207Seric 101060089Seric /* 101160207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 101260089Seric */ 101360089Seric 101460089Seric void 101560207Seric impl_map_close(map) 101660089Seric MAP *map; 101760089Seric { 101860089Seric #ifdef NEWDB 101960207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 102060089Seric { 102160207Seric db_map_close(map); 102260207Seric map->map_mflags &= ~MF_IMPL_HASH; 102360089Seric } 102460089Seric #endif 102560089Seric 102660089Seric #ifdef NDBM 102760207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 102860089Seric { 102960207Seric ndbm_map_close(map); 103060207Seric map->map_mflags &= ~MF_IMPL_NDBM; 103160089Seric } 103260089Seric #endif 103360089Seric } 103460207Seric /* 103560207Seric ** NULL stubs 103660089Seric */ 103760089Seric 103860207Seric bool 103960207Seric null_map_open(map, mode) 104060089Seric MAP *map; 104160207Seric int mode; 104260089Seric { 104360207Seric return TRUE; 104460089Seric } 104560089Seric 104660207Seric void 104760207Seric null_map_close(map) 104860207Seric MAP *map; 104960089Seric { 105060207Seric return; 105160207Seric } 105260089Seric 105360207Seric void 105460207Seric null_map_store(map, key, val) 105560207Seric MAP *map; 105660207Seric char *key; 105760207Seric char *val; 105860089Seric { 105960207Seric return; 106060089Seric } 1061