156822Seric /* 256822Seric * Copyright (c) 1992 Eric P. Allman. 362526Sbostic * Copyright (c) 1992, 1993 462526Sbostic * The Regents of the University of California. All rights reserved. 556822Seric * 656822Seric * %sccs.include.redist.c% 756822Seric */ 856822Seric 956822Seric #ifndef lint 10*63753Seric static char sccsid[] = "@(#)map.c 8.2 (Berkeley) 07/11/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 86*63753Seric map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; 8760089Seric for (;;) 8860089Seric { 8960089Seric while (isascii(*p) && isspace(*p)) 9060089Seric p++; 9160089Seric if (*p != '-') 9260089Seric break; 9360089Seric switch (*++p) 9460089Seric { 9560089Seric case 'N': 9660207Seric map->map_mflags |= MF_INCLNULL; 97*63753Seric map->map_mflags &= ~MF_TRY0NULL; 9860089Seric break; 9960089Seric 100*63753Seric case 'O': 101*63753Seric map->map_mflags &= ~MF_TRY1NULL; 102*63753Seric break; 103*63753Seric 10460089Seric case 'o': 10560207Seric map->map_mflags |= MF_OPTIONAL; 10660089Seric break; 10760089Seric 10860089Seric case 'f': 10960207Seric map->map_mflags |= MF_NOFOLDCASE; 11060089Seric break; 11160089Seric 11260089Seric case 'm': 11360207Seric map->map_mflags |= MF_MATCHONLY; 11460089Seric break; 11560089Seric 11660089Seric case 'a': 11760089Seric map->map_app = ++p; 11860089Seric break; 11960089Seric } 12060089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 12160089Seric p++; 12260089Seric if (*p != '\0') 12360089Seric *p++ = '\0'; 12460089Seric } 12560089Seric if (map->map_app != NULL) 12660089Seric map->map_app = newstr(map->map_app); 12760089Seric 12860089Seric if (*p != '\0') 12960089Seric { 13060089Seric map->map_file = p; 13160089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 13260089Seric p++; 13360089Seric if (*p != '\0') 13460089Seric *p++ = '\0'; 13560089Seric map->map_file = newstr(map->map_file); 13660089Seric } 13760089Seric 13860089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 13960089Seric p++; 14060089Seric if (*p != '\0') 14160089Seric map->map_rebuild = newstr(p); 14260089Seric 14356822Seric if (map->map_file == NULL) 14457208Seric { 14560089Seric syserr("No file name for %s map %s", 14660089Seric map->map_class->map_cname, map->map_mname); 14756822Seric return FALSE; 14857208Seric } 14960089Seric return TRUE; 15060089Seric } 15160089Seric /* 15260089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 15360089Seric ** 15460089Seric ** It also adds the map_app string. It can be used as a utility 15560089Seric ** in the map_lookup method. 15660089Seric ** 15760089Seric ** Parameters: 15860089Seric ** map -- the map that causes this. 15960089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 16060089Seric ** slen -- the length of s. 16160089Seric ** av -- arguments to interpolate into buf. 16260089Seric ** 16360089Seric ** Returns: 16460089Seric ** Pointer to rewritten result. 16560089Seric ** 16660089Seric ** Side Effects: 16760089Seric ** none. 16860089Seric */ 16960089Seric 17060492Seric struct rwbuf 17160492Seric { 17260492Seric int rwb_len; /* size of buffer */ 17360492Seric char *rwb_buf; /* ptr to buffer */ 17460492Seric }; 17560492Seric 17660492Seric struct rwbuf RwBufs[2]; /* buffers for rewriting output */ 17760492Seric 17860089Seric char * 17960089Seric map_rewrite(map, s, slen, av) 18060089Seric register MAP *map; 18160089Seric register char *s; 18260089Seric int slen; 18360089Seric char **av; 18460089Seric { 18560089Seric register char *bp; 18660089Seric register char c; 18760089Seric char **avp; 18860089Seric register char *ap; 18960492Seric register struct rwbuf *rwb; 19060089Seric int i; 19160089Seric int len; 19260089Seric 19360537Seric if (tTd(39, 1)) 19460089Seric { 19560256Seric printf("map_rewrite(%.*s), av =", slen, s); 19660256Seric if (av == NULL) 19760256Seric printf(" (nullv)"); 19860256Seric else 19960256Seric { 20060256Seric for (avp = av; *avp != NULL; avp++) 20160256Seric printf("\n\t%s", *avp); 20260256Seric } 20360256Seric printf("\n"); 20460089Seric } 20560089Seric 20660492Seric rwb = RwBufs; 20760492Seric if (av == NULL) 20860492Seric rwb++; 20960492Seric 21060089Seric /* count expected size of output (can safely overestimate) */ 21160089Seric i = len = slen; 21260089Seric if (av != NULL) 21360089Seric { 21460089Seric bp = s; 21560089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 21660089Seric { 21760089Seric if (c != '%') 21860089Seric continue; 21960089Seric if (--i < 0) 22060089Seric break; 22160089Seric c = *bp++; 22260089Seric if (!(isascii(c) && isdigit(c))) 22360089Seric continue; 22460089Seric c -= 0; 22560089Seric for (avp = av; --c >= 0 && *avp != NULL; avp++) 22660089Seric continue; 22760089Seric if (*avp == NULL) 22860089Seric continue; 22960089Seric len += strlen(*avp); 23060089Seric } 23160089Seric } 23260089Seric if (map->map_app != NULL) 23360089Seric len += strlen(map->map_app); 23460492Seric if (rwb->rwb_len < ++len) 23560089Seric { 23660089Seric /* need to malloc additional space */ 23760492Seric rwb->rwb_len = len; 23860492Seric if (rwb->rwb_buf != NULL) 23960492Seric free(rwb->rwb_buf); 24060492Seric rwb->rwb_buf = xalloc(rwb->rwb_len); 24160089Seric } 24260089Seric 24360492Seric bp = rwb->rwb_buf; 24460089Seric if (av == NULL) 24560089Seric { 24660089Seric bcopy(s, bp, slen); 24760089Seric bp += slen; 24860089Seric } 24960089Seric else 25060089Seric { 25160089Seric while (--slen >= 0 && (c = *s++) != '\0') 25260089Seric { 25360089Seric if (c != '%') 25460089Seric { 25560089Seric pushc: 25660089Seric *bp++ = c; 25760089Seric continue; 25860089Seric } 25960089Seric if (--slen < 0 || (c = *s++) == '\0') 26060089Seric c = '%'; 26160089Seric if (c == '%') 26260089Seric goto pushc; 26360089Seric if (!(isascii(c) && isdigit(c))) 26460089Seric { 26560089Seric *bp++ = '%'; 26660089Seric goto pushc; 26760089Seric } 26860089Seric c -= '0'; 26960089Seric for (avp = av; --c >= 0 && *avp != NULL; avp++) 27060089Seric continue; 27160089Seric if (*avp == NULL) 27260089Seric continue; 27360089Seric 27460089Seric /* transliterate argument into output string */ 27560089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 27660089Seric *bp++ = c; 27760089Seric } 27860089Seric } 27960089Seric if (map->map_app != NULL) 28060089Seric strcpy(bp, map->map_app); 28160089Seric else 28260089Seric *bp = '\0'; 28360537Seric if (tTd(39, 1)) 28460492Seric printf("map_rewrite => %s\n", rwb->rwb_buf); 28560492Seric return rwb->rwb_buf; 28660089Seric } 28760089Seric /* 28860537Seric ** INITMAPS -- initialize for aliasing 28960537Seric ** 29060537Seric ** Parameters: 29160537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 29260537Seric ** e -- current envelope. 29360537Seric ** 29460537Seric ** Returns: 29560537Seric ** none. 29660537Seric ** 29760537Seric ** Side Effects: 29860537Seric ** initializes aliases: 29960537Seric ** if NDBM: opens the database. 30060537Seric ** if ~NDBM: reads the aliases into the symbol table. 30160537Seric */ 30260537Seric 30360537Seric initmaps(rebuild, e) 30460537Seric bool rebuild; 30560537Seric register ENVELOPE *e; 30660537Seric { 30760537Seric extern void map_init(); 30860537Seric 30960537Seric CurEnv = e; 31060537Seric stabapply(map_init, rebuild); 31160537Seric } 31260537Seric 31360537Seric void 31460537Seric map_init(s, rebuild) 31560537Seric register STAB *s; 31660537Seric int rebuild; 31760537Seric { 31860537Seric register MAP *map; 31960537Seric 32060537Seric /* has to be a map */ 32160537Seric if (s->s_type != ST_MAP) 32260537Seric return; 32360537Seric 32460537Seric map = &s->s_map; 32560537Seric if (!bitset(MF_VALID, map->map_mflags)) 32660537Seric return; 32760537Seric 32860537Seric if (tTd(38, 2)) 32960537Seric printf("map_init(%s:%s)\n", 33060537Seric map->map_class->map_cname, map->map_file); 33160537Seric 33260537Seric /* if already open, close it (for nested open) */ 33360537Seric if (bitset(MF_OPEN, map->map_mflags)) 33460537Seric { 33560537Seric map->map_class->map_close(map); 33660537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 33760537Seric } 33860537Seric 33960537Seric if (rebuild) 34060537Seric { 34160926Seric if (bitset(MF_ALIAS, map->map_mflags) && 34260926Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 34360537Seric rebuildaliases(map, FALSE); 34460537Seric } 34560537Seric else 34660537Seric { 34760537Seric if (map->map_class->map_open(map, O_RDONLY)) 34860537Seric { 34960537Seric if (tTd(38, 4)) 35060537Seric printf("%s:%s: valid\n", 35160537Seric map->map_class->map_cname, 35260537Seric map->map_file); 35360537Seric map->map_mflags |= MF_OPEN; 35460537Seric } 35560537Seric else if (tTd(38, 4)) 35660537Seric printf("%s:%s: invalid: %s\n", 35760537Seric map->map_class->map_cname, 35860537Seric map->map_file, 35960537Seric errstring(errno)); 36060537Seric } 36160537Seric } 36260537Seric /* 36360089Seric ** NDBM modules 36460089Seric */ 36560089Seric 36660089Seric #ifdef NDBM 36760089Seric 36860089Seric /* 36960089Seric ** DBM_MAP_OPEN -- DBM-style map open 37060089Seric */ 37160089Seric 37260089Seric bool 37360089Seric ndbm_map_open(map, mode) 37460089Seric MAP *map; 37560089Seric int mode; 37660089Seric { 37760089Seric DBM *dbm; 37860089Seric 37960537Seric if (tTd(38, 2)) 38060089Seric printf("ndbm_map_open(%s, %d)\n", map->map_file, mode); 38160089Seric 38260207Seric if (mode == O_RDWR) 38360207Seric mode |= O_CREAT|O_TRUNC; 38460207Seric 38560089Seric /* open the database */ 38660089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 38756822Seric if (dbm == NULL) 38856822Seric { 38960207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 39056836Seric syserr("Cannot open DBM database %s", map->map_file); 39156822Seric return FALSE; 39256822Seric } 39360089Seric map->map_db1 = (void *) dbm; 39460207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 39560604Seric aliaswait(map, ".pag"); 39656822Seric return TRUE; 39756822Seric } 39860089Seric 39960089Seric 40060089Seric /* 40156822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 40256822Seric */ 40356822Seric 40456822Seric char * 40560089Seric ndbm_map_lookup(map, name, av, statp) 40656822Seric MAP *map; 40760089Seric char *name; 40856822Seric char **av; 40959084Seric int *statp; 41056822Seric { 41156822Seric datum key, val; 41260089Seric char keybuf[MAXNAME + 1]; 41356822Seric 41460537Seric if (tTd(38, 20)) 41560089Seric printf("ndbm_map_lookup(%s)\n", name); 41660089Seric 41760089Seric key.dptr = name; 41860089Seric key.dsize = strlen(name); 41960207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 42057014Seric { 42160089Seric if (key.dsize > sizeof keybuf - 1) 42260089Seric key.dsize = sizeof keybuf - 1; 42360089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 42460089Seric makelower(keybuf); 42560089Seric key.dptr = keybuf; 42657014Seric } 427*63753Seric (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH); 428*63753Seric val.dptr = NULL; 429*63753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 430*63753Seric { 431*63753Seric val = dbm_fetch((DBM *) map->map_db1, key); 432*63753Seric if (val.dptr != NULL) 433*63753Seric map->map_mflags &= ~MF_TRY1NULL; 434*63753Seric } 435*63753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 436*63753Seric { 43756822Seric key.dsize++; 438*63753Seric val = dbm_fetch((DBM *) map->map_db1, key); 439*63753Seric if (val.dptr != NULL) 440*63753Seric map->map_mflags &= ~MF_TRY0NULL; 441*63753Seric } 44260089Seric (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN); 44356822Seric if (val.dptr == NULL) 44456822Seric return NULL; 44560207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 446*63753Seric return map_rewrite(map, name, strlen(name), NULL); 447*63753Seric else 448*63753Seric return map_rewrite(map, val.dptr, val.dsize, av); 44956822Seric } 45056822Seric 45156822Seric 45256822Seric /* 45360089Seric ** DBM_MAP_STORE -- store a datum in the database 45456822Seric */ 45556822Seric 45660089Seric void 45760089Seric ndbm_map_store(map, lhs, rhs) 45860089Seric register MAP *map; 45960089Seric char *lhs; 46060089Seric char *rhs; 46160089Seric { 46260089Seric datum key; 46360089Seric datum data; 46460089Seric int stat; 46560089Seric 46660537Seric if (tTd(38, 12)) 46760089Seric printf("ndbm_map_store(%s, %s)\n", lhs, rhs); 46860089Seric 46960089Seric key.dsize = strlen(lhs); 47060089Seric key.dptr = lhs; 47160089Seric 47260089Seric data.dsize = strlen(rhs); 47360089Seric data.dptr = rhs; 47460089Seric 47560207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 47660089Seric { 47760089Seric key.dsize++; 47860089Seric data.dsize++; 47960089Seric } 48060089Seric 48160089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 48260089Seric if (stat > 0) 48360089Seric { 48460089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 48560089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 48660089Seric } 48760089Seric if (stat != 0) 48860089Seric syserr("readaliases: dbm put (%s)", lhs); 48960089Seric } 49060089Seric 49160089Seric 49260089Seric /* 49360207Seric ** NDBM_MAP_CLOSE -- close the database 49460089Seric */ 49560089Seric 49660089Seric void 49760089Seric ndbm_map_close(map) 49860089Seric register MAP *map; 49960089Seric { 50060207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 50160089Seric { 50260089Seric #ifdef YPCOMPAT 50360089Seric char buf[200]; 50460089Seric 50560089Seric (void) sprintf(buf, "%010ld", curtime()); 50660089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 50760089Seric 50860089Seric (void) myhostname(buf, sizeof buf); 50960089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 51060089Seric #endif 51160089Seric 51260089Seric /* write out the distinguished alias */ 51360089Seric ndbm_map_store(map, "@", "@"); 51460089Seric } 51560089Seric dbm_close((DBM *) map->map_db1); 51660089Seric } 51760089Seric 51860089Seric #endif 51960089Seric /* 52060582Seric ** NEWDB (Hash and BTree) Modules 52160089Seric */ 52260089Seric 52360089Seric #ifdef NEWDB 52460089Seric 52560089Seric /* 52660582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 52760582Seric ** 52860582Seric ** These do rather bizarre locking. If you can lock on open, 52960582Seric ** do that to avoid the condition of opening a database that 53060582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 53160582Seric ** there will be a race condition. If opening for read-only, 53260582Seric ** we immediately release the lock to avoid freezing things up. 53360582Seric ** We really ought to hold the lock, but guarantee that we won't 53460582Seric ** be pokey about it. That's hard to do. 53560089Seric */ 53660089Seric 53756822Seric bool 53860089Seric bt_map_open(map, mode) 53956822Seric MAP *map; 54060089Seric int mode; 54156822Seric { 54256822Seric DB *db; 54360228Seric int i; 54460582Seric int omode; 54560089Seric char buf[MAXNAME]; 54656822Seric 54760537Seric if (tTd(38, 2)) 54860089Seric printf("bt_map_open(%s, %d)\n", map->map_file, mode); 54960089Seric 55060582Seric omode = mode; 55160582Seric if (omode == O_RDWR) 55260582Seric { 55360582Seric omode |= O_CREAT|O_TRUNC; 55460582Seric #if defined(O_EXLOCK) && !defined(LOCKF) 55560582Seric omode |= O_EXLOCK; 55660582Seric # if !defined(OLD_NEWDB) 55760582Seric } 55860582Seric else 55960582Seric { 56060582Seric omode |= O_SHLOCK; 56160582Seric # endif 56260582Seric #endif 56360582Seric } 56460207Seric 56560228Seric (void) strcpy(buf, map->map_file); 56660228Seric i = strlen(buf); 56760228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 56860228Seric (void) strcat(buf, ".db"); 56960582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 57056822Seric if (db == NULL) 57156822Seric { 57260207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 57356836Seric syserr("Cannot open BTREE database %s", map->map_file); 57456822Seric return FALSE; 57556822Seric } 57660582Seric #if !defined(OLD_NEWDB) && !defined(LOCKF) 57760582Seric # if !defined(O_EXLOCK) 57860582Seric if (mode == O_RDWR) 57960582Seric (void) lockfile(db->fd(db), map->map_file, LOCK_EX); 58060582Seric # else 58160582Seric if (mode == O_RDONLY) 58260582Seric (void) lockfile(db->fd(db), map->map_file, LOCK_UN); 58360582Seric # endif 58460582Seric #endif 58560585Seric 58660585Seric /* try to make sure that at least the database header is on disk */ 58760585Seric if (mode == O_RDWR) 58860585Seric (void) db->sync(db, 0); 58960585Seric 59060089Seric map->map_db2 = (void *) db; 59160207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 59260207Seric aliaswait(map, ".db"); 59356822Seric return TRUE; 59456822Seric } 59556822Seric 59656822Seric 59756822Seric /* 59856822Seric ** HASH_MAP_INIT -- HASH-style map initialization 59956822Seric */ 60056822Seric 60156822Seric bool 60260089Seric hash_map_open(map, mode) 60356822Seric MAP *map; 60460089Seric int mode; 60556822Seric { 60656822Seric DB *db; 60760228Seric int i; 60860582Seric int omode; 60960089Seric char buf[MAXNAME]; 61056822Seric 61160537Seric if (tTd(38, 2)) 61260089Seric printf("hash_map_open(%s, %d)\n", map->map_file, mode); 61360089Seric 61460582Seric omode = mode; 61560582Seric if (omode == O_RDWR) 61660582Seric { 61760582Seric omode |= O_CREAT|O_TRUNC; 61860582Seric #if defined(O_EXLOCK) && !defined(LOCKF) 61960582Seric omode |= O_EXLOCK; 62060582Seric # if !defined(OLD_NEWDB) 62160582Seric } 62260582Seric else 62360582Seric { 62460582Seric omode |= O_SHLOCK; 62560582Seric # endif 62660582Seric #endif 62760582Seric } 62860207Seric 62960228Seric (void) strcpy(buf, map->map_file); 63060228Seric i = strlen(buf); 63160228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 63260228Seric (void) strcat(buf, ".db"); 63360582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 63456822Seric if (db == NULL) 63556822Seric { 63660207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 63756836Seric syserr("Cannot open HASH database %s", map->map_file); 63856822Seric return FALSE; 63956822Seric } 64060582Seric #if !defined(OLD_NEWDB) && !defined(LOCKF) 64160582Seric # if !defined(O_EXLOCK) 64260582Seric if (mode == O_RDWR) 64360582Seric (void) lockfile(db->fd(db), map->map_file, LOCK_EX); 64460582Seric # else 64560582Seric if (mode == O_RDONLY) 64660582Seric (void) lockfile(db->fd(db), map->map_file, LOCK_UN); 64760582Seric # endif 64860582Seric #endif 64960585Seric 65060585Seric /* try to make sure that at least the database header is on disk */ 65160585Seric if (mode == O_RDWR) 65260585Seric (void) db->sync(db, 0); 65360585Seric 65460089Seric map->map_db2 = (void *) db; 65560207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 65660207Seric aliaswait(map, ".db"); 65756822Seric return TRUE; 65856822Seric } 65956822Seric 66056822Seric 66156822Seric /* 66256822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 66356822Seric */ 66456822Seric 66556822Seric char * 66660089Seric db_map_lookup(map, name, av, statp) 66756822Seric MAP *map; 66860089Seric char *name; 66956822Seric char **av; 67059084Seric int *statp; 67156822Seric { 67256822Seric DBT key, val; 67360422Seric register DB *db = (DB *) map->map_db2; 67460422Seric int st; 67560422Seric int saveerrno; 67660089Seric char keybuf[MAXNAME + 1]; 67756822Seric 67860537Seric if (tTd(38, 20)) 67960089Seric printf("db_map_lookup(%s)\n", name); 68060089Seric 68160089Seric key.size = strlen(name); 68260089Seric if (key.size > sizeof keybuf - 1) 68360089Seric key.size = sizeof keybuf - 1; 68460089Seric key.data = keybuf; 68560089Seric bcopy(name, keybuf, key.size + 1); 68660207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 68760089Seric makelower(keybuf); 68860422Seric #ifndef OLD_NEWDB 68960422Seric (void) lockfile(db->fd(db), map->map_file, LOCK_SH); 69060422Seric #endif 691*63753Seric st = 1; 692*63753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 693*63753Seric { 694*63753Seric st = db->get(db, &key, &val, 0); 695*63753Seric if (st == 0) 696*63753Seric map->map_mflags &= ~MF_TRY1NULL; 697*63753Seric } 698*63753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 699*63753Seric { 700*63753Seric key.size++; 701*63753Seric st = db->get(db, &key, &val, 0); 702*63753Seric if (st == 0) 703*63753Seric map->map_mflags &= ~MF_TRY0NULL; 704*63753Seric } 70560422Seric saveerrno = errno; 70660422Seric #ifndef OLD_NEWDB 70760422Seric (void) lockfile(db->fd(db), map->map_file, LOCK_UN); 70860422Seric #endif 70960422Seric if (st != 0) 71060422Seric { 71160422Seric errno = saveerrno; 71260422Seric if (st < 0) 71360422Seric syserr("db_map_lookup: get (%s)", name); 71456822Seric return NULL; 71560422Seric } 71660207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 717*63753Seric return map_rewrite(map, name, strlen(name), NULL); 718*63753Seric else 719*63753Seric return map_rewrite(map, val.data, val.size, av); 72056822Seric } 72156822Seric 72260089Seric 72360089Seric /* 72460089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 72556822Seric */ 72656822Seric 72760089Seric void 72860089Seric db_map_store(map, lhs, rhs) 72960089Seric register MAP *map; 73060089Seric char *lhs; 73160089Seric char *rhs; 73256822Seric { 73360089Seric int stat; 73460089Seric DBT key; 73560089Seric DBT data; 73660089Seric register DB *db = map->map_db2; 73756822Seric 73860537Seric if (tTd(38, 20)) 73960089Seric printf("db_map_store(%s, %s)\n", lhs, rhs); 74060089Seric 74160089Seric key.size = strlen(lhs); 74260089Seric key.data = lhs; 74360089Seric 74460089Seric data.size = strlen(rhs); 74560089Seric data.data = rhs; 74660089Seric 74760207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 74856822Seric { 74960089Seric key.size++; 75060089Seric data.size++; 75160089Seric } 75256836Seric 75360089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 75460089Seric if (stat > 0) 75560089Seric { 75660089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 75760089Seric stat = db->put(db, &key, &data, 0); 75860089Seric } 75960089Seric if (stat != 0) 76060089Seric syserr("readaliases: db put (%s)", lhs); 76160089Seric } 76256836Seric 76356847Seric 76460089Seric /* 76560089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 76660089Seric */ 76760089Seric 76860089Seric void 76960089Seric db_map_close(map) 77060089Seric MAP *map; 77160089Seric { 77260089Seric register DB *db = map->map_db2; 77360089Seric 77460537Seric if (tTd(38, 9)) 77560207Seric printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags); 77660089Seric 77760207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 77858804Seric { 77960089Seric /* write out the distinguished alias */ 78060089Seric db_map_store(map, "@", "@"); 78158804Seric } 78258963Seric 78360089Seric if (db->close(db) != 0) 78460089Seric syserr("readaliases: db close failure"); 78556822Seric } 78657208Seric 78760089Seric #endif 78860089Seric /* 78960089Seric ** NIS Modules 79060089Seric */ 79160089Seric 79260089Seric # ifdef NIS 79360089Seric 79457208Seric /* 79560089Seric ** NIS_MAP_OPEN -- open DBM map 79657208Seric */ 79757208Seric 79857208Seric bool 79960089Seric nis_map_open(map, mode) 80057208Seric MAP *map; 80160089Seric int mode; 80257208Seric { 80357216Seric int yperr; 80460215Seric register char *p; 80560215Seric auto char *vp; 80660215Seric auto int vsize; 80757216Seric char *master; 80857216Seric 80960537Seric if (tTd(38, 2)) 81060089Seric printf("nis_map_open(%s)\n", map->map_file); 81160089Seric 81260207Seric if (mode != O_RDONLY) 81360207Seric { 81460207Seric errno = ENODEV; 81560207Seric return FALSE; 81660207Seric } 81760207Seric 81860089Seric p = strchr(map->map_file, '@'); 81960089Seric if (p != NULL) 82060089Seric { 82160089Seric *p++ = '\0'; 82260089Seric if (*p != '\0') 82360089Seric map->map_domain = p; 82460089Seric } 82560215Seric 82660089Seric if (map->map_domain == NULL) 82760089Seric yp_get_default_domain(&map->map_domain); 82860089Seric 82960089Seric if (*map->map_file == '\0') 83060089Seric map->map_file = "mail.aliases"; 83160089Seric 83260215Seric /* check to see if this map actually exists */ 83360089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 83460089Seric &vp, &vsize); 83560537Seric if (tTd(38, 10)) 83660089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 83760089Seric map->map_domain, map->map_file, yperr_string(yperr)); 83860089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 83960089Seric return TRUE; 84060215Seric 84160215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 84260215Seric syserr("Cannot bind to domain %s: %s", map->map_domain, 84360215Seric yperr_string(yperr)); 84460215Seric 84560089Seric return FALSE; 84660089Seric } 84760089Seric 84860089Seric 84960089Seric /* 85057208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 85157208Seric */ 85257208Seric 85357208Seric char * 85460089Seric nis_map_lookup(map, name, av, statp) 85557208Seric MAP *map; 85660089Seric char *name; 85757208Seric char **av; 85859084Seric int *statp; 85957208Seric { 86057208Seric char *vp; 86157642Seric auto int vsize; 86259274Seric int buflen; 86360215Seric int yperr; 86460089Seric char keybuf[MAXNAME + 1]; 86557208Seric 86660537Seric if (tTd(38, 20)) 86760089Seric printf("nis_map_lookup(%s)\n", name); 86860089Seric 86960089Seric buflen = strlen(name); 87060089Seric if (buflen > sizeof keybuf - 1) 87160089Seric buflen = sizeof keybuf - 1; 87260089Seric bcopy(name, keybuf, buflen + 1); 87360207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 87460089Seric makelower(keybuf); 875*63753Seric yperr = YPERR_KEY; 876*63753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 877*63753Seric { 878*63753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 879*63753Seric &vp, &vsize); 880*63753Seric if (yperr == 0) 881*63753Seric map->map_mflags &= ~MF_TRY1NULL; 882*63753Seric } 883*63753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 884*63753Seric { 88559274Seric buflen++; 886*63753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 887*63753Seric &vp, &vsize); 888*63753Seric if (yperr == 0) 889*63753Seric map->map_mflags &= ~MF_TRY0NULL; 890*63753Seric } 89160089Seric if (yperr != 0) 89260089Seric { 89360089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 89460215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 89557208Seric return NULL; 89660089Seric } 89760207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 898*63753Seric return map_rewrite(map, name, strlen(name), NULL); 899*63753Seric else 900*63753Seric return map_rewrite(map, vp, vsize, av); 90157208Seric } 90257208Seric 90360089Seric 90460089Seric /* 90560207Seric ** NIS_MAP_STORE 90660089Seric */ 90760089Seric 90860089Seric void 90960089Seric nis_map_store(map, lhs, rhs) 91060089Seric MAP *map; 91160089Seric char *lhs; 91260089Seric char *rhs; 91360089Seric { 91460089Seric /* nothing */ 91560089Seric } 91660089Seric 91760089Seric 91860089Seric /* 91960207Seric ** NIS_MAP_CLOSE 92060089Seric */ 92160089Seric 92260089Seric void 92360089Seric nis_map_close(map) 92460089Seric MAP *map; 92560089Seric { 92660089Seric /* nothing */ 92760089Seric } 92860089Seric 92960089Seric #endif /* NIS */ 93057208Seric /* 93160089Seric ** STAB (Symbol Table) Modules 93260089Seric */ 93360089Seric 93460089Seric 93560089Seric /* 93660207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 93760089Seric */ 93860089Seric 93960089Seric char * 94061707Seric stab_map_lookup(map, name, av, pstat) 94160089Seric register MAP *map; 94260089Seric char *name; 94361707Seric char **av; 94461707Seric int *pstat; 94560089Seric { 94660089Seric register STAB *s; 94760089Seric 94860537Seric if (tTd(38, 20)) 94960089Seric printf("stab_lookup(%s)\n", name); 95060089Seric 95160089Seric s = stab(name, ST_ALIAS, ST_FIND); 95260089Seric if (s != NULL) 95360089Seric return (s->s_alias); 95460089Seric return (NULL); 95560089Seric } 95660089Seric 95760089Seric 95860089Seric /* 95960207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 96060089Seric */ 96160089Seric 96260089Seric void 96360089Seric stab_map_store(map, lhs, rhs) 96460089Seric register MAP *map; 96560089Seric char *lhs; 96660089Seric char *rhs; 96760089Seric { 96860089Seric register STAB *s; 96960089Seric 97060089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 97160089Seric s->s_alias = newstr(rhs); 97260089Seric } 97360089Seric 97460089Seric 97560089Seric /* 97660207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 97760207Seric ** 97860207Seric ** This is a wierd case -- it is only intended as a fallback for 97960207Seric ** aliases. For this reason, opens for write (only during a 98060207Seric ** "newaliases") always fails, and opens for read open the 98160207Seric ** actual underlying text file instead of the database. 98260089Seric */ 98360089Seric 98460089Seric bool 98560089Seric stab_map_open(map, mode) 98660089Seric register MAP *map; 98760089Seric int mode; 98860089Seric { 98960537Seric if (tTd(38, 2)) 99060089Seric printf("stab_map_open(%s)\n", map->map_file); 99160089Seric 99260089Seric if (mode != O_RDONLY) 99360207Seric { 99460207Seric errno = ENODEV; 99560089Seric return FALSE; 99660207Seric } 99760089Seric 99860089Seric return TRUE; 99960089Seric } 100060089Seric 100160089Seric 100260089Seric /* 100360207Seric ** STAB_MAP_CLOSE -- close symbol table (???) 100460089Seric */ 100560089Seric 100660089Seric void 100760089Seric stab_map_close(map) 100860089Seric MAP *map; 100960089Seric { 101060089Seric /* ignore it */ 101160089Seric } 101260089Seric /* 101360089Seric ** Implicit Modules 101456822Seric ** 101560089Seric ** Tries several types. For back compatibility of aliases. 101656822Seric */ 101756822Seric 101860089Seric 101960089Seric /* 102060207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 102160089Seric */ 102260089Seric 102360089Seric char * 102460089Seric impl_map_lookup(map, name, av, pstat) 102560089Seric MAP *map; 102660089Seric char *name; 102756822Seric char **av; 102860089Seric int *pstat; 102956822Seric { 103060537Seric if (tTd(38, 20)) 103160089Seric printf("impl_map_lookup(%s)\n", name); 103256822Seric 103360089Seric #ifdef NEWDB 103460207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 103560089Seric return db_map_lookup(map, name, av, pstat); 103660089Seric #endif 103760089Seric #ifdef NDBM 103860207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 103960089Seric return ndbm_map_lookup(map, name, av, pstat); 104060089Seric #endif 104160089Seric return stab_map_lookup(map, name, av, pstat); 104260089Seric } 104360089Seric 104460089Seric /* 104560207Seric ** IMPL_MAP_STORE -- store in open databases 104660089Seric */ 104760089Seric 104860089Seric void 104960089Seric impl_map_store(map, lhs, rhs) 105060089Seric MAP *map; 105160089Seric char *lhs; 105260089Seric char *rhs; 105360089Seric { 105460089Seric #ifdef NEWDB 105560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 105660089Seric db_map_store(map, lhs, rhs); 105760089Seric #endif 105860089Seric #ifdef NDBM 105960207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 106060089Seric ndbm_map_store(map, lhs, rhs); 106160089Seric #endif 106260089Seric stab_map_store(map, lhs, rhs); 106360089Seric } 106460089Seric 106560089Seric /* 106660089Seric ** IMPL_MAP_OPEN -- implicit database open 106760089Seric */ 106860089Seric 106960089Seric bool 107060089Seric impl_map_open(map, mode) 107160089Seric MAP *map; 107260089Seric int mode; 107360089Seric { 107460089Seric struct stat stb; 107560089Seric 107660537Seric if (tTd(38, 2)) 107760089Seric printf("impl_map_open(%s)\n", map->map_file); 107860089Seric 107960089Seric if (stat(map->map_file, &stb) < 0) 108056822Seric { 108160089Seric /* no alias file at all */ 108260089Seric return FALSE; 108356822Seric } 108456822Seric 108560089Seric #ifdef NEWDB 108660207Seric map->map_mflags |= MF_IMPL_HASH; 108760089Seric if (hash_map_open(map, mode)) 108856822Seric { 108960207Seric #if defined(NDBM) && defined(YPCOMPAT) 109060561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 109160207Seric #endif 109260207Seric return TRUE; 109360089Seric } 109460207Seric else 109560207Seric map->map_mflags &= ~MF_IMPL_HASH; 109660089Seric #endif 109760089Seric #ifdef NDBM 109860207Seric map->map_mflags |= MF_IMPL_NDBM; 109960089Seric if (ndbm_map_open(map, mode)) 110060089Seric { 110160089Seric return TRUE; 110260089Seric } 110360207Seric else 110460207Seric map->map_mflags &= ~MF_IMPL_NDBM; 110560089Seric #endif 110656822Seric 110760207Seric #if !defined(NEWDB) && !defined(NDBM) 110860089Seric if (Verbose) 110960089Seric message("WARNING: cannot open alias database %s", map->map_file); 111060207Seric #endif 111160089Seric 111260207Seric return stab_map_open(map, mode); 111356822Seric } 111460089Seric 111560207Seric 111660089Seric /* 111760207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 111860089Seric */ 111960089Seric 112060089Seric void 112160207Seric impl_map_close(map) 112260089Seric MAP *map; 112360089Seric { 112460089Seric #ifdef NEWDB 112560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 112660089Seric { 112760207Seric db_map_close(map); 112860207Seric map->map_mflags &= ~MF_IMPL_HASH; 112960089Seric } 113060089Seric #endif 113160089Seric 113260089Seric #ifdef NDBM 113360207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 113460089Seric { 113560207Seric ndbm_map_close(map); 113660207Seric map->map_mflags &= ~MF_IMPL_NDBM; 113760089Seric } 113860089Seric #endif 113960089Seric } 114060207Seric /* 114160207Seric ** NULL stubs 114260089Seric */ 114360089Seric 114460207Seric bool 114560207Seric null_map_open(map, mode) 114660089Seric MAP *map; 114760207Seric int mode; 114860089Seric { 114960207Seric return TRUE; 115060089Seric } 115160089Seric 115260207Seric void 115360207Seric null_map_close(map) 115460207Seric MAP *map; 115560089Seric { 115660207Seric return; 115760207Seric } 115860089Seric 115960207Seric void 116060207Seric null_map_store(map, key, val) 116160207Seric MAP *map; 116260207Seric char *key; 116360207Seric char *val; 116460089Seric { 116560207Seric return; 116660089Seric } 1167