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*67173Seric static char sccsid[] = "@(#)map.c 8.26 (Berkeley) 05/18/94"; 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 6264718Seric 6364718Seric extern bool aliaswait __P((MAP *, char *, int)); 6460089Seric /* 6560089Seric ** MAP_PARSEARGS -- parse config line arguments for database lookup 6660089Seric ** 6760089Seric ** This is a generic version of the map_parse method. 6860089Seric ** 6956822Seric ** Parameters: 7060089Seric ** map -- the map being initialized. 7160089Seric ** ap -- a pointer to the args on the config line. 7256822Seric ** 7356822Seric ** Returns: 7460089Seric ** TRUE -- if everything parsed OK. 7556822Seric ** FALSE -- otherwise. 7656822Seric ** 7756822Seric ** Side Effects: 7860089Seric ** null terminates the filename; stores it in map 7956822Seric */ 8056822Seric 8156822Seric bool 8260089Seric map_parseargs(map, ap) 8356822Seric MAP *map; 8460089Seric char *ap; 8556822Seric { 8660089Seric register char *p = ap; 8756822Seric 8863753Seric map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; 8960089Seric for (;;) 9060089Seric { 9160089Seric while (isascii(*p) && isspace(*p)) 9260089Seric p++; 9360089Seric if (*p != '-') 9460089Seric break; 9560089Seric switch (*++p) 9660089Seric { 9760089Seric case 'N': 9860207Seric map->map_mflags |= MF_INCLNULL; 9963753Seric map->map_mflags &= ~MF_TRY0NULL; 10060089Seric break; 10160089Seric 10263753Seric case 'O': 10363753Seric map->map_mflags &= ~MF_TRY1NULL; 10463753Seric break; 10563753Seric 10660089Seric case 'o': 10760207Seric map->map_mflags |= MF_OPTIONAL; 10860089Seric break; 10960089Seric 11060089Seric case 'f': 11160207Seric map->map_mflags |= MF_NOFOLDCASE; 11260089Seric break; 11360089Seric 11460089Seric case 'm': 11560207Seric map->map_mflags |= MF_MATCHONLY; 11660089Seric break; 11760089Seric 11860089Seric case 'a': 11960089Seric map->map_app = ++p; 12060089Seric break; 12160089Seric } 12260089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 12360089Seric p++; 12460089Seric if (*p != '\0') 12560089Seric *p++ = '\0'; 12660089Seric } 12760089Seric if (map->map_app != NULL) 12860089Seric map->map_app = newstr(map->map_app); 12960089Seric 13060089Seric if (*p != '\0') 13160089Seric { 13260089Seric map->map_file = p; 13360089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 13460089Seric p++; 13560089Seric if (*p != '\0') 13660089Seric *p++ = '\0'; 13760089Seric map->map_file = newstr(map->map_file); 13860089Seric } 13960089Seric 14060089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 14160089Seric p++; 14260089Seric if (*p != '\0') 14360089Seric map->map_rebuild = newstr(p); 14460089Seric 14556822Seric if (map->map_file == NULL) 14657208Seric { 14760089Seric syserr("No file name for %s map %s", 14860089Seric map->map_class->map_cname, map->map_mname); 14956822Seric return FALSE; 15057208Seric } 15160089Seric return TRUE; 15260089Seric } 15360089Seric /* 15460089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 15560089Seric ** 15660089Seric ** It also adds the map_app string. It can be used as a utility 15760089Seric ** in the map_lookup method. 15860089Seric ** 15960089Seric ** Parameters: 16060089Seric ** map -- the map that causes this. 16160089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 16260089Seric ** slen -- the length of s. 16360089Seric ** av -- arguments to interpolate into buf. 16460089Seric ** 16560089Seric ** Returns: 16660089Seric ** Pointer to rewritten result. 16760089Seric ** 16860089Seric ** Side Effects: 16960089Seric ** none. 17060089Seric */ 17160089Seric 17260492Seric struct rwbuf 17360492Seric { 17460492Seric int rwb_len; /* size of buffer */ 17560492Seric char *rwb_buf; /* ptr to buffer */ 17660492Seric }; 17760492Seric 17860492Seric struct rwbuf RwBufs[2]; /* buffers for rewriting output */ 17960492Seric 18060089Seric char * 18160089Seric map_rewrite(map, s, slen, av) 18260089Seric register MAP *map; 18360089Seric register char *s; 18460089Seric int slen; 18560089Seric char **av; 18660089Seric { 18760089Seric register char *bp; 18860089Seric register char c; 18960089Seric char **avp; 19060089Seric register char *ap; 19160492Seric register struct rwbuf *rwb; 19260089Seric int i; 19360089Seric int len; 19460089Seric 19560537Seric if (tTd(39, 1)) 19660089Seric { 19760256Seric printf("map_rewrite(%.*s), av =", slen, s); 19860256Seric if (av == NULL) 19960256Seric printf(" (nullv)"); 20060256Seric else 20160256Seric { 20260256Seric for (avp = av; *avp != NULL; avp++) 20360256Seric printf("\n\t%s", *avp); 20460256Seric } 20560256Seric printf("\n"); 20660089Seric } 20760089Seric 20860492Seric rwb = RwBufs; 20960492Seric if (av == NULL) 21060492Seric rwb++; 21160492Seric 21260089Seric /* count expected size of output (can safely overestimate) */ 21360089Seric i = len = slen; 21460089Seric if (av != NULL) 21560089Seric { 21660089Seric bp = s; 21760089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 21860089Seric { 21960089Seric if (c != '%') 22060089Seric continue; 22160089Seric if (--i < 0) 22260089Seric break; 22360089Seric c = *bp++; 22460089Seric if (!(isascii(c) && isdigit(c))) 22560089Seric continue; 22663937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 22760089Seric continue; 22860089Seric if (*avp == NULL) 22960089Seric continue; 23060089Seric len += strlen(*avp); 23160089Seric } 23260089Seric } 23360089Seric if (map->map_app != NULL) 23460089Seric len += strlen(map->map_app); 23560492Seric if (rwb->rwb_len < ++len) 23660089Seric { 23760089Seric /* need to malloc additional space */ 23860492Seric rwb->rwb_len = len; 23960492Seric if (rwb->rwb_buf != NULL) 24060492Seric free(rwb->rwb_buf); 24160492Seric rwb->rwb_buf = xalloc(rwb->rwb_len); 24260089Seric } 24360089Seric 24460492Seric bp = rwb->rwb_buf; 24560089Seric if (av == NULL) 24660089Seric { 24760089Seric bcopy(s, bp, slen); 24860089Seric bp += slen; 24960089Seric } 25060089Seric else 25160089Seric { 25260089Seric while (--slen >= 0 && (c = *s++) != '\0') 25360089Seric { 25460089Seric if (c != '%') 25560089Seric { 25660089Seric pushc: 25760089Seric *bp++ = c; 25860089Seric continue; 25960089Seric } 26060089Seric if (--slen < 0 || (c = *s++) == '\0') 26160089Seric c = '%'; 26260089Seric if (c == '%') 26360089Seric goto pushc; 26460089Seric if (!(isascii(c) && isdigit(c))) 26560089Seric { 26660089Seric *bp++ = '%'; 26760089Seric goto pushc; 26860089Seric } 26963937Seric 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 30964671Seric #ifdef XDEBUG 31064671Seric checkfd012("entering initmaps"); 31164671Seric #endif 31260537Seric CurEnv = e; 31365085Seric if (rebuild) 31465085Seric { 31565085Seric stabapply(map_init, 1); 31665085Seric stabapply(map_init, 2); 31765085Seric } 31865085Seric else 31965085Seric { 32065085Seric stabapply(map_init, 0); 32165085Seric } 32264671Seric #ifdef XDEBUG 32364671Seric checkfd012("exiting initmaps"); 32464671Seric #endif 32560537Seric } 32660537Seric 32760537Seric void 32860537Seric map_init(s, rebuild) 32960537Seric register STAB *s; 33060537Seric int rebuild; 33160537Seric { 33260537Seric register MAP *map; 33360537Seric 33460537Seric /* has to be a map */ 33560537Seric if (s->s_type != ST_MAP) 33660537Seric return; 33760537Seric 33860537Seric map = &s->s_map; 33960537Seric if (!bitset(MF_VALID, map->map_mflags)) 34060537Seric return; 34160537Seric 34260537Seric if (tTd(38, 2)) 34365085Seric printf("map_init(%s:%s, %d)\n", 34464690Seric map->map_class->map_cname == NULL ? "NULL" : 34564690Seric map->map_class->map_cname, 34665085Seric map->map_file == NULL ? "NULL" : map->map_file, 34765085Seric rebuild); 34860537Seric 34965085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && 35065085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) 35165085Seric { 35265085Seric if (tTd(38, 3)) 35365085Seric printf("\twrong pass\n"); 35465085Seric return; 35565085Seric } 35665085Seric 35760537Seric /* if already open, close it (for nested open) */ 35860537Seric if (bitset(MF_OPEN, map->map_mflags)) 35960537Seric { 36060537Seric map->map_class->map_close(map); 36160537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 36260537Seric } 36360537Seric 36465085Seric if (rebuild == 2) 36560537Seric { 36665085Seric rebuildaliases(map, FALSE); 36760537Seric } 36860537Seric else 36960537Seric { 37060537Seric if (map->map_class->map_open(map, O_RDONLY)) 37160537Seric { 37260537Seric if (tTd(38, 4)) 37365085Seric printf("\t%s:%s: valid\n", 37464690Seric map->map_class->map_cname == NULL ? "NULL" : 37564690Seric map->map_class->map_cname, 37664690Seric map->map_file == NULL ? "NULL" : 37764690Seric map->map_file); 37860537Seric map->map_mflags |= MF_OPEN; 37960537Seric } 38060537Seric else if (tTd(38, 4)) 38165085Seric printf("\t%s:%s: invalid: %s\n", 38264690Seric map->map_class->map_cname == NULL ? "NULL" : 38364690Seric map->map_class->map_cname, 38464690Seric map->map_file == NULL ? "NULL" : 38564690Seric map->map_file, 38660537Seric errstring(errno)); 38760537Seric } 38860537Seric } 38960537Seric /* 39060089Seric ** NDBM modules 39160089Seric */ 39260089Seric 39360089Seric #ifdef NDBM 39460089Seric 39560089Seric /* 39660089Seric ** DBM_MAP_OPEN -- DBM-style map open 39760089Seric */ 39860089Seric 39960089Seric bool 40060089Seric ndbm_map_open(map, mode) 40160089Seric MAP *map; 40260089Seric int mode; 40360089Seric { 40464284Seric register DBM *dbm; 40564284Seric struct stat st; 40660089Seric 40760537Seric if (tTd(38, 2)) 40860089Seric printf("ndbm_map_open(%s, %d)\n", map->map_file, mode); 40960089Seric 41060207Seric if (mode == O_RDWR) 41160207Seric mode |= O_CREAT|O_TRUNC; 41260207Seric 41360089Seric /* open the database */ 41460089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 41556822Seric if (dbm == NULL) 41656822Seric { 41764718Seric #ifdef MAYBENEXTRELEASE 41864718Seric if (aliaswait(map, ".pag", FALSE)) 41964718Seric return TRUE; 42064718Seric #endif 42160207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 42256836Seric syserr("Cannot open DBM database %s", map->map_file); 42356822Seric return FALSE; 42456822Seric } 42560089Seric map->map_db1 = (void *) dbm; 42664964Seric if (mode == O_RDONLY) 42764964Seric { 42864964Seric if (bitset(MF_ALIAS, map->map_mflags) && 42964964Seric !aliaswait(map, ".pag", TRUE)) 43064718Seric return FALSE; 43164964Seric } 43264964Seric else 43364964Seric { 43464964Seric int fd; 43564964Seric 43664964Seric /* exclusive lock for duration of rebuild */ 43764964Seric fd = dbm_dirfno((DBM *) map->map_db1); 43864964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 43964964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 44064964Seric map->map_mflags |= MF_LOCKED; 44164964Seric } 44264718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 44364284Seric map->map_mtime = st.st_mtime; 44456822Seric return TRUE; 44556822Seric } 44660089Seric 44760089Seric 44860089Seric /* 44956822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 45056822Seric */ 45156822Seric 45256822Seric char * 45360089Seric ndbm_map_lookup(map, name, av, statp) 45456822Seric MAP *map; 45560089Seric char *name; 45656822Seric char **av; 45759084Seric int *statp; 45856822Seric { 45956822Seric datum key, val; 46064373Seric int fd; 46160089Seric char keybuf[MAXNAME + 1]; 46256822Seric 46360537Seric if (tTd(38, 20)) 46460089Seric printf("ndbm_map_lookup(%s)\n", name); 46560089Seric 46660089Seric key.dptr = name; 46760089Seric key.dsize = strlen(name); 46860207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 46957014Seric { 47060089Seric if (key.dsize > sizeof keybuf - 1) 47160089Seric key.dsize = sizeof keybuf - 1; 47260089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 47360089Seric makelower(keybuf); 47460089Seric key.dptr = keybuf; 47557014Seric } 47664373Seric fd = dbm_dirfno((DBM *) map->map_db1); 47764388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 47864373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 47963753Seric val.dptr = NULL; 48063753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 48163753Seric { 48263753Seric val = dbm_fetch((DBM *) map->map_db1, key); 48363753Seric if (val.dptr != NULL) 48463753Seric map->map_mflags &= ~MF_TRY1NULL; 48563753Seric } 48663753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 48763753Seric { 48856822Seric key.dsize++; 48963753Seric val = dbm_fetch((DBM *) map->map_db1, key); 49063753Seric if (val.dptr != NULL) 49163753Seric map->map_mflags &= ~MF_TRY0NULL; 49263753Seric } 49364388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 49464373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 49556822Seric if (val.dptr == NULL) 49656822Seric return NULL; 49760207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 49863753Seric return map_rewrite(map, name, strlen(name), NULL); 49963753Seric else 50063753Seric return map_rewrite(map, val.dptr, val.dsize, av); 50156822Seric } 50256822Seric 50356822Seric 50456822Seric /* 50560089Seric ** DBM_MAP_STORE -- store a datum in the database 50656822Seric */ 50756822Seric 50860089Seric void 50960089Seric ndbm_map_store(map, lhs, rhs) 51060089Seric register MAP *map; 51160089Seric char *lhs; 51260089Seric char *rhs; 51360089Seric { 51460089Seric datum key; 51560089Seric datum data; 51660089Seric int stat; 51760089Seric 51860537Seric if (tTd(38, 12)) 51960089Seric printf("ndbm_map_store(%s, %s)\n", lhs, rhs); 52060089Seric 52160089Seric key.dsize = strlen(lhs); 52260089Seric key.dptr = lhs; 52360089Seric 52460089Seric data.dsize = strlen(rhs); 52560089Seric data.dptr = rhs; 52660089Seric 52760207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 52860089Seric { 52960089Seric key.dsize++; 53060089Seric data.dsize++; 53160089Seric } 53260089Seric 53360089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 53460089Seric if (stat > 0) 53560089Seric { 53660089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 53760089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 53860089Seric } 53960089Seric if (stat != 0) 54060089Seric syserr("readaliases: dbm put (%s)", lhs); 54160089Seric } 54260089Seric 54360089Seric 54460089Seric /* 54560207Seric ** NDBM_MAP_CLOSE -- close the database 54660089Seric */ 54760089Seric 54860089Seric void 54960089Seric ndbm_map_close(map) 55060089Seric register MAP *map; 55160089Seric { 55266773Seric if (tTd(38, 9)) 55366773Seric printf("ndbm_map_close(%s, %x)\n", map->map_file, map->map_mflags); 55466773Seric 55560207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 55660089Seric { 55764250Seric #ifdef NIS 55864075Seric bool inclnull; 55960089Seric char buf[200]; 56060089Seric 56164075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 56264075Seric map->map_mflags &= ~MF_INCLNULL; 56364075Seric 56460089Seric (void) sprintf(buf, "%010ld", curtime()); 56560089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 56660089Seric 56764941Seric (void) gethostname(buf, sizeof buf); 56860089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 56964075Seric 57064075Seric if (inclnull) 57164075Seric map->map_mflags |= MF_INCLNULL; 57260089Seric #endif 57360089Seric 57460089Seric /* write out the distinguished alias */ 57560089Seric ndbm_map_store(map, "@", "@"); 57660089Seric } 57760089Seric dbm_close((DBM *) map->map_db1); 57860089Seric } 57960089Seric 58060089Seric #endif 58160089Seric /* 58260582Seric ** NEWDB (Hash and BTree) Modules 58360089Seric */ 58460089Seric 58560089Seric #ifdef NEWDB 58660089Seric 58760089Seric /* 58860582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 58960582Seric ** 59060582Seric ** These do rather bizarre locking. If you can lock on open, 59160582Seric ** do that to avoid the condition of opening a database that 59260582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 59360582Seric ** there will be a race condition. If opening for read-only, 59460582Seric ** we immediately release the lock to avoid freezing things up. 59560582Seric ** We really ought to hold the lock, but guarantee that we won't 59660582Seric ** be pokey about it. That's hard to do. 59760089Seric */ 59860089Seric 59956822Seric bool 60060089Seric bt_map_open(map, mode) 60156822Seric MAP *map; 60260089Seric int mode; 60356822Seric { 60456822Seric DB *db; 60560228Seric int i; 60660582Seric int omode; 60764373Seric int fd; 60864284Seric struct stat st; 60960089Seric char buf[MAXNAME]; 61056822Seric 61160537Seric if (tTd(38, 2)) 61260089Seric printf("bt_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; 61865830Seric #if defined(O_EXLOCK) && HASFLOCK 61960582Seric omode |= O_EXLOCK; 62066843Seric # if !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_BTREE, NULL); 63456822Seric if (db == NULL) 63556822Seric { 63664718Seric #ifdef MAYBENEXTRELEASE 63764718Seric if (aliaswait(map, ".db", FALSE)) 63864718Seric return TRUE; 63964718Seric #endif 64060207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 64156836Seric syserr("Cannot open BTREE database %s", map->map_file); 64256822Seric return FALSE; 64356822Seric } 644*67173Seric #if !OLD_NEWDB 64564373Seric fd = db->fd(db); 646*67173Seric #endif 647*67173Seric #if HASFLOCK 64860582Seric # if !defined(O_EXLOCK) 64964373Seric if (mode == O_RDWR && fd >= 0) 65064388Seric { 65164388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 65264388Seric map->map_mflags |= MF_LOCKED; 65364388Seric } 65460582Seric # else 65564373Seric if (mode == O_RDONLY && fd >= 0) 65664373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 65764388Seric else 65864388Seric map->map_mflags |= MF_LOCKED; 65960582Seric # endif 66060582Seric #endif 66160585Seric 66260585Seric /* try to make sure that at least the database header is on disk */ 66360585Seric if (mode == O_RDWR) 66466843Seric #if OLD_NEWDB 66564373Seric (void) db->sync(db); 66664373Seric #else 66760585Seric (void) db->sync(db, 0); 66860585Seric 66964373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 67064284Seric map->map_mtime = st.st_mtime; 67164284Seric #endif 67264284Seric 67360089Seric map->map_db2 = (void *) db; 67460207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 67564718Seric if (!aliaswait(map, ".db", TRUE)) 67664718Seric return FALSE; 67756822Seric return TRUE; 67856822Seric } 67956822Seric 68056822Seric 68156822Seric /* 68256822Seric ** HASH_MAP_INIT -- HASH-style map initialization 68356822Seric */ 68456822Seric 68556822Seric bool 68660089Seric hash_map_open(map, mode) 68756822Seric MAP *map; 68860089Seric int mode; 68956822Seric { 69056822Seric DB *db; 69160228Seric int i; 69260582Seric int omode; 69364373Seric int fd; 69464284Seric struct stat st; 69560089Seric char buf[MAXNAME]; 69656822Seric 69760537Seric if (tTd(38, 2)) 69860089Seric printf("hash_map_open(%s, %d)\n", map->map_file, mode); 69960089Seric 70060582Seric omode = mode; 70160582Seric if (omode == O_RDWR) 70260582Seric { 70360582Seric omode |= O_CREAT|O_TRUNC; 70465830Seric #if defined(O_EXLOCK) && HASFLOCK 70560582Seric omode |= O_EXLOCK; 70666843Seric # if !OLD_NEWDB 70760582Seric } 70860582Seric else 70960582Seric { 71060582Seric omode |= O_SHLOCK; 71160582Seric # endif 71260582Seric #endif 71360582Seric } 71460207Seric 71560228Seric (void) strcpy(buf, map->map_file); 71660228Seric i = strlen(buf); 71760228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 71860228Seric (void) strcat(buf, ".db"); 71960582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 72056822Seric if (db == NULL) 72156822Seric { 72264718Seric #ifdef MAYBENEXTRELEASE 72364718Seric if (aliaswait(map, ".db", FALSE)) 72464718Seric return TRUE; 72564718Seric #endif 72660207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 72756836Seric syserr("Cannot open HASH database %s", map->map_file); 72856822Seric return FALSE; 72956822Seric } 730*67173Seric #if !OLD_NEWDB 73164373Seric fd = db->fd(db); 732*67173Seric #endif 733*67173Seric #if HASFLOCK 73460582Seric # if !defined(O_EXLOCK) 73564373Seric if (mode == O_RDWR && fd >= 0) 73664388Seric { 73764388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 73864388Seric map->map_mflags |= MF_LOCKED; 73964388Seric } 74060582Seric # else 74164373Seric if (mode == O_RDONLY && fd >= 0) 74264373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 74364388Seric else 74464388Seric map->map_mflags |= MF_LOCKED; 74560582Seric # endif 74660582Seric #endif 74760585Seric 74860585Seric /* try to make sure that at least the database header is on disk */ 74960585Seric if (mode == O_RDWR) 75066843Seric #if OLD_NEWDB 75164373Seric (void) db->sync(db); 75264373Seric #else 75360585Seric (void) db->sync(db, 0); 75460585Seric 75564373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 75664284Seric map->map_mtime = st.st_mtime; 75764284Seric #endif 75864284Seric 75960089Seric map->map_db2 = (void *) db; 76060207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 76164718Seric if (!aliaswait(map, ".db", TRUE)) 76264718Seric return FALSE; 76356822Seric return TRUE; 76456822Seric } 76556822Seric 76656822Seric 76756822Seric /* 76856822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 76956822Seric */ 77056822Seric 77156822Seric char * 77260089Seric db_map_lookup(map, name, av, statp) 77356822Seric MAP *map; 77460089Seric char *name; 77556822Seric char **av; 77659084Seric int *statp; 77756822Seric { 77856822Seric DBT key, val; 77960422Seric register DB *db = (DB *) map->map_db2; 78060422Seric int st; 78160422Seric int saveerrno; 78264373Seric int fd; 78360089Seric char keybuf[MAXNAME + 1]; 78456822Seric 78560537Seric if (tTd(38, 20)) 78660089Seric printf("db_map_lookup(%s)\n", name); 78760089Seric 78860089Seric key.size = strlen(name); 78960089Seric if (key.size > sizeof keybuf - 1) 79060089Seric key.size = sizeof keybuf - 1; 79160089Seric key.data = keybuf; 79260089Seric bcopy(name, keybuf, key.size + 1); 79360207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 79460089Seric makelower(keybuf); 79566843Seric #if !OLD_NEWDB 79664388Seric fd = db->fd(db); 79764388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 79864388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 79960422Seric #endif 80063753Seric st = 1; 80163753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 80263753Seric { 80363753Seric st = db->get(db, &key, &val, 0); 80463753Seric if (st == 0) 80563753Seric map->map_mflags &= ~MF_TRY1NULL; 80663753Seric } 80763753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 80863753Seric { 80963753Seric key.size++; 81063753Seric st = db->get(db, &key, &val, 0); 81163753Seric if (st == 0) 81263753Seric map->map_mflags &= ~MF_TRY0NULL; 81363753Seric } 81460422Seric saveerrno = errno; 81566843Seric #if !OLD_NEWDB 81664388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 81764373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 81860422Seric #endif 81960422Seric if (st != 0) 82060422Seric { 82160422Seric errno = saveerrno; 82260422Seric if (st < 0) 82360422Seric syserr("db_map_lookup: get (%s)", name); 82456822Seric return NULL; 82560422Seric } 82660207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 82763753Seric return map_rewrite(map, name, strlen(name), NULL); 82863753Seric else 82963753Seric return map_rewrite(map, val.data, val.size, av); 83056822Seric } 83156822Seric 83260089Seric 83360089Seric /* 83460089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 83556822Seric */ 83656822Seric 83760089Seric void 83860089Seric db_map_store(map, lhs, rhs) 83960089Seric register MAP *map; 84060089Seric char *lhs; 84160089Seric char *rhs; 84256822Seric { 84360089Seric int stat; 84460089Seric DBT key; 84560089Seric DBT data; 84660089Seric register DB *db = map->map_db2; 84756822Seric 84860537Seric if (tTd(38, 20)) 84960089Seric printf("db_map_store(%s, %s)\n", lhs, rhs); 85060089Seric 85160089Seric key.size = strlen(lhs); 85260089Seric key.data = lhs; 85360089Seric 85460089Seric data.size = strlen(rhs); 85560089Seric data.data = rhs; 85660089Seric 85760207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 85856822Seric { 85960089Seric key.size++; 86060089Seric data.size++; 86160089Seric } 86256836Seric 86360089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 86460089Seric if (stat > 0) 86560089Seric { 86660089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 86760089Seric stat = db->put(db, &key, &data, 0); 86860089Seric } 86960089Seric if (stat != 0) 87060089Seric syserr("readaliases: db put (%s)", lhs); 87160089Seric } 87256836Seric 87356847Seric 87460089Seric /* 87560089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 87660089Seric */ 87760089Seric 87860089Seric void 87960089Seric db_map_close(map) 88060089Seric MAP *map; 88160089Seric { 88260089Seric register DB *db = map->map_db2; 88360089Seric 88460537Seric if (tTd(38, 9)) 88560207Seric printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags); 88660089Seric 88760207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 88858804Seric { 88960089Seric /* write out the distinguished alias */ 89060089Seric db_map_store(map, "@", "@"); 89158804Seric } 89258963Seric 89360089Seric if (db->close(db) != 0) 89460089Seric syserr("readaliases: db close failure"); 89556822Seric } 89657208Seric 89760089Seric #endif 89860089Seric /* 89960089Seric ** NIS Modules 90060089Seric */ 90160089Seric 90260089Seric # ifdef NIS 90360089Seric 90464369Seric # ifndef YPERR_BUSY 90564369Seric # define YPERR_BUSY 16 90664369Seric # endif 90764369Seric 90857208Seric /* 90960089Seric ** NIS_MAP_OPEN -- open DBM map 91057208Seric */ 91157208Seric 91257208Seric bool 91360089Seric nis_map_open(map, mode) 91457208Seric MAP *map; 91560089Seric int mode; 91657208Seric { 91757216Seric int yperr; 91860215Seric register char *p; 91960215Seric auto char *vp; 92060215Seric auto int vsize; 92157216Seric char *master; 92257216Seric 92360537Seric if (tTd(38, 2)) 92460089Seric printf("nis_map_open(%s)\n", map->map_file); 92560089Seric 92660207Seric if (mode != O_RDONLY) 92760207Seric { 92864650Seric /* issue a pseudo-error message */ 92964650Seric #ifdef ENOSYS 93064650Seric errno = ENOSYS; 93164650Seric #else 93264650Seric # ifdef EFTYPE 93364650Seric errno = EFTYPE; 93464650Seric # else 93564650Seric errno = ENXIO; 93664650Seric # endif 93764650Seric #endif 93860207Seric return FALSE; 93960207Seric } 94060207Seric 94160089Seric p = strchr(map->map_file, '@'); 94260089Seric if (p != NULL) 94360089Seric { 94460089Seric *p++ = '\0'; 94560089Seric if (*p != '\0') 94660089Seric map->map_domain = p; 94760089Seric } 94860215Seric 94960089Seric if (*map->map_file == '\0') 95060089Seric map->map_file = "mail.aliases"; 95160089Seric 95266157Seric if (map->map_domain == NULL) 95366157Seric { 95466157Seric yperr = yp_get_default_domain(&map->map_domain); 95566157Seric if (yperr != 0) 95666157Seric { 95766744Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 95866744Seric syserr("NIS map %s specified, but NIS not running\n", 95966744Seric map->map_file); 96066157Seric return FALSE; 96166157Seric } 96266157Seric } 96366157Seric 96460215Seric /* check to see if this map actually exists */ 96560089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 96660089Seric &vp, &vsize); 96760537Seric if (tTd(38, 10)) 96860089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 96960089Seric map->map_domain, map->map_file, yperr_string(yperr)); 97060089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 97160089Seric return TRUE; 97260215Seric 97360215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 97460215Seric syserr("Cannot bind to domain %s: %s", map->map_domain, 97560215Seric yperr_string(yperr)); 97660215Seric 97760089Seric return FALSE; 97860089Seric } 97960089Seric 98060089Seric 98160089Seric /* 98257208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 98357208Seric */ 98457208Seric 98557208Seric char * 98660089Seric nis_map_lookup(map, name, av, statp) 98757208Seric MAP *map; 98860089Seric char *name; 98957208Seric char **av; 99059084Seric int *statp; 99157208Seric { 99257208Seric char *vp; 99357642Seric auto int vsize; 99459274Seric int buflen; 99560215Seric int yperr; 99660089Seric char keybuf[MAXNAME + 1]; 99757208Seric 99860537Seric if (tTd(38, 20)) 99960089Seric printf("nis_map_lookup(%s)\n", name); 100060089Seric 100160089Seric buflen = strlen(name); 100260089Seric if (buflen > sizeof keybuf - 1) 100360089Seric buflen = sizeof keybuf - 1; 100460089Seric bcopy(name, keybuf, buflen + 1); 100560207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 100660089Seric makelower(keybuf); 100763753Seric yperr = YPERR_KEY; 100863753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 100963753Seric { 101063753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 101163753Seric &vp, &vsize); 101263753Seric if (yperr == 0) 101363753Seric map->map_mflags &= ~MF_TRY1NULL; 101463753Seric } 101563753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 101663753Seric { 101759274Seric buflen++; 101863753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 101963753Seric &vp, &vsize); 102063753Seric if (yperr == 0) 102163753Seric map->map_mflags &= ~MF_TRY0NULL; 102263753Seric } 102360089Seric if (yperr != 0) 102460089Seric { 102560089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 102660215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 102757208Seric return NULL; 102860089Seric } 102960207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 103063753Seric return map_rewrite(map, name, strlen(name), NULL); 103163753Seric else 103263753Seric return map_rewrite(map, vp, vsize, av); 103357208Seric } 103457208Seric 103560089Seric 103660089Seric /* 103760207Seric ** NIS_MAP_STORE 103860089Seric */ 103960089Seric 104060089Seric void 104160089Seric nis_map_store(map, lhs, rhs) 104260089Seric MAP *map; 104360089Seric char *lhs; 104460089Seric char *rhs; 104560089Seric { 104660089Seric /* nothing */ 104760089Seric } 104860089Seric 104960089Seric 105060089Seric /* 105160207Seric ** NIS_MAP_CLOSE 105260089Seric */ 105360089Seric 105460089Seric void 105560089Seric nis_map_close(map) 105660089Seric MAP *map; 105760089Seric { 105860089Seric /* nothing */ 105960089Seric } 106060089Seric 106160089Seric #endif /* NIS */ 106257208Seric /* 106360089Seric ** STAB (Symbol Table) Modules 106460089Seric */ 106560089Seric 106660089Seric 106760089Seric /* 106860207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 106960089Seric */ 107060089Seric 107160089Seric char * 107261707Seric stab_map_lookup(map, name, av, pstat) 107360089Seric register MAP *map; 107460089Seric char *name; 107561707Seric char **av; 107661707Seric int *pstat; 107760089Seric { 107860089Seric register STAB *s; 107960089Seric 108060537Seric if (tTd(38, 20)) 108160089Seric printf("stab_lookup(%s)\n", name); 108260089Seric 108360089Seric s = stab(name, ST_ALIAS, ST_FIND); 108460089Seric if (s != NULL) 108560089Seric return (s->s_alias); 108660089Seric return (NULL); 108760089Seric } 108860089Seric 108960089Seric 109060089Seric /* 109160207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 109260089Seric */ 109360089Seric 109460089Seric void 109560089Seric stab_map_store(map, lhs, rhs) 109660089Seric register MAP *map; 109760089Seric char *lhs; 109860089Seric char *rhs; 109960089Seric { 110060089Seric register STAB *s; 110160089Seric 110260089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 110360089Seric s->s_alias = newstr(rhs); 110460089Seric } 110560089Seric 110660089Seric 110760089Seric /* 110860207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 110960207Seric ** 111060207Seric ** This is a wierd case -- it is only intended as a fallback for 111160207Seric ** aliases. For this reason, opens for write (only during a 111260207Seric ** "newaliases") always fails, and opens for read open the 111360207Seric ** actual underlying text file instead of the database. 111460089Seric */ 111560089Seric 111660089Seric bool 111760089Seric stab_map_open(map, mode) 111860089Seric register MAP *map; 111960089Seric int mode; 112060089Seric { 112163835Seric FILE *af; 112264284Seric struct stat st; 112363835Seric 112460537Seric if (tTd(38, 2)) 112560089Seric printf("stab_map_open(%s)\n", map->map_file); 112660089Seric 112760089Seric if (mode != O_RDONLY) 112860207Seric { 112960207Seric errno = ENODEV; 113060089Seric return FALSE; 113160207Seric } 113260089Seric 113363835Seric af = fopen(map->map_file, "r"); 113463835Seric if (af == NULL) 113563835Seric return FALSE; 113663835Seric readaliases(map, af, TRUE); 113764284Seric 113864284Seric if (fstat(fileno(af), &st) >= 0) 113964284Seric map->map_mtime = st.st_mtime; 114063835Seric fclose(af); 114163835Seric 114260089Seric return TRUE; 114360089Seric } 114460089Seric 114560089Seric 114660089Seric /* 114764642Seric ** STAB_MAP_CLOSE -- close symbol table. 114864642Seric ** 114964642Seric ** Since this is in memory, there is nothing to do. 115060089Seric */ 115160089Seric 115260089Seric void 115360089Seric stab_map_close(map) 115460089Seric MAP *map; 115560089Seric { 115660089Seric /* ignore it */ 115760089Seric } 115860089Seric /* 115960089Seric ** Implicit Modules 116056822Seric ** 116160089Seric ** Tries several types. For back compatibility of aliases. 116256822Seric */ 116356822Seric 116460089Seric 116560089Seric /* 116660207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 116760089Seric */ 116860089Seric 116960089Seric char * 117060089Seric impl_map_lookup(map, name, av, pstat) 117160089Seric MAP *map; 117260089Seric char *name; 117356822Seric char **av; 117460089Seric int *pstat; 117556822Seric { 117660537Seric if (tTd(38, 20)) 117760089Seric printf("impl_map_lookup(%s)\n", name); 117856822Seric 117960089Seric #ifdef NEWDB 118060207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 118160089Seric return db_map_lookup(map, name, av, pstat); 118260089Seric #endif 118360089Seric #ifdef NDBM 118460207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 118560089Seric return ndbm_map_lookup(map, name, av, pstat); 118660089Seric #endif 118760089Seric return stab_map_lookup(map, name, av, pstat); 118860089Seric } 118960089Seric 119060089Seric /* 119160207Seric ** IMPL_MAP_STORE -- store in open databases 119260089Seric */ 119360089Seric 119460089Seric void 119560089Seric impl_map_store(map, lhs, rhs) 119660089Seric MAP *map; 119760089Seric char *lhs; 119860089Seric char *rhs; 119960089Seric { 120060089Seric #ifdef NEWDB 120160207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 120260089Seric db_map_store(map, lhs, rhs); 120360089Seric #endif 120460089Seric #ifdef NDBM 120560207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 120660089Seric ndbm_map_store(map, lhs, rhs); 120760089Seric #endif 120860089Seric stab_map_store(map, lhs, rhs); 120960089Seric } 121060089Seric 121160089Seric /* 121260089Seric ** IMPL_MAP_OPEN -- implicit database open 121360089Seric */ 121460089Seric 121560089Seric bool 121660089Seric impl_map_open(map, mode) 121760089Seric MAP *map; 121860089Seric int mode; 121960089Seric { 122060089Seric struct stat stb; 122160089Seric 122260537Seric if (tTd(38, 2)) 122364718Seric printf("impl_map_open(%s, %d)\n", map->map_file, mode); 122460089Seric 122560089Seric if (stat(map->map_file, &stb) < 0) 122656822Seric { 122760089Seric /* no alias file at all */ 122864718Seric if (tTd(38, 3)) 122964718Seric printf("no map file\n"); 123060089Seric return FALSE; 123156822Seric } 123256822Seric 123360089Seric #ifdef NEWDB 123460207Seric map->map_mflags |= MF_IMPL_HASH; 123560089Seric if (hash_map_open(map, mode)) 123656822Seric { 123764250Seric #if defined(NDBM) && defined(NIS) 123860561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 123960207Seric #endif 124060207Seric return TRUE; 124160089Seric } 124260207Seric else 124360207Seric map->map_mflags &= ~MF_IMPL_HASH; 124460089Seric #endif 124560089Seric #ifdef NDBM 124660207Seric map->map_mflags |= MF_IMPL_NDBM; 124760089Seric if (ndbm_map_open(map, mode)) 124860089Seric { 124960089Seric return TRUE; 125060089Seric } 125160207Seric else 125260207Seric map->map_mflags &= ~MF_IMPL_NDBM; 125360089Seric #endif 125456822Seric 125564650Seric #if defined(NEWDB) || defined(NDBM) 125660089Seric if (Verbose) 125760089Seric message("WARNING: cannot open alias database %s", map->map_file); 125864964Seric #else 125964964Seric if (mode != O_RDONLY) 126064964Seric usrerr("Cannot rebuild aliases: no database format defined"); 126160207Seric #endif 126260089Seric 126360207Seric return stab_map_open(map, mode); 126456822Seric } 126560089Seric 126660207Seric 126760089Seric /* 126860207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 126960089Seric */ 127060089Seric 127160089Seric void 127260207Seric impl_map_close(map) 127360089Seric MAP *map; 127460089Seric { 127560089Seric #ifdef NEWDB 127660207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 127760089Seric { 127860207Seric db_map_close(map); 127960207Seric map->map_mflags &= ~MF_IMPL_HASH; 128060089Seric } 128160089Seric #endif 128260089Seric 128360089Seric #ifdef NDBM 128460207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 128560089Seric { 128660207Seric ndbm_map_close(map); 128760207Seric map->map_mflags &= ~MF_IMPL_NDBM; 128860089Seric } 128960089Seric #endif 129060089Seric } 129160207Seric /* 129260207Seric ** NULL stubs 129360089Seric */ 129460089Seric 129560207Seric bool 129660207Seric null_map_open(map, mode) 129760089Seric MAP *map; 129860207Seric int mode; 129960089Seric { 130060207Seric return TRUE; 130160089Seric } 130260089Seric 130360207Seric void 130460207Seric null_map_close(map) 130560207Seric MAP *map; 130660089Seric { 130760207Seric return; 130860207Seric } 130960089Seric 131060207Seric void 131160207Seric null_map_store(map, key, val) 131260207Seric MAP *map; 131360207Seric char *key; 131460207Seric char *val; 131560089Seric { 131660207Seric return; 131760089Seric } 1318