156822Seric /* 256822Seric * Copyright (c) 1992 Eric P. Allman. 356822Seric * Copyright (c) 1992 Regents of the University of California. 456822Seric * All rights reserved. 556822Seric * 656822Seric * %sccs.include.redist.c% 756822Seric */ 856822Seric 956822Seric #ifndef lint 10*60492Seric static char sccsid[] = "@(#)map.c 6.21 (Berkeley) 05/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 6260089Seric /* 6360089Seric ** MAP_PARSEARGS -- parse config line arguments for database lookup 6460089Seric ** 6560089Seric ** This is a generic version of the map_parse method. 6660089Seric ** 6756822Seric ** Parameters: 6860089Seric ** map -- the map being initialized. 6960089Seric ** ap -- a pointer to the args on the config line. 7056822Seric ** 7156822Seric ** Returns: 7260089Seric ** TRUE -- if everything parsed OK. 7356822Seric ** FALSE -- otherwise. 7456822Seric ** 7556822Seric ** Side Effects: 7660089Seric ** null terminates the filename; stores it in map 7756822Seric */ 7856822Seric 7956822Seric bool 8060089Seric map_parseargs(map, ap) 8156822Seric MAP *map; 8260089Seric char *ap; 8356822Seric { 8460089Seric register char *p = ap; 8556822Seric 8660089Seric for (;;) 8760089Seric { 8860089Seric while (isascii(*p) && isspace(*p)) 8960089Seric p++; 9060089Seric if (*p != '-') 9160089Seric break; 9260089Seric switch (*++p) 9360089Seric { 9460089Seric case 'N': 9560207Seric map->map_mflags |= MF_INCLNULL; 9660089Seric break; 9760089Seric 9860089Seric case 'o': 9960207Seric map->map_mflags |= MF_OPTIONAL; 10060089Seric break; 10160089Seric 10260089Seric case 'f': 10360207Seric map->map_mflags |= MF_NOFOLDCASE; 10460089Seric break; 10560089Seric 10660089Seric case 'm': 10760207Seric map->map_mflags |= MF_MATCHONLY; 10860089Seric break; 10960089Seric 11060089Seric case 'a': 11160089Seric map->map_app = ++p; 11260089Seric break; 11360089Seric } 11460089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 11560089Seric p++; 11660089Seric if (*p != '\0') 11760089Seric *p++ = '\0'; 11860089Seric } 11960089Seric if (map->map_app != NULL) 12060089Seric map->map_app = newstr(map->map_app); 12160089Seric 12260089Seric if (*p != '\0') 12360089Seric { 12460089Seric map->map_file = p; 12560089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 12660089Seric p++; 12760089Seric if (*p != '\0') 12860089Seric *p++ = '\0'; 12960089Seric map->map_file = newstr(map->map_file); 13060089Seric } 13160089Seric 13260089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 13360089Seric p++; 13460089Seric if (*p != '\0') 13560089Seric map->map_rebuild = newstr(p); 13660089Seric 13756822Seric if (map->map_file == NULL) 13857208Seric { 13960089Seric syserr("No file name for %s map %s", 14060089Seric map->map_class->map_cname, map->map_mname); 14156822Seric return FALSE; 14257208Seric } 14360089Seric return TRUE; 14460089Seric } 14560089Seric /* 14660089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 14760089Seric ** 14860089Seric ** It also adds the map_app string. It can be used as a utility 14960089Seric ** in the map_lookup method. 15060089Seric ** 15160089Seric ** Parameters: 15260089Seric ** map -- the map that causes this. 15360089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 15460089Seric ** slen -- the length of s. 15560089Seric ** av -- arguments to interpolate into buf. 15660089Seric ** 15760089Seric ** Returns: 15860089Seric ** Pointer to rewritten result. 15960089Seric ** 16060089Seric ** Side Effects: 16160089Seric ** none. 16260089Seric */ 16360089Seric 164*60492Seric struct rwbuf 165*60492Seric { 166*60492Seric int rwb_len; /* size of buffer */ 167*60492Seric char *rwb_buf; /* ptr to buffer */ 168*60492Seric }; 169*60492Seric 170*60492Seric struct rwbuf RwBufs[2]; /* buffers for rewriting output */ 171*60492Seric 17260089Seric char * 17360089Seric map_rewrite(map, s, slen, av) 17460089Seric register MAP *map; 17560089Seric register char *s; 17660089Seric int slen; 17760089Seric char **av; 17860089Seric { 17960089Seric register char *bp; 18060089Seric register char c; 18160089Seric char **avp; 18260089Seric register char *ap; 183*60492Seric register struct rwbuf *rwb; 18460089Seric int i; 18560089Seric int len; 18660089Seric 18760089Seric if (tTd(23, 1)) 18860089Seric { 18960256Seric printf("map_rewrite(%.*s), av =", slen, s); 19060256Seric if (av == NULL) 19160256Seric printf(" (nullv)"); 19260256Seric else 19360256Seric { 19460256Seric for (avp = av; *avp != NULL; avp++) 19560256Seric printf("\n\t%s", *avp); 19660256Seric } 19760256Seric printf("\n"); 19860089Seric } 19960089Seric 200*60492Seric rwb = RwBufs; 201*60492Seric if (av == NULL) 202*60492Seric rwb++; 203*60492Seric 20460089Seric /* count expected size of output (can safely overestimate) */ 20560089Seric i = len = slen; 20660089Seric if (av != NULL) 20760089Seric { 20860089Seric bp = s; 20960089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 21060089Seric { 21160089Seric if (c != '%') 21260089Seric continue; 21360089Seric if (--i < 0) 21460089Seric break; 21560089Seric c = *bp++; 21660089Seric if (!(isascii(c) && isdigit(c))) 21760089Seric continue; 21860089Seric c -= 0; 21960089Seric for (avp = av; --c >= 0 && *avp != NULL; avp++) 22060089Seric continue; 22160089Seric if (*avp == NULL) 22260089Seric continue; 22360089Seric len += strlen(*avp); 22460089Seric } 22560089Seric } 22660089Seric if (map->map_app != NULL) 22760089Seric len += strlen(map->map_app); 228*60492Seric if (rwb->rwb_len < ++len) 22960089Seric { 23060089Seric /* need to malloc additional space */ 231*60492Seric rwb->rwb_len = len; 232*60492Seric if (rwb->rwb_buf != NULL) 233*60492Seric free(rwb->rwb_buf); 234*60492Seric rwb->rwb_buf = xalloc(rwb->rwb_len); 23560089Seric } 23660089Seric 237*60492Seric bp = rwb->rwb_buf; 23860089Seric if (av == NULL) 23960089Seric { 24060089Seric bcopy(s, bp, slen); 24160089Seric bp += slen; 24260089Seric } 24360089Seric else 24460089Seric { 24560089Seric while (--slen >= 0 && (c = *s++) != '\0') 24660089Seric { 24760089Seric if (c != '%') 24860089Seric { 24960089Seric pushc: 25060089Seric *bp++ = c; 25160089Seric continue; 25260089Seric } 25360089Seric if (--slen < 0 || (c = *s++) == '\0') 25460089Seric c = '%'; 25560089Seric if (c == '%') 25660089Seric goto pushc; 25760089Seric if (!(isascii(c) && isdigit(c))) 25860089Seric { 25960089Seric *bp++ = '%'; 26060089Seric goto pushc; 26160089Seric } 26260089Seric c -= '0'; 26360089Seric for (avp = av; --c >= 0 && *avp != NULL; avp++) 26460089Seric continue; 26560089Seric if (*avp == NULL) 26660089Seric continue; 26760089Seric 26860089Seric /* transliterate argument into output string */ 26960089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 27060089Seric *bp++ = c; 27160089Seric } 27260089Seric } 27360089Seric if (map->map_app != NULL) 27460089Seric strcpy(bp, map->map_app); 27560089Seric else 27660089Seric *bp = '\0'; 27760089Seric if (tTd(23, 1)) 278*60492Seric printf("map_rewrite => %s\n", rwb->rwb_buf); 279*60492Seric return rwb->rwb_buf; 28060089Seric } 28160089Seric /* 28260089Seric ** NDBM modules 28360089Seric */ 28460089Seric 28560089Seric #ifdef NDBM 28660089Seric 28760089Seric /* 28860089Seric ** DBM_MAP_OPEN -- DBM-style map open 28960089Seric */ 29060089Seric 29160089Seric bool 29260089Seric ndbm_map_open(map, mode) 29360089Seric MAP *map; 29460089Seric int mode; 29560089Seric { 29660089Seric DBM *dbm; 29760089Seric 29860089Seric if (tTd(27, 2)) 29960089Seric printf("ndbm_map_open(%s, %d)\n", map->map_file, mode); 30060089Seric 30160207Seric if (mode == O_RDWR) 30260207Seric mode |= O_CREAT|O_TRUNC; 30360207Seric 30460089Seric /* open the database */ 30560089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 30656822Seric if (dbm == NULL) 30756822Seric { 30860207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 30956836Seric syserr("Cannot open DBM database %s", map->map_file); 31056822Seric return FALSE; 31156822Seric } 31260089Seric map->map_db1 = (void *) dbm; 31360207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 31460207Seric aliaswait(map, ".dir"); 31556822Seric return TRUE; 31656822Seric } 31760089Seric 31860089Seric 31960089Seric /* 32056822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 32156822Seric */ 32256822Seric 32356822Seric char * 32460089Seric ndbm_map_lookup(map, name, av, statp) 32556822Seric MAP *map; 32660089Seric char *name; 32756822Seric char **av; 32859084Seric int *statp; 32956822Seric { 33056822Seric datum key, val; 33160089Seric char keybuf[MAXNAME + 1]; 33256822Seric 33360089Seric if (tTd(27, 20)) 33460089Seric printf("ndbm_map_lookup(%s)\n", name); 33560089Seric 33660089Seric key.dptr = name; 33760089Seric key.dsize = strlen(name); 33860207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 33957014Seric { 34060089Seric if (key.dsize > sizeof keybuf - 1) 34160089Seric key.dsize = sizeof keybuf - 1; 34260089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 34360089Seric makelower(keybuf); 34460089Seric key.dptr = keybuf; 34557014Seric } 34660207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 34756822Seric key.dsize++; 34860089Seric (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH); 34960089Seric val = dbm_fetch((DBM *) map->map_db1, key); 35060089Seric (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN); 35156822Seric if (val.dptr == NULL) 35256822Seric return NULL; 35360207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 35460089Seric av = NULL; 35560089Seric return map_rewrite(map, val.dptr, val.dsize, av); 35656822Seric } 35756822Seric 35856822Seric 35956822Seric /* 36060089Seric ** DBM_MAP_STORE -- store a datum in the database 36156822Seric */ 36256822Seric 36360089Seric void 36460089Seric ndbm_map_store(map, lhs, rhs) 36560089Seric register MAP *map; 36660089Seric char *lhs; 36760089Seric char *rhs; 36860089Seric { 36960089Seric datum key; 37060089Seric datum data; 37160089Seric int stat; 37260089Seric 37360089Seric if (tTd(27, 12)) 37460089Seric printf("ndbm_map_store(%s, %s)\n", lhs, rhs); 37560089Seric 37660089Seric key.dsize = strlen(lhs); 37760089Seric key.dptr = lhs; 37860089Seric 37960089Seric data.dsize = strlen(rhs); 38060089Seric data.dptr = rhs; 38160089Seric 38260207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 38360089Seric { 38460089Seric key.dsize++; 38560089Seric data.dsize++; 38660089Seric } 38760089Seric 38860089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 38960089Seric if (stat > 0) 39060089Seric { 39160089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 39260089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 39360089Seric } 39460089Seric if (stat != 0) 39560089Seric syserr("readaliases: dbm put (%s)", lhs); 39660089Seric } 39760089Seric 39860089Seric 39960089Seric /* 40060207Seric ** NDBM_MAP_CLOSE -- close the database 40160089Seric */ 40260089Seric 40360089Seric void 40460089Seric ndbm_map_close(map) 40560089Seric register MAP *map; 40660089Seric { 40760207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 40860089Seric { 40960089Seric #ifdef YPCOMPAT 41060089Seric char buf[200]; 41160089Seric 41260089Seric (void) sprintf(buf, "%010ld", curtime()); 41360089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 41460089Seric 41560089Seric (void) myhostname(buf, sizeof buf); 41660089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 41760089Seric #endif 41860089Seric 41960089Seric /* write out the distinguished alias */ 42060089Seric ndbm_map_store(map, "@", "@"); 42160089Seric } 42260089Seric dbm_close((DBM *) map->map_db1); 42360089Seric } 42460089Seric 42560089Seric #endif 42660089Seric /* 42760089Seric ** HASH (NEWDB) Modules 42860089Seric */ 42960089Seric 43060089Seric #ifdef NEWDB 43160089Seric 43260089Seric /* 43360089Seric ** BTREE_MAP_PARSE -- BTREE-style map initialization 43460089Seric */ 43560089Seric 43656822Seric bool 43760089Seric bt_map_open(map, mode) 43856822Seric MAP *map; 43960089Seric int mode; 44056822Seric { 44156822Seric DB *db; 44260228Seric int i; 44360089Seric char buf[MAXNAME]; 44456822Seric 44560089Seric if (tTd(27, 2)) 44660089Seric printf("bt_map_open(%s, %d)\n", map->map_file, mode); 44760089Seric 44860207Seric if (mode == O_RDWR) 44960207Seric mode |= O_CREAT|O_TRUNC; 45060207Seric 45160228Seric (void) strcpy(buf, map->map_file); 45260228Seric i = strlen(buf); 45360228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 45460228Seric (void) strcat(buf, ".db"); 45560222Seric db = dbopen(buf, mode, DBMMODE, DB_BTREE, NULL); 45656822Seric if (db == NULL) 45756822Seric { 45860207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 45956836Seric syserr("Cannot open BTREE database %s", map->map_file); 46056822Seric return FALSE; 46156822Seric } 46260089Seric map->map_db2 = (void *) db; 46360207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 46460207Seric aliaswait(map, ".db"); 46556822Seric return TRUE; 46656822Seric } 46756822Seric 46856822Seric 46956822Seric /* 47056822Seric ** HASH_MAP_INIT -- HASH-style map initialization 47156822Seric */ 47256822Seric 47356822Seric bool 47460089Seric hash_map_open(map, mode) 47556822Seric MAP *map; 47660089Seric int mode; 47756822Seric { 47856822Seric DB *db; 47960228Seric int i; 48060089Seric char buf[MAXNAME]; 48156822Seric 48260089Seric if (tTd(27, 2)) 48360089Seric printf("hash_map_open(%s, %d)\n", map->map_file, mode); 48460089Seric 48560207Seric if (mode == O_RDWR) 48660207Seric mode |= O_CREAT|O_TRUNC; 48760207Seric 48860228Seric (void) strcpy(buf, map->map_file); 48960228Seric i = strlen(buf); 49060228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 49160228Seric (void) strcat(buf, ".db"); 49260222Seric db = dbopen(buf, mode, DBMMODE, DB_HASH, NULL); 49356822Seric if (db == NULL) 49456822Seric { 49560207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 49656836Seric syserr("Cannot open HASH database %s", map->map_file); 49756822Seric return FALSE; 49856822Seric } 49960089Seric map->map_db2 = (void *) db; 50060207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 50160207Seric aliaswait(map, ".db"); 50256822Seric return TRUE; 50356822Seric } 50456822Seric 50556822Seric 50656822Seric /* 50756822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 50856822Seric */ 50956822Seric 51056822Seric char * 51160089Seric db_map_lookup(map, name, av, statp) 51256822Seric MAP *map; 51360089Seric char *name; 51456822Seric char **av; 51559084Seric int *statp; 51656822Seric { 51756822Seric DBT key, val; 51860422Seric register DB *db = (DB *) map->map_db2; 51960422Seric int st; 52060422Seric int saveerrno; 52160089Seric char keybuf[MAXNAME + 1]; 52256822Seric 52360089Seric if (tTd(27, 20)) 52460089Seric printf("db_map_lookup(%s)\n", name); 52560089Seric 52660089Seric key.size = strlen(name); 52760089Seric if (key.size > sizeof keybuf - 1) 52860089Seric key.size = sizeof keybuf - 1; 52960089Seric key.data = keybuf; 53060089Seric bcopy(name, keybuf, key.size + 1); 53160207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 53260089Seric makelower(keybuf); 53360207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 53456822Seric key.size++; 53560422Seric #ifndef OLD_NEWDB 53660422Seric (void) lockfile(db->fd(db), map->map_file, LOCK_SH); 53760422Seric #endif 53860422Seric st = db->get(db, &key, &val, 0); 53960422Seric saveerrno = errno; 54060422Seric #ifndef OLD_NEWDB 54160422Seric (void) lockfile(db->fd(db), map->map_file, LOCK_UN); 54260422Seric #endif 54360422Seric if (st != 0) 54460422Seric { 54560422Seric errno = saveerrno; 54660422Seric if (st < 0) 54760422Seric syserr("db_map_lookup: get (%s)", name); 54856822Seric return NULL; 54960422Seric } 55060207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 55160089Seric av = NULL; 55260089Seric return map_rewrite(map, val.data, val.size, av); 55356822Seric } 55456822Seric 55560089Seric 55660089Seric /* 55760089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 55856822Seric */ 55956822Seric 56060089Seric void 56160089Seric db_map_store(map, lhs, rhs) 56260089Seric register MAP *map; 56360089Seric char *lhs; 56460089Seric char *rhs; 56556822Seric { 56660089Seric int stat; 56760089Seric DBT key; 56860089Seric DBT data; 56960089Seric register DB *db = map->map_db2; 57056822Seric 57160089Seric if (tTd(27, 20)) 57260089Seric printf("db_map_store(%s, %s)\n", lhs, rhs); 57360089Seric 57460089Seric key.size = strlen(lhs); 57560089Seric key.data = lhs; 57660089Seric 57760089Seric data.size = strlen(rhs); 57860089Seric data.data = rhs; 57960089Seric 58060207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 58156822Seric { 58260089Seric key.size++; 58360089Seric data.size++; 58460089Seric } 58556836Seric 58660089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 58760089Seric if (stat > 0) 58860089Seric { 58960089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 59060089Seric stat = db->put(db, &key, &data, 0); 59160089Seric } 59260089Seric if (stat != 0) 59360089Seric syserr("readaliases: db put (%s)", lhs); 59460089Seric } 59556836Seric 59656847Seric 59760089Seric /* 59860089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 59960089Seric */ 60060089Seric 60160089Seric void 60260089Seric db_map_close(map) 60360089Seric MAP *map; 60460089Seric { 60560089Seric register DB *db = map->map_db2; 60660089Seric 60760089Seric if (tTd(27, 9)) 60860207Seric printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags); 60960089Seric 61060207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 61158804Seric { 61260089Seric /* write out the distinguished alias */ 61360089Seric db_map_store(map, "@", "@"); 61458804Seric } 61558963Seric 61660089Seric if (db->close(db) != 0) 61760089Seric syserr("readaliases: db close failure"); 61856822Seric } 61957208Seric 62060089Seric #endif 62160089Seric /* 62260089Seric ** NIS Modules 62360089Seric */ 62460089Seric 62560089Seric # ifdef NIS 62660089Seric 62757208Seric /* 62860089Seric ** NIS_MAP_OPEN -- open DBM map 62957208Seric */ 63057208Seric 63157208Seric bool 63260089Seric nis_map_open(map, mode) 63357208Seric MAP *map; 63460089Seric int mode; 63557208Seric { 63657216Seric int yperr; 63760215Seric register char *p; 63860215Seric auto char *vp; 63960215Seric auto int vsize; 64057216Seric char *master; 64157216Seric 64260089Seric if (tTd(27, 2)) 64360089Seric printf("nis_map_open(%s)\n", map->map_file); 64460089Seric 64560207Seric if (mode != O_RDONLY) 64660207Seric { 64760207Seric errno = ENODEV; 64860207Seric return FALSE; 64960207Seric } 65060207Seric 65160089Seric p = strchr(map->map_file, '@'); 65260089Seric if (p != NULL) 65360089Seric { 65460089Seric *p++ = '\0'; 65560089Seric if (*p != '\0') 65660089Seric map->map_domain = p; 65760089Seric } 65860215Seric 65960089Seric if (map->map_domain == NULL) 66060089Seric yp_get_default_domain(&map->map_domain); 66160089Seric 66260089Seric if (*map->map_file == '\0') 66360089Seric map->map_file = "mail.aliases"; 66460089Seric 66560215Seric /* check to see if this map actually exists */ 66660089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 66760089Seric &vp, &vsize); 66860089Seric if (tTd(27, 10)) 66960089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 67060089Seric map->map_domain, map->map_file, yperr_string(yperr)); 67160089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 67260089Seric return TRUE; 67360215Seric 67460215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 67560215Seric syserr("Cannot bind to domain %s: %s", map->map_domain, 67660215Seric yperr_string(yperr)); 67760215Seric 67860089Seric return FALSE; 67960089Seric } 68060089Seric 68160089Seric 68260089Seric /* 68357208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 68457208Seric */ 68557208Seric 68657208Seric char * 68760089Seric nis_map_lookup(map, name, av, statp) 68857208Seric MAP *map; 68960089Seric char *name; 69057208Seric char **av; 69159084Seric int *statp; 69257208Seric { 69357208Seric char *vp; 69457642Seric auto int vsize; 69559274Seric int buflen; 69660215Seric int yperr; 69760089Seric char keybuf[MAXNAME + 1]; 69857208Seric 69960089Seric if (tTd(27, 20)) 70060089Seric printf("nis_map_lookup(%s)\n", name); 70160089Seric 70260089Seric buflen = strlen(name); 70360089Seric if (buflen > sizeof keybuf - 1) 70460089Seric buflen = sizeof keybuf - 1; 70560089Seric bcopy(name, keybuf, buflen + 1); 70660207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 70760089Seric makelower(keybuf); 70860207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 70959274Seric buflen++; 71060089Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 71160089Seric &vp, &vsize); 71260089Seric if (yperr != 0) 71360089Seric { 71460089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 71560215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 71657208Seric return NULL; 71760089Seric } 71860207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 71960089Seric av = NULL; 72060215Seric return map_rewrite(map, vp, vsize, av); 72157208Seric } 72257208Seric 72360089Seric 72460089Seric /* 72560207Seric ** NIS_MAP_STORE 72660089Seric */ 72760089Seric 72860089Seric void 72960089Seric nis_map_store(map, lhs, rhs) 73060089Seric MAP *map; 73160089Seric char *lhs; 73260089Seric char *rhs; 73360089Seric { 73460089Seric /* nothing */ 73560089Seric } 73660089Seric 73760089Seric 73860089Seric /* 73960207Seric ** NIS_MAP_CLOSE 74060089Seric */ 74160089Seric 74260089Seric void 74360089Seric nis_map_close(map) 74460089Seric MAP *map; 74560089Seric { 74660089Seric /* nothing */ 74760089Seric } 74860089Seric 74960089Seric #endif /* NIS */ 75057208Seric /* 75160089Seric ** STAB (Symbol Table) Modules 75260089Seric */ 75360089Seric 75460089Seric 75560089Seric /* 75660207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 75760089Seric */ 75860089Seric 75960089Seric char * 76060089Seric stab_map_lookup(map, name) 76160089Seric register MAP *map; 76260089Seric char *name; 76360089Seric { 76460089Seric register STAB *s; 76560089Seric 76660089Seric if (tTd(27, 20)) 76760089Seric printf("stab_lookup(%s)\n", name); 76860089Seric 76960089Seric s = stab(name, ST_ALIAS, ST_FIND); 77060089Seric if (s != NULL) 77160089Seric return (s->s_alias); 77260089Seric return (NULL); 77360089Seric } 77460089Seric 77560089Seric 77660089Seric /* 77760207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 77860089Seric */ 77960089Seric 78060089Seric void 78160089Seric stab_map_store(map, lhs, rhs) 78260089Seric register MAP *map; 78360089Seric char *lhs; 78460089Seric char *rhs; 78560089Seric { 78660089Seric register STAB *s; 78760089Seric 78860089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 78960089Seric s->s_alias = newstr(rhs); 79060089Seric } 79160089Seric 79260089Seric 79360089Seric /* 79460207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 79560207Seric ** 79660207Seric ** This is a wierd case -- it is only intended as a fallback for 79760207Seric ** aliases. For this reason, opens for write (only during a 79860207Seric ** "newaliases") always fails, and opens for read open the 79960207Seric ** actual underlying text file instead of the database. 80060089Seric */ 80160089Seric 80260089Seric bool 80360089Seric stab_map_open(map, mode) 80460089Seric register MAP *map; 80560089Seric int mode; 80660089Seric { 80760089Seric FILE *af; 80860089Seric 80960089Seric if (tTd(27, 2)) 81060089Seric printf("stab_map_open(%s)\n", map->map_file); 81160089Seric 81260089Seric if (mode != O_RDONLY) 81360207Seric { 81460207Seric errno = ENODEV; 81560089Seric return FALSE; 81660207Seric } 81760089Seric 81860089Seric return TRUE; 81960089Seric } 82060089Seric 82160089Seric 82260089Seric /* 82360207Seric ** STAB_MAP_CLOSE -- close symbol table (???) 82460089Seric */ 82560089Seric 82660089Seric void 82760089Seric stab_map_close(map) 82860089Seric MAP *map; 82960089Seric { 83060089Seric /* ignore it */ 83160089Seric } 83260089Seric /* 83360089Seric ** Implicit Modules 83456822Seric ** 83560089Seric ** Tries several types. For back compatibility of aliases. 83656822Seric */ 83756822Seric 83860089Seric 83960089Seric /* 84060207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 84160089Seric */ 84260089Seric 84360089Seric char * 84460089Seric impl_map_lookup(map, name, av, pstat) 84560089Seric MAP *map; 84660089Seric char *name; 84756822Seric char **av; 84860089Seric int *pstat; 84956822Seric { 85060089Seric if (tTd(27, 20)) 85160089Seric printf("impl_map_lookup(%s)\n", name); 85256822Seric 85360089Seric #ifdef NEWDB 85460207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 85560089Seric return db_map_lookup(map, name, av, pstat); 85660089Seric #endif 85760089Seric #ifdef NDBM 85860207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 85960089Seric return ndbm_map_lookup(map, name, av, pstat); 86060089Seric #endif 86160089Seric return stab_map_lookup(map, name, av, pstat); 86260089Seric } 86360089Seric 86460089Seric /* 86560207Seric ** IMPL_MAP_STORE -- store in open databases 86660089Seric */ 86760089Seric 86860089Seric void 86960089Seric impl_map_store(map, lhs, rhs) 87060089Seric MAP *map; 87160089Seric char *lhs; 87260089Seric char *rhs; 87360089Seric { 87460089Seric #ifdef NEWDB 87560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 87660089Seric db_map_store(map, lhs, rhs); 87760089Seric #endif 87860089Seric #ifdef NDBM 87960207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 88060089Seric ndbm_map_store(map, lhs, rhs); 88160089Seric #endif 88260089Seric stab_map_store(map, lhs, rhs); 88360089Seric } 88460089Seric 88560089Seric /* 88660089Seric ** IMPL_MAP_OPEN -- implicit database open 88760089Seric */ 88860089Seric 88960089Seric bool 89060089Seric impl_map_open(map, mode) 89160089Seric MAP *map; 89260089Seric int mode; 89360089Seric { 89460089Seric struct stat stb; 89560089Seric 89660089Seric if (tTd(27, 2)) 89760089Seric printf("impl_map_open(%s)\n", map->map_file); 89860089Seric 89960089Seric if (stat(map->map_file, &stb) < 0) 90056822Seric { 90160089Seric /* no alias file at all */ 90260089Seric return FALSE; 90356822Seric } 90456822Seric 90560089Seric #ifdef NEWDB 90660207Seric map->map_mflags |= MF_IMPL_HASH; 90760089Seric if (hash_map_open(map, mode)) 90856822Seric { 90960207Seric #if defined(NDBM) && defined(YPCOMPAT) 91060207Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) == 0) 91160207Seric #endif 91260207Seric return TRUE; 91360089Seric } 91460207Seric else 91560207Seric map->map_mflags &= ~MF_IMPL_HASH; 91660089Seric #endif 91760089Seric #ifdef NDBM 91860207Seric map->map_mflags |= MF_IMPL_NDBM; 91960089Seric if (ndbm_map_open(map, mode)) 92060089Seric { 92160089Seric return TRUE; 92260089Seric } 92360207Seric else 92460207Seric map->map_mflags &= ~MF_IMPL_NDBM; 92560089Seric #endif 92656822Seric 92760207Seric #if !defined(NEWDB) && !defined(NDBM) 92860089Seric if (Verbose) 92960089Seric message("WARNING: cannot open alias database %s", map->map_file); 93060207Seric #endif 93160089Seric 93260207Seric return stab_map_open(map, mode); 93356822Seric } 93460089Seric 93560207Seric 93660089Seric /* 93760207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 93860089Seric */ 93960089Seric 94060089Seric void 94160207Seric impl_map_close(map) 94260089Seric MAP *map; 94360089Seric { 94460089Seric #ifdef NEWDB 94560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 94660089Seric { 94760207Seric db_map_close(map); 94860207Seric map->map_mflags &= ~MF_IMPL_HASH; 94960089Seric } 95060089Seric #endif 95160089Seric 95260089Seric #ifdef NDBM 95360207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 95460089Seric { 95560207Seric ndbm_map_close(map); 95660207Seric map->map_mflags &= ~MF_IMPL_NDBM; 95760089Seric } 95860089Seric #endif 95960089Seric } 96060207Seric /* 96160207Seric ** NULL stubs 96260089Seric */ 96360089Seric 96460207Seric bool 96560207Seric null_map_open(map, mode) 96660089Seric MAP *map; 96760207Seric int mode; 96860089Seric { 96960207Seric return TRUE; 97060089Seric } 97160089Seric 97260207Seric void 97360207Seric null_map_close(map) 97460207Seric MAP *map; 97560089Seric { 97660207Seric return; 97760207Seric } 97860089Seric 97960207Seric void 98060207Seric null_map_store(map, key, val) 98160207Seric MAP *map; 98260207Seric char *key; 98360207Seric char *val; 98460089Seric { 98560207Seric return; 98660089Seric } 987