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*61707Seric static char sccsid[] = "@(#)map.c 6.28 (Berkeley) 06/05/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 18760537Seric 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'; 27760537Seric if (tTd(39, 1)) 27860492Seric printf("map_rewrite => %s\n", rwb->rwb_buf); 27960492Seric return rwb->rwb_buf; 28060089Seric } 28160089Seric /* 28260537Seric ** INITMAPS -- initialize for aliasing 28360537Seric ** 28460537Seric ** Parameters: 28560537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 28660537Seric ** e -- current envelope. 28760537Seric ** 28860537Seric ** Returns: 28960537Seric ** none. 29060537Seric ** 29160537Seric ** Side Effects: 29260537Seric ** initializes aliases: 29360537Seric ** if NDBM: opens the database. 29460537Seric ** if ~NDBM: reads the aliases into the symbol table. 29560537Seric */ 29660537Seric 29760537Seric initmaps(rebuild, e) 29860537Seric bool rebuild; 29960537Seric register ENVELOPE *e; 30060537Seric { 30160537Seric extern void map_init(); 30260537Seric 30360537Seric CurEnv = e; 30460537Seric stabapply(map_init, rebuild); 30560537Seric } 30660537Seric 30760537Seric void 30860537Seric map_init(s, rebuild) 30960537Seric register STAB *s; 31060537Seric int rebuild; 31160537Seric { 31260537Seric register MAP *map; 31360537Seric 31460537Seric /* has to be a map */ 31560537Seric if (s->s_type != ST_MAP) 31660537Seric return; 31760537Seric 31860537Seric map = &s->s_map; 31960537Seric if (!bitset(MF_VALID, map->map_mflags)) 32060537Seric return; 32160537Seric 32260537Seric if (tTd(38, 2)) 32360537Seric printf("map_init(%s:%s)\n", 32460537Seric map->map_class->map_cname, map->map_file); 32560537Seric 32660537Seric /* if already open, close it (for nested open) */ 32760537Seric if (bitset(MF_OPEN, map->map_mflags)) 32860537Seric { 32960537Seric map->map_class->map_close(map); 33060537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 33160537Seric } 33260537Seric 33360537Seric if (rebuild) 33460537Seric { 33560926Seric if (bitset(MF_ALIAS, map->map_mflags) && 33660926Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 33760537Seric rebuildaliases(map, FALSE); 33860537Seric } 33960537Seric else 34060537Seric { 34160537Seric if (map->map_class->map_open(map, O_RDONLY)) 34260537Seric { 34360537Seric if (tTd(38, 4)) 34460537Seric printf("%s:%s: valid\n", 34560537Seric map->map_class->map_cname, 34660537Seric map->map_file); 34760537Seric map->map_mflags |= MF_OPEN; 34860537Seric } 34960537Seric else if (tTd(38, 4)) 35060537Seric printf("%s:%s: invalid: %s\n", 35160537Seric map->map_class->map_cname, 35260537Seric map->map_file, 35360537Seric errstring(errno)); 35460537Seric } 35560537Seric } 35660537Seric /* 35760089Seric ** NDBM modules 35860089Seric */ 35960089Seric 36060089Seric #ifdef NDBM 36160089Seric 36260089Seric /* 36360089Seric ** DBM_MAP_OPEN -- DBM-style map open 36460089Seric */ 36560089Seric 36660089Seric bool 36760089Seric ndbm_map_open(map, mode) 36860089Seric MAP *map; 36960089Seric int mode; 37060089Seric { 37160089Seric DBM *dbm; 37260089Seric 37360537Seric if (tTd(38, 2)) 37460089Seric printf("ndbm_map_open(%s, %d)\n", map->map_file, mode); 37560089Seric 37660207Seric if (mode == O_RDWR) 37760207Seric mode |= O_CREAT|O_TRUNC; 37860207Seric 37960089Seric /* open the database */ 38060089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 38156822Seric if (dbm == NULL) 38256822Seric { 38360207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 38456836Seric syserr("Cannot open DBM database %s", map->map_file); 38556822Seric return FALSE; 38656822Seric } 38760089Seric map->map_db1 = (void *) dbm; 38860207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 38960604Seric aliaswait(map, ".pag"); 39056822Seric return TRUE; 39156822Seric } 39260089Seric 39360089Seric 39460089Seric /* 39556822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 39656822Seric */ 39756822Seric 39856822Seric char * 39960089Seric ndbm_map_lookup(map, name, av, statp) 40056822Seric MAP *map; 40160089Seric char *name; 40256822Seric char **av; 40359084Seric int *statp; 40456822Seric { 40556822Seric datum key, val; 40660089Seric char keybuf[MAXNAME + 1]; 40756822Seric 40860537Seric if (tTd(38, 20)) 40960089Seric printf("ndbm_map_lookup(%s)\n", name); 41060089Seric 41160089Seric key.dptr = name; 41260089Seric key.dsize = strlen(name); 41360207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 41457014Seric { 41560089Seric if (key.dsize > sizeof keybuf - 1) 41660089Seric key.dsize = sizeof keybuf - 1; 41760089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 41860089Seric makelower(keybuf); 41960089Seric key.dptr = keybuf; 42057014Seric } 42160207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 42256822Seric key.dsize++; 42360089Seric (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH); 42460089Seric val = dbm_fetch((DBM *) map->map_db1, key); 42560089Seric (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN); 42656822Seric if (val.dptr == NULL) 42756822Seric return NULL; 42860207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 42960089Seric av = NULL; 43060089Seric return map_rewrite(map, val.dptr, val.dsize, av); 43156822Seric } 43256822Seric 43356822Seric 43456822Seric /* 43560089Seric ** DBM_MAP_STORE -- store a datum in the database 43656822Seric */ 43756822Seric 43860089Seric void 43960089Seric ndbm_map_store(map, lhs, rhs) 44060089Seric register MAP *map; 44160089Seric char *lhs; 44260089Seric char *rhs; 44360089Seric { 44460089Seric datum key; 44560089Seric datum data; 44660089Seric int stat; 44760089Seric 44860537Seric if (tTd(38, 12)) 44960089Seric printf("ndbm_map_store(%s, %s)\n", lhs, rhs); 45060089Seric 45160089Seric key.dsize = strlen(lhs); 45260089Seric key.dptr = lhs; 45360089Seric 45460089Seric data.dsize = strlen(rhs); 45560089Seric data.dptr = rhs; 45660089Seric 45760207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 45860089Seric { 45960089Seric key.dsize++; 46060089Seric data.dsize++; 46160089Seric } 46260089Seric 46360089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 46460089Seric if (stat > 0) 46560089Seric { 46660089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 46760089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 46860089Seric } 46960089Seric if (stat != 0) 47060089Seric syserr("readaliases: dbm put (%s)", lhs); 47160089Seric } 47260089Seric 47360089Seric 47460089Seric /* 47560207Seric ** NDBM_MAP_CLOSE -- close the database 47660089Seric */ 47760089Seric 47860089Seric void 47960089Seric ndbm_map_close(map) 48060089Seric register MAP *map; 48160089Seric { 48260207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 48360089Seric { 48460089Seric #ifdef YPCOMPAT 48560089Seric char buf[200]; 48660089Seric 48760089Seric (void) sprintf(buf, "%010ld", curtime()); 48860089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 48960089Seric 49060089Seric (void) myhostname(buf, sizeof buf); 49160089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 49260089Seric #endif 49360089Seric 49460089Seric /* write out the distinguished alias */ 49560089Seric ndbm_map_store(map, "@", "@"); 49660089Seric } 49760089Seric dbm_close((DBM *) map->map_db1); 49860089Seric } 49960089Seric 50060089Seric #endif 50160089Seric /* 50260582Seric ** NEWDB (Hash and BTree) Modules 50360089Seric */ 50460089Seric 50560089Seric #ifdef NEWDB 50660089Seric 50760089Seric /* 50860582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 50960582Seric ** 51060582Seric ** These do rather bizarre locking. If you can lock on open, 51160582Seric ** do that to avoid the condition of opening a database that 51260582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 51360582Seric ** there will be a race condition. If opening for read-only, 51460582Seric ** we immediately release the lock to avoid freezing things up. 51560582Seric ** We really ought to hold the lock, but guarantee that we won't 51660582Seric ** be pokey about it. That's hard to do. 51760089Seric */ 51860089Seric 51956822Seric bool 52060089Seric bt_map_open(map, mode) 52156822Seric MAP *map; 52260089Seric int mode; 52356822Seric { 52456822Seric DB *db; 52560228Seric int i; 52660582Seric int omode; 52760089Seric char buf[MAXNAME]; 52856822Seric 52960537Seric if (tTd(38, 2)) 53060089Seric printf("bt_map_open(%s, %d)\n", map->map_file, mode); 53160089Seric 53260582Seric omode = mode; 53360582Seric if (omode == O_RDWR) 53460582Seric { 53560582Seric omode |= O_CREAT|O_TRUNC; 53660582Seric #if defined(O_EXLOCK) && !defined(LOCKF) 53760582Seric omode |= O_EXLOCK; 53860582Seric # if !defined(OLD_NEWDB) 53960582Seric } 54060582Seric else 54160582Seric { 54260582Seric omode |= O_SHLOCK; 54360582Seric # endif 54460582Seric #endif 54560582Seric } 54660207Seric 54760228Seric (void) strcpy(buf, map->map_file); 54860228Seric i = strlen(buf); 54960228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 55060228Seric (void) strcat(buf, ".db"); 55160582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 55256822Seric if (db == NULL) 55356822Seric { 55460207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 55556836Seric syserr("Cannot open BTREE database %s", map->map_file); 55656822Seric return FALSE; 55756822Seric } 55860582Seric #if !defined(OLD_NEWDB) && !defined(LOCKF) 55960582Seric # if !defined(O_EXLOCK) 56060582Seric if (mode == O_RDWR) 56160582Seric (void) lockfile(db->fd(db), map->map_file, LOCK_EX); 56260582Seric # else 56360582Seric if (mode == O_RDONLY) 56460582Seric (void) lockfile(db->fd(db), map->map_file, LOCK_UN); 56560582Seric # endif 56660582Seric #endif 56760585Seric 56860585Seric /* try to make sure that at least the database header is on disk */ 56960585Seric if (mode == O_RDWR) 57060585Seric (void) db->sync(db, 0); 57160585Seric 57260089Seric map->map_db2 = (void *) db; 57360207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 57460207Seric aliaswait(map, ".db"); 57556822Seric return TRUE; 57656822Seric } 57756822Seric 57856822Seric 57956822Seric /* 58056822Seric ** HASH_MAP_INIT -- HASH-style map initialization 58156822Seric */ 58256822Seric 58356822Seric bool 58460089Seric hash_map_open(map, mode) 58556822Seric MAP *map; 58660089Seric int mode; 58756822Seric { 58856822Seric DB *db; 58960228Seric int i; 59060582Seric int omode; 59160089Seric char buf[MAXNAME]; 59256822Seric 59360537Seric if (tTd(38, 2)) 59460089Seric printf("hash_map_open(%s, %d)\n", map->map_file, mode); 59560089Seric 59660582Seric omode = mode; 59760582Seric if (omode == O_RDWR) 59860582Seric { 59960582Seric omode |= O_CREAT|O_TRUNC; 60060582Seric #if defined(O_EXLOCK) && !defined(LOCKF) 60160582Seric omode |= O_EXLOCK; 60260582Seric # if !defined(OLD_NEWDB) 60360582Seric } 60460582Seric else 60560582Seric { 60660582Seric omode |= O_SHLOCK; 60760582Seric # endif 60860582Seric #endif 60960582Seric } 61060207Seric 61160228Seric (void) strcpy(buf, map->map_file); 61260228Seric i = strlen(buf); 61360228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 61460228Seric (void) strcat(buf, ".db"); 61560582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 61656822Seric if (db == NULL) 61756822Seric { 61860207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 61956836Seric syserr("Cannot open HASH database %s", map->map_file); 62056822Seric return FALSE; 62156822Seric } 62260582Seric #if !defined(OLD_NEWDB) && !defined(LOCKF) 62360582Seric # if !defined(O_EXLOCK) 62460582Seric if (mode == O_RDWR) 62560582Seric (void) lockfile(db->fd(db), map->map_file, LOCK_EX); 62660582Seric # else 62760582Seric if (mode == O_RDONLY) 62860582Seric (void) lockfile(db->fd(db), map->map_file, LOCK_UN); 62960582Seric # endif 63060582Seric #endif 63160585Seric 63260585Seric /* try to make sure that at least the database header is on disk */ 63360585Seric if (mode == O_RDWR) 63460585Seric (void) db->sync(db, 0); 63560585Seric 63660089Seric map->map_db2 = (void *) db; 63760207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 63860207Seric aliaswait(map, ".db"); 63956822Seric return TRUE; 64056822Seric } 64156822Seric 64256822Seric 64356822Seric /* 64456822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 64556822Seric */ 64656822Seric 64756822Seric char * 64860089Seric db_map_lookup(map, name, av, statp) 64956822Seric MAP *map; 65060089Seric char *name; 65156822Seric char **av; 65259084Seric int *statp; 65356822Seric { 65456822Seric DBT key, val; 65560422Seric register DB *db = (DB *) map->map_db2; 65660422Seric int st; 65760422Seric int saveerrno; 65860089Seric char keybuf[MAXNAME + 1]; 65956822Seric 66060537Seric if (tTd(38, 20)) 66160089Seric printf("db_map_lookup(%s)\n", name); 66260089Seric 66360089Seric key.size = strlen(name); 66460089Seric if (key.size > sizeof keybuf - 1) 66560089Seric key.size = sizeof keybuf - 1; 66660089Seric key.data = keybuf; 66760089Seric bcopy(name, keybuf, key.size + 1); 66860207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 66960089Seric makelower(keybuf); 67060207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 67156822Seric key.size++; 67260422Seric #ifndef OLD_NEWDB 67360422Seric (void) lockfile(db->fd(db), map->map_file, LOCK_SH); 67460422Seric #endif 67560422Seric st = db->get(db, &key, &val, 0); 67660422Seric saveerrno = errno; 67760422Seric #ifndef OLD_NEWDB 67860422Seric (void) lockfile(db->fd(db), map->map_file, LOCK_UN); 67960422Seric #endif 68060422Seric if (st != 0) 68160422Seric { 68260422Seric errno = saveerrno; 68360422Seric if (st < 0) 68460422Seric syserr("db_map_lookup: get (%s)", name); 68556822Seric return NULL; 68660422Seric } 68760207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 68860089Seric av = NULL; 68960089Seric return map_rewrite(map, val.data, val.size, av); 69056822Seric } 69156822Seric 69260089Seric 69360089Seric /* 69460089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 69556822Seric */ 69656822Seric 69760089Seric void 69860089Seric db_map_store(map, lhs, rhs) 69960089Seric register MAP *map; 70060089Seric char *lhs; 70160089Seric char *rhs; 70256822Seric { 70360089Seric int stat; 70460089Seric DBT key; 70560089Seric DBT data; 70660089Seric register DB *db = map->map_db2; 70756822Seric 70860537Seric if (tTd(38, 20)) 70960089Seric printf("db_map_store(%s, %s)\n", lhs, rhs); 71060089Seric 71160089Seric key.size = strlen(lhs); 71260089Seric key.data = lhs; 71360089Seric 71460089Seric data.size = strlen(rhs); 71560089Seric data.data = rhs; 71660089Seric 71760207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 71856822Seric { 71960089Seric key.size++; 72060089Seric data.size++; 72160089Seric } 72256836Seric 72360089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 72460089Seric if (stat > 0) 72560089Seric { 72660089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 72760089Seric stat = db->put(db, &key, &data, 0); 72860089Seric } 72960089Seric if (stat != 0) 73060089Seric syserr("readaliases: db put (%s)", lhs); 73160089Seric } 73256836Seric 73356847Seric 73460089Seric /* 73560089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 73660089Seric */ 73760089Seric 73860089Seric void 73960089Seric db_map_close(map) 74060089Seric MAP *map; 74160089Seric { 74260089Seric register DB *db = map->map_db2; 74360089Seric 74460537Seric if (tTd(38, 9)) 74560207Seric printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags); 74660089Seric 74760207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 74858804Seric { 74960089Seric /* write out the distinguished alias */ 75060089Seric db_map_store(map, "@", "@"); 75158804Seric } 75258963Seric 75360089Seric if (db->close(db) != 0) 75460089Seric syserr("readaliases: db close failure"); 75556822Seric } 75657208Seric 75760089Seric #endif 75860089Seric /* 75960089Seric ** NIS Modules 76060089Seric */ 76160089Seric 76260089Seric # ifdef NIS 76360089Seric 76457208Seric /* 76560089Seric ** NIS_MAP_OPEN -- open DBM map 76657208Seric */ 76757208Seric 76857208Seric bool 76960089Seric nis_map_open(map, mode) 77057208Seric MAP *map; 77160089Seric int mode; 77257208Seric { 77357216Seric int yperr; 77460215Seric register char *p; 77560215Seric auto char *vp; 77660215Seric auto int vsize; 77757216Seric char *master; 77857216Seric 77960537Seric if (tTd(38, 2)) 78060089Seric printf("nis_map_open(%s)\n", map->map_file); 78160089Seric 78260207Seric if (mode != O_RDONLY) 78360207Seric { 78460207Seric errno = ENODEV; 78560207Seric return FALSE; 78660207Seric } 78760207Seric 78860089Seric p = strchr(map->map_file, '@'); 78960089Seric if (p != NULL) 79060089Seric { 79160089Seric *p++ = '\0'; 79260089Seric if (*p != '\0') 79360089Seric map->map_domain = p; 79460089Seric } 79560215Seric 79660089Seric if (map->map_domain == NULL) 79760089Seric yp_get_default_domain(&map->map_domain); 79860089Seric 79960089Seric if (*map->map_file == '\0') 80060089Seric map->map_file = "mail.aliases"; 80160089Seric 80260215Seric /* check to see if this map actually exists */ 80360089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 80460089Seric &vp, &vsize); 80560537Seric if (tTd(38, 10)) 80660089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 80760089Seric map->map_domain, map->map_file, yperr_string(yperr)); 80860089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 80960089Seric return TRUE; 81060215Seric 81160215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 81260215Seric syserr("Cannot bind to domain %s: %s", map->map_domain, 81360215Seric yperr_string(yperr)); 81460215Seric 81560089Seric return FALSE; 81660089Seric } 81760089Seric 81860089Seric 81960089Seric /* 82057208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 82157208Seric */ 82257208Seric 82357208Seric char * 82460089Seric nis_map_lookup(map, name, av, statp) 82557208Seric MAP *map; 82660089Seric char *name; 82757208Seric char **av; 82859084Seric int *statp; 82957208Seric { 83057208Seric char *vp; 83157642Seric auto int vsize; 83259274Seric int buflen; 83360215Seric int yperr; 83460089Seric char keybuf[MAXNAME + 1]; 83557208Seric 83660537Seric if (tTd(38, 20)) 83760089Seric printf("nis_map_lookup(%s)\n", name); 83860089Seric 83960089Seric buflen = strlen(name); 84060089Seric if (buflen > sizeof keybuf - 1) 84160089Seric buflen = sizeof keybuf - 1; 84260089Seric bcopy(name, keybuf, buflen + 1); 84360207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 84460089Seric makelower(keybuf); 84560207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 84659274Seric buflen++; 84760089Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 84860089Seric &vp, &vsize); 84960089Seric if (yperr != 0) 85060089Seric { 85160089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 85260215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 85357208Seric return NULL; 85460089Seric } 85560207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 85660089Seric av = NULL; 85760215Seric return map_rewrite(map, vp, vsize, av); 85857208Seric } 85957208Seric 86060089Seric 86160089Seric /* 86260207Seric ** NIS_MAP_STORE 86360089Seric */ 86460089Seric 86560089Seric void 86660089Seric nis_map_store(map, lhs, rhs) 86760089Seric MAP *map; 86860089Seric char *lhs; 86960089Seric char *rhs; 87060089Seric { 87160089Seric /* nothing */ 87260089Seric } 87360089Seric 87460089Seric 87560089Seric /* 87660207Seric ** NIS_MAP_CLOSE 87760089Seric */ 87860089Seric 87960089Seric void 88060089Seric nis_map_close(map) 88160089Seric MAP *map; 88260089Seric { 88360089Seric /* nothing */ 88460089Seric } 88560089Seric 88660089Seric #endif /* NIS */ 88757208Seric /* 88860089Seric ** STAB (Symbol Table) Modules 88960089Seric */ 89060089Seric 89160089Seric 89260089Seric /* 89360207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 89460089Seric */ 89560089Seric 89660089Seric char * 897*61707Seric stab_map_lookup(map, name, av, pstat) 89860089Seric register MAP *map; 89960089Seric char *name; 900*61707Seric char **av; 901*61707Seric int *pstat; 90260089Seric { 90360089Seric register STAB *s; 90460089Seric 90560537Seric if (tTd(38, 20)) 90660089Seric printf("stab_lookup(%s)\n", name); 90760089Seric 90860089Seric s = stab(name, ST_ALIAS, ST_FIND); 90960089Seric if (s != NULL) 91060089Seric return (s->s_alias); 91160089Seric return (NULL); 91260089Seric } 91360089Seric 91460089Seric 91560089Seric /* 91660207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 91760089Seric */ 91860089Seric 91960089Seric void 92060089Seric stab_map_store(map, lhs, rhs) 92160089Seric register MAP *map; 92260089Seric char *lhs; 92360089Seric char *rhs; 92460089Seric { 92560089Seric register STAB *s; 92660089Seric 92760089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 92860089Seric s->s_alias = newstr(rhs); 92960089Seric } 93060089Seric 93160089Seric 93260089Seric /* 93360207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 93460207Seric ** 93560207Seric ** This is a wierd case -- it is only intended as a fallback for 93660207Seric ** aliases. For this reason, opens for write (only during a 93760207Seric ** "newaliases") always fails, and opens for read open the 93860207Seric ** actual underlying text file instead of the database. 93960089Seric */ 94060089Seric 94160089Seric bool 94260089Seric stab_map_open(map, mode) 94360089Seric register MAP *map; 94460089Seric int mode; 94560089Seric { 94660537Seric if (tTd(38, 2)) 94760089Seric printf("stab_map_open(%s)\n", map->map_file); 94860089Seric 94960089Seric if (mode != O_RDONLY) 95060207Seric { 95160207Seric errno = ENODEV; 95260089Seric return FALSE; 95360207Seric } 95460089Seric 95560089Seric return TRUE; 95660089Seric } 95760089Seric 95860089Seric 95960089Seric /* 96060207Seric ** STAB_MAP_CLOSE -- close symbol table (???) 96160089Seric */ 96260089Seric 96360089Seric void 96460089Seric stab_map_close(map) 96560089Seric MAP *map; 96660089Seric { 96760089Seric /* ignore it */ 96860089Seric } 96960089Seric /* 97060089Seric ** Implicit Modules 97156822Seric ** 97260089Seric ** Tries several types. For back compatibility of aliases. 97356822Seric */ 97456822Seric 97560089Seric 97660089Seric /* 97760207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 97860089Seric */ 97960089Seric 98060089Seric char * 98160089Seric impl_map_lookup(map, name, av, pstat) 98260089Seric MAP *map; 98360089Seric char *name; 98456822Seric char **av; 98560089Seric int *pstat; 98656822Seric { 98760537Seric if (tTd(38, 20)) 98860089Seric printf("impl_map_lookup(%s)\n", name); 98956822Seric 99060089Seric #ifdef NEWDB 99160207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 99260089Seric return db_map_lookup(map, name, av, pstat); 99360089Seric #endif 99460089Seric #ifdef NDBM 99560207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 99660089Seric return ndbm_map_lookup(map, name, av, pstat); 99760089Seric #endif 99860089Seric return stab_map_lookup(map, name, av, pstat); 99960089Seric } 100060089Seric 100160089Seric /* 100260207Seric ** IMPL_MAP_STORE -- store in open databases 100360089Seric */ 100460089Seric 100560089Seric void 100660089Seric impl_map_store(map, lhs, rhs) 100760089Seric MAP *map; 100860089Seric char *lhs; 100960089Seric char *rhs; 101060089Seric { 101160089Seric #ifdef NEWDB 101260207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 101360089Seric db_map_store(map, lhs, rhs); 101460089Seric #endif 101560089Seric #ifdef NDBM 101660207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 101760089Seric ndbm_map_store(map, lhs, rhs); 101860089Seric #endif 101960089Seric stab_map_store(map, lhs, rhs); 102060089Seric } 102160089Seric 102260089Seric /* 102360089Seric ** IMPL_MAP_OPEN -- implicit database open 102460089Seric */ 102560089Seric 102660089Seric bool 102760089Seric impl_map_open(map, mode) 102860089Seric MAP *map; 102960089Seric int mode; 103060089Seric { 103160089Seric struct stat stb; 103260089Seric 103360537Seric if (tTd(38, 2)) 103460089Seric printf("impl_map_open(%s)\n", map->map_file); 103560089Seric 103660089Seric if (stat(map->map_file, &stb) < 0) 103756822Seric { 103860089Seric /* no alias file at all */ 103960089Seric return FALSE; 104056822Seric } 104156822Seric 104260089Seric #ifdef NEWDB 104360207Seric map->map_mflags |= MF_IMPL_HASH; 104460089Seric if (hash_map_open(map, mode)) 104556822Seric { 104660207Seric #if defined(NDBM) && defined(YPCOMPAT) 104760561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 104860207Seric #endif 104960207Seric return TRUE; 105060089Seric } 105160207Seric else 105260207Seric map->map_mflags &= ~MF_IMPL_HASH; 105360089Seric #endif 105460089Seric #ifdef NDBM 105560207Seric map->map_mflags |= MF_IMPL_NDBM; 105660089Seric if (ndbm_map_open(map, mode)) 105760089Seric { 105860089Seric return TRUE; 105960089Seric } 106060207Seric else 106160207Seric map->map_mflags &= ~MF_IMPL_NDBM; 106260089Seric #endif 106356822Seric 106460207Seric #if !defined(NEWDB) && !defined(NDBM) 106560089Seric if (Verbose) 106660089Seric message("WARNING: cannot open alias database %s", map->map_file); 106760207Seric #endif 106860089Seric 106960207Seric return stab_map_open(map, mode); 107056822Seric } 107160089Seric 107260207Seric 107360089Seric /* 107460207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 107560089Seric */ 107660089Seric 107760089Seric void 107860207Seric impl_map_close(map) 107960089Seric MAP *map; 108060089Seric { 108160089Seric #ifdef NEWDB 108260207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 108360089Seric { 108460207Seric db_map_close(map); 108560207Seric map->map_mflags &= ~MF_IMPL_HASH; 108660089Seric } 108760089Seric #endif 108860089Seric 108960089Seric #ifdef NDBM 109060207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 109160089Seric { 109260207Seric ndbm_map_close(map); 109360207Seric map->map_mflags &= ~MF_IMPL_NDBM; 109460089Seric } 109560089Seric #endif 109660089Seric } 109760207Seric /* 109860207Seric ** NULL stubs 109960089Seric */ 110060089Seric 110160207Seric bool 110260207Seric null_map_open(map, mode) 110360089Seric MAP *map; 110460207Seric int mode; 110560089Seric { 110660207Seric return TRUE; 110760089Seric } 110860089Seric 110960207Seric void 111060207Seric null_map_close(map) 111160207Seric MAP *map; 111260089Seric { 111360207Seric return; 111460207Seric } 111560089Seric 111660207Seric void 111760207Seric null_map_store(map, key, val) 111860207Seric MAP *map; 111960207Seric char *key; 112060207Seric char *val; 112160089Seric { 112260207Seric return; 112360089Seric } 1124