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*64964Seric static char sccsid[] = "@(#)map.c 8.19 (Berkeley) 11/27/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 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; 31360537Seric stabapply(map_init, rebuild); 31464671Seric #ifdef XDEBUG 31564671Seric checkfd012("exiting initmaps"); 31664671Seric #endif 31760537Seric } 31860537Seric 31960537Seric void 32060537Seric map_init(s, rebuild) 32160537Seric register STAB *s; 32260537Seric int rebuild; 32360537Seric { 32460537Seric register MAP *map; 32560537Seric 32660537Seric /* has to be a map */ 32760537Seric if (s->s_type != ST_MAP) 32860537Seric return; 32960537Seric 33060537Seric map = &s->s_map; 33160537Seric if (!bitset(MF_VALID, map->map_mflags)) 33260537Seric return; 33360537Seric 33460537Seric if (tTd(38, 2)) 33560537Seric printf("map_init(%s:%s)\n", 33664690Seric map->map_class->map_cname == NULL ? "NULL" : 33764690Seric map->map_class->map_cname, 33864690Seric map->map_file == NULL ? "NULL" : map->map_file); 33960537Seric 34060537Seric /* if already open, close it (for nested open) */ 34160537Seric if (bitset(MF_OPEN, map->map_mflags)) 34260537Seric { 34360537Seric map->map_class->map_close(map); 34460537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 34560537Seric } 34660537Seric 34760537Seric if (rebuild) 34860537Seric { 34960926Seric if (bitset(MF_ALIAS, map->map_mflags) && 35060926Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 35160537Seric rebuildaliases(map, FALSE); 35260537Seric } 35360537Seric else 35460537Seric { 35560537Seric if (map->map_class->map_open(map, O_RDONLY)) 35660537Seric { 35760537Seric if (tTd(38, 4)) 35860537Seric printf("%s:%s: valid\n", 35964690Seric map->map_class->map_cname == NULL ? "NULL" : 36064690Seric map->map_class->map_cname, 36164690Seric map->map_file == NULL ? "NULL" : 36264690Seric map->map_file); 36360537Seric map->map_mflags |= MF_OPEN; 36460537Seric } 36560537Seric else if (tTd(38, 4)) 36660537Seric printf("%s:%s: invalid: %s\n", 36764690Seric map->map_class->map_cname == NULL ? "NULL" : 36864690Seric map->map_class->map_cname, 36964690Seric map->map_file == NULL ? "NULL" : 37064690Seric map->map_file, 37160537Seric errstring(errno)); 37260537Seric } 37360537Seric } 37460537Seric /* 37560089Seric ** NDBM modules 37660089Seric */ 37760089Seric 37860089Seric #ifdef NDBM 37960089Seric 38060089Seric /* 38160089Seric ** DBM_MAP_OPEN -- DBM-style map open 38260089Seric */ 38360089Seric 38460089Seric bool 38560089Seric ndbm_map_open(map, mode) 38660089Seric MAP *map; 38760089Seric int mode; 38860089Seric { 38964284Seric register DBM *dbm; 39064284Seric struct stat st; 39160089Seric 39260537Seric if (tTd(38, 2)) 39360089Seric printf("ndbm_map_open(%s, %d)\n", map->map_file, mode); 39460089Seric 39560207Seric if (mode == O_RDWR) 39660207Seric mode |= O_CREAT|O_TRUNC; 39760207Seric 39860089Seric /* open the database */ 39960089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 40056822Seric if (dbm == NULL) 40156822Seric { 40264718Seric #ifdef MAYBENEXTRELEASE 40364718Seric if (aliaswait(map, ".pag", FALSE)) 40464718Seric return TRUE; 40564718Seric #endif 40660207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 40756836Seric syserr("Cannot open DBM database %s", map->map_file); 40856822Seric return FALSE; 40956822Seric } 41060089Seric map->map_db1 = (void *) dbm; 411*64964Seric if (mode == O_RDONLY) 412*64964Seric { 413*64964Seric if (bitset(MF_ALIAS, map->map_mflags) && 414*64964Seric !aliaswait(map, ".pag", TRUE)) 41564718Seric return FALSE; 416*64964Seric } 417*64964Seric else 418*64964Seric { 419*64964Seric int fd; 420*64964Seric 421*64964Seric /* exclusive lock for duration of rebuild */ 422*64964Seric fd = dbm_dirfno((DBM *) map->map_db1); 423*64964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 424*64964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 425*64964Seric map->map_mflags |= MF_LOCKED; 426*64964Seric } 42764718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 42864284Seric map->map_mtime = st.st_mtime; 42956822Seric return TRUE; 43056822Seric } 43160089Seric 43260089Seric 43360089Seric /* 43456822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 43556822Seric */ 43656822Seric 43756822Seric char * 43860089Seric ndbm_map_lookup(map, name, av, statp) 43956822Seric MAP *map; 44060089Seric char *name; 44156822Seric char **av; 44259084Seric int *statp; 44356822Seric { 44456822Seric datum key, val; 44564373Seric int fd; 44660089Seric char keybuf[MAXNAME + 1]; 44756822Seric 44860537Seric if (tTd(38, 20)) 44960089Seric printf("ndbm_map_lookup(%s)\n", name); 45060089Seric 45160089Seric key.dptr = name; 45260089Seric key.dsize = strlen(name); 45360207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 45457014Seric { 45560089Seric if (key.dsize > sizeof keybuf - 1) 45660089Seric key.dsize = sizeof keybuf - 1; 45760089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 45860089Seric makelower(keybuf); 45960089Seric key.dptr = keybuf; 46057014Seric } 46164373Seric fd = dbm_dirfno((DBM *) map->map_db1); 46264388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 46364373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 46463753Seric val.dptr = NULL; 46563753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 46663753Seric { 46763753Seric val = dbm_fetch((DBM *) map->map_db1, key); 46863753Seric if (val.dptr != NULL) 46963753Seric map->map_mflags &= ~MF_TRY1NULL; 47063753Seric } 47163753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 47263753Seric { 47356822Seric key.dsize++; 47463753Seric val = dbm_fetch((DBM *) map->map_db1, key); 47563753Seric if (val.dptr != NULL) 47663753Seric map->map_mflags &= ~MF_TRY0NULL; 47763753Seric } 47864388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 47964373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 48056822Seric if (val.dptr == NULL) 48156822Seric return NULL; 48260207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 48363753Seric return map_rewrite(map, name, strlen(name), NULL); 48463753Seric else 48563753Seric return map_rewrite(map, val.dptr, val.dsize, av); 48656822Seric } 48756822Seric 48856822Seric 48956822Seric /* 49060089Seric ** DBM_MAP_STORE -- store a datum in the database 49156822Seric */ 49256822Seric 49360089Seric void 49460089Seric ndbm_map_store(map, lhs, rhs) 49560089Seric register MAP *map; 49660089Seric char *lhs; 49760089Seric char *rhs; 49860089Seric { 49960089Seric datum key; 50060089Seric datum data; 50160089Seric int stat; 50260089Seric 50360537Seric if (tTd(38, 12)) 50460089Seric printf("ndbm_map_store(%s, %s)\n", lhs, rhs); 50560089Seric 50660089Seric key.dsize = strlen(lhs); 50760089Seric key.dptr = lhs; 50860089Seric 50960089Seric data.dsize = strlen(rhs); 51060089Seric data.dptr = rhs; 51160089Seric 51260207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 51360089Seric { 51460089Seric key.dsize++; 51560089Seric data.dsize++; 51660089Seric } 51760089Seric 51860089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 51960089Seric if (stat > 0) 52060089Seric { 52160089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 52260089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 52360089Seric } 52460089Seric if (stat != 0) 52560089Seric syserr("readaliases: dbm put (%s)", lhs); 52660089Seric } 52760089Seric 52860089Seric 52960089Seric /* 53060207Seric ** NDBM_MAP_CLOSE -- close the database 53160089Seric */ 53260089Seric 53360089Seric void 53460089Seric ndbm_map_close(map) 53560089Seric register MAP *map; 53660089Seric { 53760207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 53860089Seric { 53964250Seric #ifdef NIS 54064075Seric bool inclnull; 54160089Seric char buf[200]; 54260089Seric 54364075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 54464075Seric map->map_mflags &= ~MF_INCLNULL; 54564075Seric 54660089Seric (void) sprintf(buf, "%010ld", curtime()); 54760089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 54860089Seric 54964941Seric (void) gethostname(buf, sizeof buf); 55060089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 55164075Seric 55264075Seric if (inclnull) 55364075Seric map->map_mflags |= MF_INCLNULL; 55460089Seric #endif 55560089Seric 55660089Seric /* write out the distinguished alias */ 55760089Seric ndbm_map_store(map, "@", "@"); 55860089Seric } 55960089Seric dbm_close((DBM *) map->map_db1); 56060089Seric } 56160089Seric 56260089Seric #endif 56360089Seric /* 56460582Seric ** NEWDB (Hash and BTree) Modules 56560089Seric */ 56660089Seric 56760089Seric #ifdef NEWDB 56860089Seric 56960089Seric /* 57060582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 57160582Seric ** 57260582Seric ** These do rather bizarre locking. If you can lock on open, 57360582Seric ** do that to avoid the condition of opening a database that 57460582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 57560582Seric ** there will be a race condition. If opening for read-only, 57660582Seric ** we immediately release the lock to avoid freezing things up. 57760582Seric ** We really ought to hold the lock, but guarantee that we won't 57860582Seric ** be pokey about it. That's hard to do. 57960089Seric */ 58060089Seric 58156822Seric bool 58260089Seric bt_map_open(map, mode) 58356822Seric MAP *map; 58460089Seric int mode; 58556822Seric { 58656822Seric DB *db; 58760228Seric int i; 58860582Seric int omode; 58964373Seric int fd; 59064284Seric struct stat st; 59160089Seric char buf[MAXNAME]; 59256822Seric 59360537Seric if (tTd(38, 2)) 59460089Seric printf("bt_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; 60064035Seric #if defined(O_EXLOCK) && defined(HASFLOCK) 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_BTREE, NULL); 61656822Seric if (db == NULL) 61756822Seric { 61864718Seric #ifdef MAYBENEXTRELEASE 61964718Seric if (aliaswait(map, ".db", FALSE)) 62064718Seric return TRUE; 62164718Seric #endif 62260207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 62356836Seric syserr("Cannot open BTREE database %s", map->map_file); 62456822Seric return FALSE; 62556822Seric } 62664035Seric #if !defined(OLD_NEWDB) && defined(HASFLOCK) 62764373Seric fd = db->fd(db); 62860582Seric # if !defined(O_EXLOCK) 62964373Seric if (mode == O_RDWR && fd >= 0) 63064388Seric { 63164388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 63264388Seric map->map_mflags |= MF_LOCKED; 63364388Seric } 63460582Seric # else 63564373Seric if (mode == O_RDONLY && fd >= 0) 63664373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 63764388Seric else 63864388Seric map->map_mflags |= MF_LOCKED; 63960582Seric # endif 64060582Seric #endif 64160585Seric 64260585Seric /* try to make sure that at least the database header is on disk */ 64360585Seric if (mode == O_RDWR) 64464373Seric #ifdef OLD_NEWDB 64564373Seric (void) db->sync(db); 64664373Seric #else 64760585Seric (void) db->sync(db, 0); 64860585Seric 64964373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 65064284Seric map->map_mtime = st.st_mtime; 65164284Seric #endif 65264284Seric 65360089Seric map->map_db2 = (void *) db; 65460207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 65564718Seric if (!aliaswait(map, ".db", TRUE)) 65664718Seric return FALSE; 65756822Seric return TRUE; 65856822Seric } 65956822Seric 66056822Seric 66156822Seric /* 66256822Seric ** HASH_MAP_INIT -- HASH-style map initialization 66356822Seric */ 66456822Seric 66556822Seric bool 66660089Seric hash_map_open(map, mode) 66756822Seric MAP *map; 66860089Seric int mode; 66956822Seric { 67056822Seric DB *db; 67160228Seric int i; 67260582Seric int omode; 67364373Seric int fd; 67464284Seric struct stat st; 67560089Seric char buf[MAXNAME]; 67656822Seric 67760537Seric if (tTd(38, 2)) 67860089Seric printf("hash_map_open(%s, %d)\n", map->map_file, mode); 67960089Seric 68060582Seric omode = mode; 68160582Seric if (omode == O_RDWR) 68260582Seric { 68360582Seric omode |= O_CREAT|O_TRUNC; 68464035Seric #if defined(O_EXLOCK) && defined(HASFLOCK) 68560582Seric omode |= O_EXLOCK; 68660582Seric # if !defined(OLD_NEWDB) 68760582Seric } 68860582Seric else 68960582Seric { 69060582Seric omode |= O_SHLOCK; 69160582Seric # endif 69260582Seric #endif 69360582Seric } 69460207Seric 69560228Seric (void) strcpy(buf, map->map_file); 69660228Seric i = strlen(buf); 69760228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 69860228Seric (void) strcat(buf, ".db"); 69960582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 70056822Seric if (db == NULL) 70156822Seric { 70264718Seric #ifdef MAYBENEXTRELEASE 70364718Seric if (aliaswait(map, ".db", FALSE)) 70464718Seric return TRUE; 70564718Seric #endif 70660207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 70756836Seric syserr("Cannot open HASH database %s", map->map_file); 70856822Seric return FALSE; 70956822Seric } 71064035Seric #if !defined(OLD_NEWDB) && defined(HASFLOCK) 71164373Seric fd = db->fd(db); 71260582Seric # if !defined(O_EXLOCK) 71364373Seric if (mode == O_RDWR && fd >= 0) 71464388Seric { 71564388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 71664388Seric map->map_mflags |= MF_LOCKED; 71764388Seric } 71860582Seric # else 71964373Seric if (mode == O_RDONLY && fd >= 0) 72064373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 72164388Seric else 72264388Seric map->map_mflags |= MF_LOCKED; 72360582Seric # endif 72460582Seric #endif 72560585Seric 72660585Seric /* try to make sure that at least the database header is on disk */ 72760585Seric if (mode == O_RDWR) 72864373Seric #ifdef OLD_NEWDB 72964373Seric (void) db->sync(db); 73064373Seric #else 73160585Seric (void) db->sync(db, 0); 73260585Seric 73364373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 73464284Seric map->map_mtime = st.st_mtime; 73564284Seric #endif 73664284Seric 73760089Seric map->map_db2 = (void *) db; 73860207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 73964718Seric if (!aliaswait(map, ".db", TRUE)) 74064718Seric return FALSE; 74156822Seric return TRUE; 74256822Seric } 74356822Seric 74456822Seric 74556822Seric /* 74656822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 74756822Seric */ 74856822Seric 74956822Seric char * 75060089Seric db_map_lookup(map, name, av, statp) 75156822Seric MAP *map; 75260089Seric char *name; 75356822Seric char **av; 75459084Seric int *statp; 75556822Seric { 75656822Seric DBT key, val; 75760422Seric register DB *db = (DB *) map->map_db2; 75860422Seric int st; 75960422Seric int saveerrno; 76064373Seric int fd; 76160089Seric char keybuf[MAXNAME + 1]; 76256822Seric 76360537Seric if (tTd(38, 20)) 76460089Seric printf("db_map_lookup(%s)\n", name); 76560089Seric 76660089Seric key.size = strlen(name); 76760089Seric if (key.size > sizeof keybuf - 1) 76860089Seric key.size = sizeof keybuf - 1; 76960089Seric key.data = keybuf; 77060089Seric bcopy(name, keybuf, key.size + 1); 77160207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 77260089Seric makelower(keybuf); 77360422Seric #ifndef OLD_NEWDB 77464388Seric fd = db->fd(db); 77564388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 77664388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 77760422Seric #endif 77863753Seric st = 1; 77963753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 78063753Seric { 78163753Seric st = db->get(db, &key, &val, 0); 78263753Seric if (st == 0) 78363753Seric map->map_mflags &= ~MF_TRY1NULL; 78463753Seric } 78563753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 78663753Seric { 78763753Seric key.size++; 78863753Seric st = db->get(db, &key, &val, 0); 78963753Seric if (st == 0) 79063753Seric map->map_mflags &= ~MF_TRY0NULL; 79163753Seric } 79260422Seric saveerrno = errno; 79360422Seric #ifndef OLD_NEWDB 79464388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 79564373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 79660422Seric #endif 79760422Seric if (st != 0) 79860422Seric { 79960422Seric errno = saveerrno; 80060422Seric if (st < 0) 80160422Seric syserr("db_map_lookup: get (%s)", name); 80256822Seric return NULL; 80360422Seric } 80460207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 80563753Seric return map_rewrite(map, name, strlen(name), NULL); 80663753Seric else 80763753Seric return map_rewrite(map, val.data, val.size, av); 80856822Seric } 80956822Seric 81060089Seric 81160089Seric /* 81260089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 81356822Seric */ 81456822Seric 81560089Seric void 81660089Seric db_map_store(map, lhs, rhs) 81760089Seric register MAP *map; 81860089Seric char *lhs; 81960089Seric char *rhs; 82056822Seric { 82160089Seric int stat; 82260089Seric DBT key; 82360089Seric DBT data; 82460089Seric register DB *db = map->map_db2; 82556822Seric 82660537Seric if (tTd(38, 20)) 82760089Seric printf("db_map_store(%s, %s)\n", lhs, rhs); 82860089Seric 82960089Seric key.size = strlen(lhs); 83060089Seric key.data = lhs; 83160089Seric 83260089Seric data.size = strlen(rhs); 83360089Seric data.data = rhs; 83460089Seric 83560207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 83656822Seric { 83760089Seric key.size++; 83860089Seric data.size++; 83960089Seric } 84056836Seric 84160089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 84260089Seric if (stat > 0) 84360089Seric { 84460089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 84560089Seric stat = db->put(db, &key, &data, 0); 84660089Seric } 84760089Seric if (stat != 0) 84860089Seric syserr("readaliases: db put (%s)", lhs); 84960089Seric } 85056836Seric 85156847Seric 85260089Seric /* 85360089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 85460089Seric */ 85560089Seric 85660089Seric void 85760089Seric db_map_close(map) 85860089Seric MAP *map; 85960089Seric { 86060089Seric register DB *db = map->map_db2; 86160089Seric 86260537Seric if (tTd(38, 9)) 86360207Seric printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags); 86460089Seric 86560207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 86658804Seric { 86760089Seric /* write out the distinguished alias */ 86860089Seric db_map_store(map, "@", "@"); 86958804Seric } 87058963Seric 87160089Seric if (db->close(db) != 0) 87260089Seric syserr("readaliases: db close failure"); 87356822Seric } 87457208Seric 87560089Seric #endif 87660089Seric /* 87760089Seric ** NIS Modules 87860089Seric */ 87960089Seric 88060089Seric # ifdef NIS 88160089Seric 88264369Seric # ifndef YPERR_BUSY 88364369Seric # define YPERR_BUSY 16 88464369Seric # endif 88564369Seric 88657208Seric /* 88760089Seric ** NIS_MAP_OPEN -- open DBM map 88857208Seric */ 88957208Seric 89057208Seric bool 89160089Seric nis_map_open(map, mode) 89257208Seric MAP *map; 89360089Seric int mode; 89457208Seric { 89557216Seric int yperr; 89660215Seric register char *p; 89760215Seric auto char *vp; 89860215Seric auto int vsize; 89957216Seric char *master; 90057216Seric 90160537Seric if (tTd(38, 2)) 90260089Seric printf("nis_map_open(%s)\n", map->map_file); 90360089Seric 90460207Seric if (mode != O_RDONLY) 90560207Seric { 90664650Seric /* issue a pseudo-error message */ 90764650Seric #ifdef ENOSYS 90864650Seric errno = ENOSYS; 90964650Seric #else 91064650Seric # ifdef EFTYPE 91164650Seric errno = EFTYPE; 91264650Seric # else 91364650Seric errno = ENXIO; 91464650Seric # endif 91564650Seric #endif 91660207Seric return FALSE; 91760207Seric } 91860207Seric 91960089Seric p = strchr(map->map_file, '@'); 92060089Seric if (p != NULL) 92160089Seric { 92260089Seric *p++ = '\0'; 92360089Seric if (*p != '\0') 92460089Seric map->map_domain = p; 92560089Seric } 92660215Seric 92760089Seric if (map->map_domain == NULL) 92860089Seric yp_get_default_domain(&map->map_domain); 92960089Seric 93060089Seric if (*map->map_file == '\0') 93160089Seric map->map_file = "mail.aliases"; 93260089Seric 93360215Seric /* check to see if this map actually exists */ 93460089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 93560089Seric &vp, &vsize); 93660537Seric if (tTd(38, 10)) 93760089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 93860089Seric map->map_domain, map->map_file, yperr_string(yperr)); 93960089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 94060089Seric return TRUE; 94160215Seric 94260215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 94360215Seric syserr("Cannot bind to domain %s: %s", map->map_domain, 94460215Seric yperr_string(yperr)); 94560215Seric 94660089Seric return FALSE; 94760089Seric } 94860089Seric 94960089Seric 95060089Seric /* 95157208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 95257208Seric */ 95357208Seric 95457208Seric char * 95560089Seric nis_map_lookup(map, name, av, statp) 95657208Seric MAP *map; 95760089Seric char *name; 95857208Seric char **av; 95959084Seric int *statp; 96057208Seric { 96157208Seric char *vp; 96257642Seric auto int vsize; 96359274Seric int buflen; 96460215Seric int yperr; 96560089Seric char keybuf[MAXNAME + 1]; 96657208Seric 96760537Seric if (tTd(38, 20)) 96860089Seric printf("nis_map_lookup(%s)\n", name); 96960089Seric 97060089Seric buflen = strlen(name); 97160089Seric if (buflen > sizeof keybuf - 1) 97260089Seric buflen = sizeof keybuf - 1; 97360089Seric bcopy(name, keybuf, buflen + 1); 97460207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 97560089Seric makelower(keybuf); 97663753Seric yperr = YPERR_KEY; 97763753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 97863753Seric { 97963753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 98063753Seric &vp, &vsize); 98163753Seric if (yperr == 0) 98263753Seric map->map_mflags &= ~MF_TRY1NULL; 98363753Seric } 98463753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 98563753Seric { 98659274Seric buflen++; 98763753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 98863753Seric &vp, &vsize); 98963753Seric if (yperr == 0) 99063753Seric map->map_mflags &= ~MF_TRY0NULL; 99163753Seric } 99260089Seric if (yperr != 0) 99360089Seric { 99460089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 99560215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 99657208Seric return NULL; 99760089Seric } 99860207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 99963753Seric return map_rewrite(map, name, strlen(name), NULL); 100063753Seric else 100163753Seric return map_rewrite(map, vp, vsize, av); 100257208Seric } 100357208Seric 100460089Seric 100560089Seric /* 100660207Seric ** NIS_MAP_STORE 100760089Seric */ 100860089Seric 100960089Seric void 101060089Seric nis_map_store(map, lhs, rhs) 101160089Seric MAP *map; 101260089Seric char *lhs; 101360089Seric char *rhs; 101460089Seric { 101560089Seric /* nothing */ 101660089Seric } 101760089Seric 101860089Seric 101960089Seric /* 102060207Seric ** NIS_MAP_CLOSE 102160089Seric */ 102260089Seric 102360089Seric void 102460089Seric nis_map_close(map) 102560089Seric MAP *map; 102660089Seric { 102760089Seric /* nothing */ 102860089Seric } 102960089Seric 103060089Seric #endif /* NIS */ 103157208Seric /* 103260089Seric ** STAB (Symbol Table) Modules 103360089Seric */ 103460089Seric 103560089Seric 103660089Seric /* 103760207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 103860089Seric */ 103960089Seric 104060089Seric char * 104161707Seric stab_map_lookup(map, name, av, pstat) 104260089Seric register MAP *map; 104360089Seric char *name; 104461707Seric char **av; 104561707Seric int *pstat; 104660089Seric { 104760089Seric register STAB *s; 104860089Seric 104960537Seric if (tTd(38, 20)) 105060089Seric printf("stab_lookup(%s)\n", name); 105160089Seric 105260089Seric s = stab(name, ST_ALIAS, ST_FIND); 105360089Seric if (s != NULL) 105460089Seric return (s->s_alias); 105560089Seric return (NULL); 105660089Seric } 105760089Seric 105860089Seric 105960089Seric /* 106060207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 106160089Seric */ 106260089Seric 106360089Seric void 106460089Seric stab_map_store(map, lhs, rhs) 106560089Seric register MAP *map; 106660089Seric char *lhs; 106760089Seric char *rhs; 106860089Seric { 106960089Seric register STAB *s; 107060089Seric 107160089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 107260089Seric s->s_alias = newstr(rhs); 107360089Seric } 107460089Seric 107560089Seric 107660089Seric /* 107760207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 107860207Seric ** 107960207Seric ** This is a wierd case -- it is only intended as a fallback for 108060207Seric ** aliases. For this reason, opens for write (only during a 108160207Seric ** "newaliases") always fails, and opens for read open the 108260207Seric ** actual underlying text file instead of the database. 108360089Seric */ 108460089Seric 108560089Seric bool 108660089Seric stab_map_open(map, mode) 108760089Seric register MAP *map; 108860089Seric int mode; 108960089Seric { 109063835Seric FILE *af; 109164284Seric struct stat st; 109263835Seric 109360537Seric if (tTd(38, 2)) 109460089Seric printf("stab_map_open(%s)\n", map->map_file); 109560089Seric 109660089Seric if (mode != O_RDONLY) 109760207Seric { 109860207Seric errno = ENODEV; 109960089Seric return FALSE; 110060207Seric } 110160089Seric 110263835Seric af = fopen(map->map_file, "r"); 110363835Seric if (af == NULL) 110463835Seric return FALSE; 110563835Seric readaliases(map, af, TRUE); 110664284Seric 110764284Seric if (fstat(fileno(af), &st) >= 0) 110864284Seric map->map_mtime = st.st_mtime; 110963835Seric fclose(af); 111063835Seric 111160089Seric return TRUE; 111260089Seric } 111360089Seric 111460089Seric 111560089Seric /* 111664642Seric ** STAB_MAP_CLOSE -- close symbol table. 111764642Seric ** 111864642Seric ** Since this is in memory, there is nothing to do. 111960089Seric */ 112060089Seric 112160089Seric void 112260089Seric stab_map_close(map) 112360089Seric MAP *map; 112460089Seric { 112560089Seric /* ignore it */ 112660089Seric } 112760089Seric /* 112860089Seric ** Implicit Modules 112956822Seric ** 113060089Seric ** Tries several types. For back compatibility of aliases. 113156822Seric */ 113256822Seric 113360089Seric 113460089Seric /* 113560207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 113660089Seric */ 113760089Seric 113860089Seric char * 113960089Seric impl_map_lookup(map, name, av, pstat) 114060089Seric MAP *map; 114160089Seric char *name; 114256822Seric char **av; 114360089Seric int *pstat; 114456822Seric { 114560537Seric if (tTd(38, 20)) 114660089Seric printf("impl_map_lookup(%s)\n", name); 114756822Seric 114860089Seric #ifdef NEWDB 114960207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 115060089Seric return db_map_lookup(map, name, av, pstat); 115160089Seric #endif 115260089Seric #ifdef NDBM 115360207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 115460089Seric return ndbm_map_lookup(map, name, av, pstat); 115560089Seric #endif 115660089Seric return stab_map_lookup(map, name, av, pstat); 115760089Seric } 115860089Seric 115960089Seric /* 116060207Seric ** IMPL_MAP_STORE -- store in open databases 116160089Seric */ 116260089Seric 116360089Seric void 116460089Seric impl_map_store(map, lhs, rhs) 116560089Seric MAP *map; 116660089Seric char *lhs; 116760089Seric char *rhs; 116860089Seric { 116960089Seric #ifdef NEWDB 117060207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 117160089Seric db_map_store(map, lhs, rhs); 117260089Seric #endif 117360089Seric #ifdef NDBM 117460207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 117560089Seric ndbm_map_store(map, lhs, rhs); 117660089Seric #endif 117760089Seric stab_map_store(map, lhs, rhs); 117860089Seric } 117960089Seric 118060089Seric /* 118160089Seric ** IMPL_MAP_OPEN -- implicit database open 118260089Seric */ 118360089Seric 118460089Seric bool 118560089Seric impl_map_open(map, mode) 118660089Seric MAP *map; 118760089Seric int mode; 118860089Seric { 118960089Seric struct stat stb; 119060089Seric 119160537Seric if (tTd(38, 2)) 119264718Seric printf("impl_map_open(%s, %d)\n", map->map_file, mode); 119360089Seric 119460089Seric if (stat(map->map_file, &stb) < 0) 119556822Seric { 119660089Seric /* no alias file at all */ 119764718Seric if (tTd(38, 3)) 119864718Seric printf("no map file\n"); 119960089Seric return FALSE; 120056822Seric } 120156822Seric 120260089Seric #ifdef NEWDB 120360207Seric map->map_mflags |= MF_IMPL_HASH; 120460089Seric if (hash_map_open(map, mode)) 120556822Seric { 120664250Seric #if defined(NDBM) && defined(NIS) 120760561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 120860207Seric #endif 120960207Seric return TRUE; 121060089Seric } 121160207Seric else 121260207Seric map->map_mflags &= ~MF_IMPL_HASH; 121360089Seric #endif 121460089Seric #ifdef NDBM 121560207Seric map->map_mflags |= MF_IMPL_NDBM; 121660089Seric if (ndbm_map_open(map, mode)) 121760089Seric { 121860089Seric return TRUE; 121960089Seric } 122060207Seric else 122160207Seric map->map_mflags &= ~MF_IMPL_NDBM; 122260089Seric #endif 122356822Seric 122464650Seric #if defined(NEWDB) || defined(NDBM) 122560089Seric if (Verbose) 122660089Seric message("WARNING: cannot open alias database %s", map->map_file); 1227*64964Seric #else 1228*64964Seric if (mode != O_RDONLY) 1229*64964Seric usrerr("Cannot rebuild aliases: no database format defined"); 123060207Seric #endif 123160089Seric 123260207Seric return stab_map_open(map, mode); 123356822Seric } 123460089Seric 123560207Seric 123660089Seric /* 123760207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 123860089Seric */ 123960089Seric 124060089Seric void 124160207Seric impl_map_close(map) 124260089Seric MAP *map; 124360089Seric { 124460089Seric #ifdef NEWDB 124560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 124660089Seric { 124760207Seric db_map_close(map); 124860207Seric map->map_mflags &= ~MF_IMPL_HASH; 124960089Seric } 125060089Seric #endif 125160089Seric 125260089Seric #ifdef NDBM 125360207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 125460089Seric { 125560207Seric ndbm_map_close(map); 125660207Seric map->map_mflags &= ~MF_IMPL_NDBM; 125760089Seric } 125860089Seric #endif 125960089Seric } 126060207Seric /* 126160207Seric ** NULL stubs 126260089Seric */ 126360089Seric 126460207Seric bool 126560207Seric null_map_open(map, mode) 126660089Seric MAP *map; 126760207Seric int mode; 126860089Seric { 126960207Seric return TRUE; 127060089Seric } 127160089Seric 127260207Seric void 127360207Seric null_map_close(map) 127460207Seric MAP *map; 127560089Seric { 127660207Seric return; 127760207Seric } 127860089Seric 127960207Seric void 128060207Seric null_map_store(map, key, val) 128160207Seric MAP *map; 128260207Seric char *key; 128360207Seric char *val; 128460089Seric { 128560207Seric return; 128660089Seric } 1287