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*67832Seric static char sccsid[] = "@(#)map.c 8.30 (Berkeley) 10/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; 12167726Seric 12267726Seric case 'k': 12367726Seric while (isascii(*++p) && isspace(*p)) 12467726Seric continue; 12567726Seric map->map_keycolnm = p; 12667726Seric break; 12767726Seric 12867726Seric case 'v': 12967726Seric while (isascii(*++p) && isspace(*p)) 13067726Seric continue; 13167726Seric map->map_valcolnm = p; 13267726Seric break; 13367726Seric 13467726Seric case 'z': 13567726Seric if (*++p != '\\') 13667726Seric map->map_coldelim = *p; 13767726Seric else 13867726Seric { 13967726Seric switch (*++p) 14067726Seric { 14167726Seric case 'n': 14267726Seric map->map_coldelim = '\n'; 14367726Seric break; 14467726Seric 14567726Seric case 't': 14667726Seric map->map_coldelim = '\t'; 14767726Seric break; 14867726Seric 14967726Seric default: 15067726Seric map->map_coldelim = '\\'; 15167726Seric } 15267726Seric } 15367726Seric break; 15460089Seric } 15560089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 15660089Seric p++; 15760089Seric if (*p != '\0') 15860089Seric *p++ = '\0'; 15960089Seric } 16060089Seric if (map->map_app != NULL) 16160089Seric map->map_app = newstr(map->map_app); 16267726Seric if (map->map_keycolnm != NULL) 16367726Seric map->map_keycolnm = newstr(map->map_keycolnm); 16467726Seric if (map->map_valcolnm != NULL) 16567726Seric map->map_valcolnm = newstr(map->map_valcolnm); 16660089Seric 16760089Seric if (*p != '\0') 16860089Seric { 16960089Seric map->map_file = p; 17060089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 17160089Seric p++; 17260089Seric if (*p != '\0') 17360089Seric *p++ = '\0'; 17460089Seric map->map_file = newstr(map->map_file); 17560089Seric } 17660089Seric 17760089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 17860089Seric p++; 17960089Seric if (*p != '\0') 18060089Seric map->map_rebuild = newstr(p); 18160089Seric 18256822Seric if (map->map_file == NULL) 18357208Seric { 18460089Seric syserr("No file name for %s map %s", 18560089Seric map->map_class->map_cname, map->map_mname); 18656822Seric return FALSE; 18757208Seric } 18860089Seric return TRUE; 18960089Seric } 19060089Seric /* 19160089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 19260089Seric ** 19360089Seric ** It also adds the map_app string. It can be used as a utility 19460089Seric ** in the map_lookup method. 19560089Seric ** 19660089Seric ** Parameters: 19760089Seric ** map -- the map that causes this. 19860089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 19960089Seric ** slen -- the length of s. 20060089Seric ** av -- arguments to interpolate into buf. 20160089Seric ** 20260089Seric ** Returns: 20360089Seric ** Pointer to rewritten result. 20460089Seric ** 20560089Seric ** Side Effects: 20660089Seric ** none. 20760089Seric */ 20860089Seric 20960492Seric struct rwbuf 21060492Seric { 21160492Seric int rwb_len; /* size of buffer */ 21260492Seric char *rwb_buf; /* ptr to buffer */ 21360492Seric }; 21460492Seric 21560492Seric struct rwbuf RwBufs[2]; /* buffers for rewriting output */ 21660492Seric 21760089Seric char * 21860089Seric map_rewrite(map, s, slen, av) 21960089Seric register MAP *map; 22060089Seric register char *s; 22160089Seric int slen; 22260089Seric char **av; 22360089Seric { 22460089Seric register char *bp; 22560089Seric register char c; 22660089Seric char **avp; 22760089Seric register char *ap; 22860492Seric register struct rwbuf *rwb; 22960089Seric int i; 23060089Seric int len; 23160089Seric 23260537Seric if (tTd(39, 1)) 23360089Seric { 23460256Seric printf("map_rewrite(%.*s), av =", slen, s); 23560256Seric if (av == NULL) 23660256Seric printf(" (nullv)"); 23760256Seric else 23860256Seric { 23960256Seric for (avp = av; *avp != NULL; avp++) 24060256Seric printf("\n\t%s", *avp); 24160256Seric } 24260256Seric printf("\n"); 24360089Seric } 24460089Seric 24560492Seric rwb = RwBufs; 24660492Seric if (av == NULL) 24760492Seric rwb++; 24860492Seric 24960089Seric /* count expected size of output (can safely overestimate) */ 25060089Seric i = len = slen; 25160089Seric if (av != NULL) 25260089Seric { 25360089Seric bp = s; 25460089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 25560089Seric { 25660089Seric if (c != '%') 25760089Seric continue; 25860089Seric if (--i < 0) 25960089Seric break; 26060089Seric c = *bp++; 26160089Seric if (!(isascii(c) && isdigit(c))) 26260089Seric continue; 26363937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 26460089Seric continue; 26560089Seric if (*avp == NULL) 26660089Seric continue; 26760089Seric len += strlen(*avp); 26860089Seric } 26960089Seric } 27060089Seric if (map->map_app != NULL) 27160089Seric len += strlen(map->map_app); 27260492Seric if (rwb->rwb_len < ++len) 27360089Seric { 27460089Seric /* need to malloc additional space */ 27560492Seric rwb->rwb_len = len; 27660492Seric if (rwb->rwb_buf != NULL) 27760492Seric free(rwb->rwb_buf); 27860492Seric rwb->rwb_buf = xalloc(rwb->rwb_len); 27960089Seric } 28060089Seric 28160492Seric bp = rwb->rwb_buf; 28260089Seric if (av == NULL) 28360089Seric { 28460089Seric bcopy(s, bp, slen); 28560089Seric bp += slen; 28660089Seric } 28760089Seric else 28860089Seric { 28960089Seric while (--slen >= 0 && (c = *s++) != '\0') 29060089Seric { 29160089Seric if (c != '%') 29260089Seric { 29360089Seric pushc: 29460089Seric *bp++ = c; 29560089Seric continue; 29660089Seric } 29760089Seric if (--slen < 0 || (c = *s++) == '\0') 29860089Seric c = '%'; 29960089Seric if (c == '%') 30060089Seric goto pushc; 30160089Seric if (!(isascii(c) && isdigit(c))) 30260089Seric { 30360089Seric *bp++ = '%'; 30460089Seric goto pushc; 30560089Seric } 30663937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 30760089Seric continue; 30860089Seric if (*avp == NULL) 30960089Seric continue; 31060089Seric 31160089Seric /* transliterate argument into output string */ 31260089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 31360089Seric *bp++ = c; 31460089Seric } 31560089Seric } 31660089Seric if (map->map_app != NULL) 31760089Seric strcpy(bp, map->map_app); 31860089Seric else 31960089Seric *bp = '\0'; 32060537Seric if (tTd(39, 1)) 32160492Seric printf("map_rewrite => %s\n", rwb->rwb_buf); 32260492Seric return rwb->rwb_buf; 32360089Seric } 32460089Seric /* 32560537Seric ** INITMAPS -- initialize for aliasing 32660537Seric ** 32760537Seric ** Parameters: 32860537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 32960537Seric ** e -- current envelope. 33060537Seric ** 33160537Seric ** Returns: 33260537Seric ** none. 33360537Seric ** 33460537Seric ** Side Effects: 33560537Seric ** initializes aliases: 33660537Seric ** if NDBM: opens the database. 33760537Seric ** if ~NDBM: reads the aliases into the symbol table. 33860537Seric */ 33960537Seric 34060537Seric initmaps(rebuild, e) 34160537Seric bool rebuild; 34260537Seric register ENVELOPE *e; 34360537Seric { 34460537Seric extern void map_init(); 34560537Seric 34664671Seric #ifdef XDEBUG 34764671Seric checkfd012("entering initmaps"); 34864671Seric #endif 34960537Seric CurEnv = e; 35065085Seric if (rebuild) 35165085Seric { 35265085Seric stabapply(map_init, 1); 35365085Seric stabapply(map_init, 2); 35465085Seric } 35565085Seric else 35665085Seric { 35765085Seric stabapply(map_init, 0); 35865085Seric } 35964671Seric #ifdef XDEBUG 36064671Seric checkfd012("exiting initmaps"); 36164671Seric #endif 36260537Seric } 36360537Seric 36460537Seric void 36560537Seric map_init(s, rebuild) 36660537Seric register STAB *s; 36760537Seric int rebuild; 36860537Seric { 36960537Seric register MAP *map; 37060537Seric 37160537Seric /* has to be a map */ 37260537Seric if (s->s_type != ST_MAP) 37360537Seric return; 37460537Seric 37560537Seric map = &s->s_map; 37660537Seric if (!bitset(MF_VALID, map->map_mflags)) 37760537Seric return; 37860537Seric 37960537Seric if (tTd(38, 2)) 38067726Seric printf("map_init(%s:%s, %s, %d)\n", 38164690Seric map->map_class->map_cname == NULL ? "NULL" : 38264690Seric map->map_class->map_cname, 38367726Seric map->map_mname == NULL ? "NULL" : map->map_mname, 38465085Seric map->map_file == NULL ? "NULL" : map->map_file, 38565085Seric rebuild); 38660537Seric 38765085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && 38865085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) 38965085Seric { 39065085Seric if (tTd(38, 3)) 39165085Seric printf("\twrong pass\n"); 39265085Seric return; 39365085Seric } 39465085Seric 39560537Seric /* if already open, close it (for nested open) */ 39660537Seric if (bitset(MF_OPEN, map->map_mflags)) 39760537Seric { 39860537Seric map->map_class->map_close(map); 39960537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 40060537Seric } 40160537Seric 40265085Seric if (rebuild == 2) 40360537Seric { 40465085Seric rebuildaliases(map, FALSE); 40560537Seric } 40660537Seric else 40760537Seric { 40860537Seric if (map->map_class->map_open(map, O_RDONLY)) 40960537Seric { 41060537Seric if (tTd(38, 4)) 41167726Seric printf("\t%s:%s %s: valid\n", 41264690Seric map->map_class->map_cname == NULL ? "NULL" : 41364690Seric map->map_class->map_cname, 41467726Seric map->map_mname == NULL ? "NULL" : 41567726Seric map->map_mname, 41664690Seric map->map_file == NULL ? "NULL" : 41764690Seric map->map_file); 41860537Seric map->map_mflags |= MF_OPEN; 41960537Seric } 42060537Seric else if (tTd(38, 4)) 42167726Seric printf("\t%s:%s %s: invalid: %s\n", 42264690Seric map->map_class->map_cname == NULL ? "NULL" : 42364690Seric map->map_class->map_cname, 42467726Seric map->map_mname == NULL ? "NULL" : 42567726Seric map->map_mname, 42664690Seric map->map_file == NULL ? "NULL" : 42764690Seric map->map_file, 42860537Seric errstring(errno)); 42960537Seric } 43060537Seric } 43160537Seric /* 43260089Seric ** NDBM modules 43360089Seric */ 43460089Seric 43560089Seric #ifdef NDBM 43660089Seric 43760089Seric /* 43860089Seric ** DBM_MAP_OPEN -- DBM-style map open 43960089Seric */ 44060089Seric 44160089Seric bool 44260089Seric ndbm_map_open(map, mode) 44360089Seric MAP *map; 44460089Seric int mode; 44560089Seric { 44664284Seric register DBM *dbm; 44764284Seric struct stat st; 44860089Seric 44960537Seric if (tTd(38, 2)) 45067726Seric printf("ndbm_map_open(%s, %s, %d)\n", 45167726Seric map->map_mname, map->map_file, mode); 45260089Seric 45360207Seric if (mode == O_RDWR) 45460207Seric mode |= O_CREAT|O_TRUNC; 45560207Seric 45660089Seric /* open the database */ 45760089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 45856822Seric if (dbm == NULL) 45956822Seric { 46064718Seric #ifdef MAYBENEXTRELEASE 46164718Seric if (aliaswait(map, ".pag", FALSE)) 46264718Seric return TRUE; 46364718Seric #endif 46460207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 46556836Seric syserr("Cannot open DBM database %s", map->map_file); 46656822Seric return FALSE; 46756822Seric } 46860089Seric map->map_db1 = (void *) dbm; 46964964Seric if (mode == O_RDONLY) 47064964Seric { 47164964Seric if (bitset(MF_ALIAS, map->map_mflags) && 47264964Seric !aliaswait(map, ".pag", TRUE)) 47364718Seric return FALSE; 47464964Seric } 47564964Seric else 47664964Seric { 47764964Seric int fd; 47864964Seric 47964964Seric /* exclusive lock for duration of rebuild */ 48064964Seric fd = dbm_dirfno((DBM *) map->map_db1); 48164964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 48264964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 48364964Seric map->map_mflags |= MF_LOCKED; 48464964Seric } 48564718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 48664284Seric map->map_mtime = st.st_mtime; 48756822Seric return TRUE; 48856822Seric } 48960089Seric 49060089Seric 49160089Seric /* 49256822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 49356822Seric */ 49456822Seric 49556822Seric char * 49660089Seric ndbm_map_lookup(map, name, av, statp) 49756822Seric MAP *map; 49860089Seric char *name; 49956822Seric char **av; 50059084Seric int *statp; 50156822Seric { 50256822Seric datum key, val; 50364373Seric int fd; 50460089Seric char keybuf[MAXNAME + 1]; 50556822Seric 50660537Seric if (tTd(38, 20)) 50767726Seric printf("ndbm_map_lookup(%s, %s)\n", 50867726Seric map->map_mname, name); 50960089Seric 51060089Seric key.dptr = name; 51160089Seric key.dsize = strlen(name); 51260207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 51357014Seric { 51460089Seric if (key.dsize > sizeof keybuf - 1) 51560089Seric key.dsize = sizeof keybuf - 1; 51660089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 51760089Seric makelower(keybuf); 51860089Seric key.dptr = keybuf; 51957014Seric } 52064373Seric fd = dbm_dirfno((DBM *) map->map_db1); 52164388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 52264373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 52363753Seric val.dptr = NULL; 52463753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 52563753Seric { 52663753Seric val = dbm_fetch((DBM *) map->map_db1, key); 52763753Seric if (val.dptr != NULL) 52863753Seric map->map_mflags &= ~MF_TRY1NULL; 52963753Seric } 53063753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 53163753Seric { 53256822Seric key.dsize++; 53363753Seric val = dbm_fetch((DBM *) map->map_db1, key); 53463753Seric if (val.dptr != NULL) 53563753Seric map->map_mflags &= ~MF_TRY0NULL; 53663753Seric } 53764388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 53864373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 53956822Seric if (val.dptr == NULL) 54056822Seric return NULL; 54160207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 54263753Seric return map_rewrite(map, name, strlen(name), NULL); 54363753Seric else 54463753Seric return map_rewrite(map, val.dptr, val.dsize, av); 54556822Seric } 54656822Seric 54756822Seric 54856822Seric /* 54960089Seric ** DBM_MAP_STORE -- store a datum in the database 55056822Seric */ 55156822Seric 55260089Seric void 55360089Seric ndbm_map_store(map, lhs, rhs) 55460089Seric register MAP *map; 55560089Seric char *lhs; 55660089Seric char *rhs; 55760089Seric { 55860089Seric datum key; 55960089Seric datum data; 56060089Seric int stat; 56160089Seric 56260537Seric if (tTd(38, 12)) 56367726Seric printf("ndbm_map_store(%s, %s, %s)\n", 56467726Seric map->map_mname, lhs, rhs); 56560089Seric 56660089Seric key.dsize = strlen(lhs); 56760089Seric key.dptr = lhs; 56860089Seric 56960089Seric data.dsize = strlen(rhs); 57060089Seric data.dptr = rhs; 57160089Seric 57260207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 57360089Seric { 57460089Seric key.dsize++; 57560089Seric data.dsize++; 57660089Seric } 57760089Seric 57860089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 57960089Seric if (stat > 0) 58060089Seric { 58160089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 58260089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 58360089Seric } 58460089Seric if (stat != 0) 58560089Seric syserr("readaliases: dbm put (%s)", lhs); 58660089Seric } 58760089Seric 58860089Seric 58960089Seric /* 59060207Seric ** NDBM_MAP_CLOSE -- close the database 59160089Seric */ 59260089Seric 59360089Seric void 59460089Seric ndbm_map_close(map) 59560089Seric register MAP *map; 59660089Seric { 59766773Seric if (tTd(38, 9)) 59867726Seric printf("ndbm_map_close(%s, %s, %x)\n", 59967726Seric map->map_mname, map->map_file, map->map_mflags); 60066773Seric 60160207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 60260089Seric { 60364250Seric #ifdef NIS 60464075Seric bool inclnull; 60560089Seric char buf[200]; 60660089Seric 60764075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 60864075Seric map->map_mflags &= ~MF_INCLNULL; 60964075Seric 61060089Seric (void) sprintf(buf, "%010ld", curtime()); 61160089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 61260089Seric 61364941Seric (void) gethostname(buf, sizeof buf); 61460089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 61564075Seric 61664075Seric if (inclnull) 61764075Seric map->map_mflags |= MF_INCLNULL; 61860089Seric #endif 61960089Seric 62060089Seric /* write out the distinguished alias */ 62160089Seric ndbm_map_store(map, "@", "@"); 62260089Seric } 62360089Seric dbm_close((DBM *) map->map_db1); 62460089Seric } 62560089Seric 62660089Seric #endif 62760089Seric /* 62860582Seric ** NEWDB (Hash and BTree) Modules 62960089Seric */ 63060089Seric 63160089Seric #ifdef NEWDB 63260089Seric 63360089Seric /* 63460582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 63560582Seric ** 63660582Seric ** These do rather bizarre locking. If you can lock on open, 63760582Seric ** do that to avoid the condition of opening a database that 63860582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 63960582Seric ** there will be a race condition. If opening for read-only, 64060582Seric ** we immediately release the lock to avoid freezing things up. 64160582Seric ** We really ought to hold the lock, but guarantee that we won't 64260582Seric ** be pokey about it. That's hard to do. 64360089Seric */ 64460089Seric 64556822Seric bool 64660089Seric bt_map_open(map, mode) 64756822Seric MAP *map; 64860089Seric int mode; 64956822Seric { 65056822Seric DB *db; 65160228Seric int i; 65260582Seric int omode; 65364373Seric int fd; 65464284Seric struct stat st; 65560089Seric char buf[MAXNAME]; 65656822Seric 65760537Seric if (tTd(38, 2)) 65867726Seric printf("bt_map_open(%s, %s, %d)\n", 65967726Seric map->map_mname, map->map_file, mode); 66060089Seric 66160582Seric omode = mode; 66260582Seric if (omode == O_RDWR) 66360582Seric { 66460582Seric omode |= O_CREAT|O_TRUNC; 66565830Seric #if defined(O_EXLOCK) && HASFLOCK 66660582Seric omode |= O_EXLOCK; 66766843Seric # if !OLD_NEWDB 66860582Seric } 66960582Seric else 67060582Seric { 67160582Seric omode |= O_SHLOCK; 67260582Seric # endif 67360582Seric #endif 67460582Seric } 67560207Seric 67660228Seric (void) strcpy(buf, map->map_file); 67760228Seric i = strlen(buf); 67860228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 67960228Seric (void) strcat(buf, ".db"); 68060582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 68156822Seric if (db == NULL) 68256822Seric { 68364718Seric #ifdef MAYBENEXTRELEASE 68464718Seric if (aliaswait(map, ".db", FALSE)) 68564718Seric return TRUE; 68664718Seric #endif 68760207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 68856836Seric syserr("Cannot open BTREE database %s", map->map_file); 68956822Seric return FALSE; 69056822Seric } 69167173Seric #if !OLD_NEWDB 69264373Seric fd = db->fd(db); 69367187Seric # if HASFLOCK 69467187Seric # if !defined(O_EXLOCK) 69564373Seric if (mode == O_RDWR && fd >= 0) 69664388Seric { 69764388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 69864388Seric map->map_mflags |= MF_LOCKED; 69964388Seric } 70067187Seric # else 70164373Seric if (mode == O_RDONLY && fd >= 0) 70264373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 70364388Seric else 70464388Seric map->map_mflags |= MF_LOCKED; 70567187Seric # endif 70660582Seric # endif 70760582Seric #endif 70860585Seric 70960585Seric /* try to make sure that at least the database header is on disk */ 71060585Seric if (mode == O_RDWR) 71166843Seric #if OLD_NEWDB 71264373Seric (void) db->sync(db); 71364373Seric #else 71460585Seric (void) db->sync(db, 0); 71560585Seric 71664373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 71764284Seric map->map_mtime = st.st_mtime; 71864284Seric #endif 71964284Seric 72060089Seric map->map_db2 = (void *) db; 72160207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 72264718Seric if (!aliaswait(map, ".db", TRUE)) 72364718Seric return FALSE; 72456822Seric return TRUE; 72556822Seric } 72656822Seric 72756822Seric 72856822Seric /* 72956822Seric ** HASH_MAP_INIT -- HASH-style map initialization 73056822Seric */ 73156822Seric 73256822Seric bool 73360089Seric hash_map_open(map, mode) 73456822Seric MAP *map; 73560089Seric int mode; 73656822Seric { 73756822Seric DB *db; 73860228Seric int i; 73960582Seric int omode; 74064373Seric int fd; 74164284Seric struct stat st; 74260089Seric char buf[MAXNAME]; 74356822Seric 74460537Seric if (tTd(38, 2)) 74567726Seric printf("hash_map_open(%s, %s, %d)\n", 74667726Seric map->map_mname, map->map_file, mode); 74760089Seric 74860582Seric omode = mode; 74960582Seric if (omode == O_RDWR) 75060582Seric { 75160582Seric omode |= O_CREAT|O_TRUNC; 75265830Seric #if defined(O_EXLOCK) && HASFLOCK 75360582Seric omode |= O_EXLOCK; 75466843Seric # if !OLD_NEWDB 75560582Seric } 75660582Seric else 75760582Seric { 75860582Seric omode |= O_SHLOCK; 75960582Seric # endif 76060582Seric #endif 76160582Seric } 76260207Seric 76360228Seric (void) strcpy(buf, map->map_file); 76460228Seric i = strlen(buf); 76560228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 76660228Seric (void) strcat(buf, ".db"); 76760582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 76856822Seric if (db == NULL) 76956822Seric { 77064718Seric #ifdef MAYBENEXTRELEASE 77164718Seric if (aliaswait(map, ".db", FALSE)) 77264718Seric return TRUE; 77364718Seric #endif 77460207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 77556836Seric syserr("Cannot open HASH database %s", map->map_file); 77656822Seric return FALSE; 77756822Seric } 77867173Seric #if !OLD_NEWDB 77964373Seric fd = db->fd(db); 78067187Seric # if HASFLOCK 78167187Seric # if !defined(O_EXLOCK) 78264373Seric if (mode == O_RDWR && fd >= 0) 78364388Seric { 78464388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 78564388Seric map->map_mflags |= MF_LOCKED; 78664388Seric } 78767187Seric # else 78864373Seric if (mode == O_RDONLY && fd >= 0) 78964373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 79064388Seric else 79164388Seric map->map_mflags |= MF_LOCKED; 79267187Seric # endif 79360582Seric # endif 79460582Seric #endif 79560585Seric 79660585Seric /* try to make sure that at least the database header is on disk */ 79760585Seric if (mode == O_RDWR) 79866843Seric #if OLD_NEWDB 79964373Seric (void) db->sync(db); 80064373Seric #else 80160585Seric (void) db->sync(db, 0); 80260585Seric 80364373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 80464284Seric map->map_mtime = st.st_mtime; 80564284Seric #endif 80664284Seric 80760089Seric map->map_db2 = (void *) db; 80860207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 80964718Seric if (!aliaswait(map, ".db", TRUE)) 81064718Seric return FALSE; 81156822Seric return TRUE; 81256822Seric } 81356822Seric 81456822Seric 81556822Seric /* 81656822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 81756822Seric */ 81856822Seric 81956822Seric char * 82060089Seric db_map_lookup(map, name, av, statp) 82156822Seric MAP *map; 82260089Seric char *name; 82356822Seric char **av; 82459084Seric int *statp; 82556822Seric { 82656822Seric DBT key, val; 82760422Seric register DB *db = (DB *) map->map_db2; 82860422Seric int st; 82960422Seric int saveerrno; 83064373Seric int fd; 83160089Seric char keybuf[MAXNAME + 1]; 83256822Seric 83360537Seric if (tTd(38, 20)) 83467726Seric printf("db_map_lookup(%s, %s)\n", 83567726Seric map->map_mname, name); 83660089Seric 83760089Seric key.size = strlen(name); 83860089Seric if (key.size > sizeof keybuf - 1) 83960089Seric key.size = sizeof keybuf - 1; 84060089Seric key.data = keybuf; 84160089Seric bcopy(name, keybuf, key.size + 1); 84260207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 84360089Seric makelower(keybuf); 84466843Seric #if !OLD_NEWDB 84564388Seric fd = db->fd(db); 84664388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 84764388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 84860422Seric #endif 84963753Seric st = 1; 85063753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 85163753Seric { 85263753Seric st = db->get(db, &key, &val, 0); 85363753Seric if (st == 0) 85463753Seric map->map_mflags &= ~MF_TRY1NULL; 85563753Seric } 85663753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 85763753Seric { 85863753Seric key.size++; 85963753Seric st = db->get(db, &key, &val, 0); 86063753Seric if (st == 0) 86163753Seric map->map_mflags &= ~MF_TRY0NULL; 86263753Seric } 86360422Seric saveerrno = errno; 86466843Seric #if !OLD_NEWDB 86564388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 86664373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 86760422Seric #endif 86860422Seric if (st != 0) 86960422Seric { 87060422Seric errno = saveerrno; 87160422Seric if (st < 0) 87260422Seric syserr("db_map_lookup: get (%s)", name); 87356822Seric return NULL; 87460422Seric } 87560207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 87663753Seric return map_rewrite(map, name, strlen(name), NULL); 87763753Seric else 87863753Seric return map_rewrite(map, val.data, val.size, av); 87956822Seric } 88056822Seric 88160089Seric 88260089Seric /* 88360089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 88456822Seric */ 88556822Seric 88660089Seric void 88760089Seric db_map_store(map, lhs, rhs) 88860089Seric register MAP *map; 88960089Seric char *lhs; 89060089Seric char *rhs; 89156822Seric { 89260089Seric int stat; 89360089Seric DBT key; 89460089Seric DBT data; 89560089Seric register DB *db = map->map_db2; 89656822Seric 89760537Seric if (tTd(38, 20)) 89867726Seric printf("db_map_store(%s, %s, %s)\n", 89967726Seric map->map_mname, lhs, rhs); 90060089Seric 90160089Seric key.size = strlen(lhs); 90260089Seric key.data = lhs; 90360089Seric 90460089Seric data.size = strlen(rhs); 90560089Seric data.data = rhs; 90660089Seric 90760207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 90856822Seric { 90960089Seric key.size++; 91060089Seric data.size++; 91160089Seric } 91256836Seric 91360089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 91460089Seric if (stat > 0) 91560089Seric { 91660089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 91760089Seric stat = db->put(db, &key, &data, 0); 91860089Seric } 91960089Seric if (stat != 0) 92060089Seric syserr("readaliases: db put (%s)", lhs); 92160089Seric } 92256836Seric 92356847Seric 92460089Seric /* 92560089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 92660089Seric */ 92760089Seric 92860089Seric void 92960089Seric db_map_close(map) 93060089Seric MAP *map; 93160089Seric { 93260089Seric register DB *db = map->map_db2; 93360089Seric 93460537Seric if (tTd(38, 9)) 93567726Seric printf("db_map_close(%s, %s, %x)\n", 93667726Seric map->map_mname, map->map_file, map->map_mflags); 93760089Seric 93860207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 93958804Seric { 94060089Seric /* write out the distinguished alias */ 94160089Seric db_map_store(map, "@", "@"); 94258804Seric } 94358963Seric 94460089Seric if (db->close(db) != 0) 94560089Seric syserr("readaliases: db close failure"); 94656822Seric } 94757208Seric 94860089Seric #endif 94960089Seric /* 95060089Seric ** NIS Modules 95160089Seric */ 95260089Seric 95360089Seric # ifdef NIS 95460089Seric 95564369Seric # ifndef YPERR_BUSY 95664369Seric # define YPERR_BUSY 16 95764369Seric # endif 95864369Seric 95957208Seric /* 96060089Seric ** NIS_MAP_OPEN -- open DBM map 96157208Seric */ 96257208Seric 96357208Seric bool 96460089Seric nis_map_open(map, mode) 96557208Seric MAP *map; 96660089Seric int mode; 96757208Seric { 96857216Seric int yperr; 96960215Seric register char *p; 97060215Seric auto char *vp; 97160215Seric auto int vsize; 97257216Seric char *master; 97357216Seric 97460537Seric if (tTd(38, 2)) 97567726Seric printf("nis_map_open(%s, %s)\n", 97667726Seric map->map_mname, map->map_file); 97760089Seric 97860207Seric if (mode != O_RDONLY) 97960207Seric { 98064650Seric /* issue a pseudo-error message */ 98164650Seric #ifdef ENOSYS 98264650Seric errno = ENOSYS; 98364650Seric #else 98464650Seric # ifdef EFTYPE 98564650Seric errno = EFTYPE; 98664650Seric # else 98764650Seric errno = ENXIO; 98864650Seric # endif 98964650Seric #endif 99060207Seric return FALSE; 99160207Seric } 99260207Seric 99360089Seric p = strchr(map->map_file, '@'); 99460089Seric if (p != NULL) 99560089Seric { 99660089Seric *p++ = '\0'; 99760089Seric if (*p != '\0') 99860089Seric map->map_domain = p; 99960089Seric } 100060215Seric 100160089Seric if (*map->map_file == '\0') 100260089Seric map->map_file = "mail.aliases"; 100360089Seric 100466157Seric if (map->map_domain == NULL) 100566157Seric { 100666157Seric yperr = yp_get_default_domain(&map->map_domain); 100766157Seric if (yperr != 0) 100866157Seric { 100966744Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 101066744Seric syserr("NIS map %s specified, but NIS not running\n", 101166744Seric map->map_file); 101266157Seric return FALSE; 101366157Seric } 101466157Seric } 101566157Seric 101660215Seric /* check to see if this map actually exists */ 101760089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 101860089Seric &vp, &vsize); 101960537Seric if (tTd(38, 10)) 102060089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 102160089Seric map->map_domain, map->map_file, yperr_string(yperr)); 102260089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 102360089Seric return TRUE; 102460215Seric 102560215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 102660215Seric syserr("Cannot bind to domain %s: %s", map->map_domain, 102760215Seric yperr_string(yperr)); 102860215Seric 102960089Seric return FALSE; 103060089Seric } 103160089Seric 103260089Seric 103360089Seric /* 103457208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 103557208Seric */ 103657208Seric 103757208Seric char * 103860089Seric nis_map_lookup(map, name, av, statp) 103957208Seric MAP *map; 104060089Seric char *name; 104157208Seric char **av; 104259084Seric int *statp; 104357208Seric { 104457208Seric char *vp; 104557642Seric auto int vsize; 104659274Seric int buflen; 104760215Seric int yperr; 104860089Seric char keybuf[MAXNAME + 1]; 104957208Seric 105060537Seric if (tTd(38, 20)) 105167726Seric printf("nis_map_lookup(%s, %s)\n", 105267726Seric map->map_mname, name); 105360089Seric 105460089Seric buflen = strlen(name); 105560089Seric if (buflen > sizeof keybuf - 1) 105660089Seric buflen = sizeof keybuf - 1; 105760089Seric bcopy(name, keybuf, buflen + 1); 105860207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 105960089Seric makelower(keybuf); 106063753Seric yperr = YPERR_KEY; 106163753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 106263753Seric { 106363753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 106463753Seric &vp, &vsize); 106563753Seric if (yperr == 0) 106663753Seric map->map_mflags &= ~MF_TRY1NULL; 106763753Seric } 106863753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 106963753Seric { 107059274Seric buflen++; 107163753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 107263753Seric &vp, &vsize); 107363753Seric if (yperr == 0) 107463753Seric map->map_mflags &= ~MF_TRY0NULL; 107563753Seric } 107660089Seric if (yperr != 0) 107760089Seric { 107860089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 107960215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 108057208Seric return NULL; 108160089Seric } 108260207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 108363753Seric return map_rewrite(map, name, strlen(name), NULL); 108463753Seric else 108563753Seric return map_rewrite(map, vp, vsize, av); 108657208Seric } 108757208Seric 108867726Seric #endif 108957208Seric /* 1090*67832Seric ** HESIOD Modules 1091*67832Seric ** 1092*67832Seric ** Only works for aliases (for now). 1093*67832Seric */ 1094*67832Seric 1095*67832Seric #ifdef HESIOD 1096*67832Seric 1097*67832Seric char * 1098*67832Seric hes_map_lookup(map, name, av, statp) 1099*67832Seric MAP *map; 1100*67832Seric char *name; 1101*67832Seric char **av; 1102*67832Seric int *statp; 1103*67832Seric { 1104*67832Seric struct hes_postoffice *pobox; 1105*67832Seric char keybuf[MAXNAME + 1]; 1106*67832Seric 1107*67832Seric if (tTd(38, 20)) 1108*67832Seric printf("hes_map_lookup(%s)\n", name); 1109*67832Seric 1110*67832Seric pobox = hes_getmailhost(name); 1111*67832Seric if (pobox == NULL) 1112*67832Seric return NULL; 1113*67832Seric 1114*67832Seric /* We only know how to deal with the SMTP types right now */ 1115*67832Seric if (strcmp(pobox->po_type, "SMTP") != 0 && 1116*67832Seric strcmp(pobox->po_type, "ESMTP") != 0) 1117*67832Seric return NULL; 1118*67832Seric 1119*67832Seric /* if just checking for a match, we are done */ 1120*67832Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 1121*67832Seric return map_rewrite(map, name, strlen(name), NULL); 1122*67832Seric 1123*67832Seric /* Do the rewriting with new values */ 1124*67832Seric if (strlen(pobox->po_name) + strlen(pobox->po_host) + 1 > sizeof keybuf) 1125*67832Seric return NULL; 1126*67832Seric (void) sprintf(keybuf, "%s@%s", pobox->po_name, pobox->po_host); 1127*67832Seric return map_rewrite(map, keybuf, strlen(keybuf), av); 1128*67832Seric } 1129*67832Seric 1130*67832Seric #endif 1131*67832Seric /* 113260089Seric ** STAB (Symbol Table) Modules 113360089Seric */ 113460089Seric 113560089Seric 113660089Seric /* 113760207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 113860089Seric */ 113960089Seric 114060089Seric char * 114161707Seric stab_map_lookup(map, name, av, pstat) 114260089Seric register MAP *map; 114360089Seric char *name; 114461707Seric char **av; 114561707Seric int *pstat; 114660089Seric { 114760089Seric register STAB *s; 114860089Seric 114960537Seric if (tTd(38, 20)) 115067726Seric printf("stab_lookup(%s, %s)\n", 115167726Seric map->map_mname, name); 115260089Seric 115360089Seric s = stab(name, ST_ALIAS, ST_FIND); 115460089Seric if (s != NULL) 115560089Seric return (s->s_alias); 115660089Seric return (NULL); 115760089Seric } 115860089Seric 115960089Seric 116060089Seric /* 116160207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 116260089Seric */ 116360089Seric 116460089Seric void 116560089Seric stab_map_store(map, lhs, rhs) 116660089Seric register MAP *map; 116760089Seric char *lhs; 116860089Seric char *rhs; 116960089Seric { 117060089Seric register STAB *s; 117160089Seric 117260089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 117360089Seric s->s_alias = newstr(rhs); 117460089Seric } 117560089Seric 117660089Seric 117760089Seric /* 117860207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 117960207Seric ** 118060207Seric ** This is a wierd case -- it is only intended as a fallback for 118160207Seric ** aliases. For this reason, opens for write (only during a 118260207Seric ** "newaliases") always fails, and opens for read open the 118360207Seric ** actual underlying text file instead of the database. 118460089Seric */ 118560089Seric 118660089Seric bool 118760089Seric stab_map_open(map, mode) 118860089Seric register MAP *map; 118960089Seric int mode; 119060089Seric { 119163835Seric FILE *af; 119264284Seric struct stat st; 119363835Seric 119460537Seric if (tTd(38, 2)) 119567726Seric printf("stab_map_open(%s, %s)\n", 119667726Seric map->map_mname, map->map_file); 119760089Seric 119860089Seric if (mode != O_RDONLY) 119960207Seric { 120060207Seric errno = ENODEV; 120160089Seric return FALSE; 120260207Seric } 120360089Seric 120463835Seric af = fopen(map->map_file, "r"); 120563835Seric if (af == NULL) 120663835Seric return FALSE; 120767263Seric readaliases(map, af, FALSE, FALSE); 120864284Seric 120964284Seric if (fstat(fileno(af), &st) >= 0) 121064284Seric map->map_mtime = st.st_mtime; 121163835Seric fclose(af); 121263835Seric 121360089Seric return TRUE; 121460089Seric } 121560089Seric /* 121660089Seric ** Implicit Modules 121756822Seric ** 121860089Seric ** Tries several types. For back compatibility of aliases. 121956822Seric */ 122056822Seric 122160089Seric 122260089Seric /* 122360207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 122460089Seric */ 122560089Seric 122660089Seric char * 122760089Seric impl_map_lookup(map, name, av, pstat) 122860089Seric MAP *map; 122960089Seric char *name; 123056822Seric char **av; 123160089Seric int *pstat; 123256822Seric { 123360537Seric if (tTd(38, 20)) 123467726Seric printf("impl_map_lookup(%s, %s)\n", 123567726Seric map->map_mname, name); 123656822Seric 123760089Seric #ifdef NEWDB 123860207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 123960089Seric return db_map_lookup(map, name, av, pstat); 124060089Seric #endif 124160089Seric #ifdef NDBM 124260207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 124360089Seric return ndbm_map_lookup(map, name, av, pstat); 124460089Seric #endif 124560089Seric return stab_map_lookup(map, name, av, pstat); 124660089Seric } 124760089Seric 124860089Seric /* 124960207Seric ** IMPL_MAP_STORE -- store in open databases 125060089Seric */ 125160089Seric 125260089Seric void 125360089Seric impl_map_store(map, lhs, rhs) 125460089Seric MAP *map; 125560089Seric char *lhs; 125660089Seric char *rhs; 125760089Seric { 125860089Seric #ifdef NEWDB 125960207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 126060089Seric db_map_store(map, lhs, rhs); 126160089Seric #endif 126260089Seric #ifdef NDBM 126360207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 126460089Seric ndbm_map_store(map, lhs, rhs); 126560089Seric #endif 126660089Seric stab_map_store(map, lhs, rhs); 126760089Seric } 126860089Seric 126960089Seric /* 127060089Seric ** IMPL_MAP_OPEN -- implicit database open 127160089Seric */ 127260089Seric 127360089Seric bool 127460089Seric impl_map_open(map, mode) 127560089Seric MAP *map; 127660089Seric int mode; 127760089Seric { 127860089Seric struct stat stb; 127960089Seric 128060537Seric if (tTd(38, 2)) 128167726Seric printf("impl_map_open(%s, %s, %d)\n", 128267726Seric map->map_mname, map->map_file, mode); 128360089Seric 128460089Seric if (stat(map->map_file, &stb) < 0) 128556822Seric { 128660089Seric /* no alias file at all */ 128764718Seric if (tTd(38, 3)) 128864718Seric printf("no map file\n"); 128960089Seric return FALSE; 129056822Seric } 129156822Seric 129260089Seric #ifdef NEWDB 129360207Seric map->map_mflags |= MF_IMPL_HASH; 129460089Seric if (hash_map_open(map, mode)) 129556822Seric { 129664250Seric #if defined(NDBM) && defined(NIS) 129760561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 129860207Seric #endif 129960207Seric return TRUE; 130060089Seric } 130160207Seric else 130260207Seric map->map_mflags &= ~MF_IMPL_HASH; 130360089Seric #endif 130460089Seric #ifdef NDBM 130560207Seric map->map_mflags |= MF_IMPL_NDBM; 130660089Seric if (ndbm_map_open(map, mode)) 130760089Seric { 130860089Seric return TRUE; 130960089Seric } 131060207Seric else 131160207Seric map->map_mflags &= ~MF_IMPL_NDBM; 131260089Seric #endif 131356822Seric 131464650Seric #if defined(NEWDB) || defined(NDBM) 131560089Seric if (Verbose) 131660089Seric message("WARNING: cannot open alias database %s", map->map_file); 131764964Seric #else 131864964Seric if (mode != O_RDONLY) 131964964Seric usrerr("Cannot rebuild aliases: no database format defined"); 132060207Seric #endif 132160089Seric 132260207Seric return stab_map_open(map, mode); 132356822Seric } 132460089Seric 132560207Seric 132660089Seric /* 132760207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 132860089Seric */ 132960089Seric 133060089Seric void 133160207Seric impl_map_close(map) 133260089Seric MAP *map; 133360089Seric { 133460089Seric #ifdef NEWDB 133560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 133660089Seric { 133760207Seric db_map_close(map); 133860207Seric map->map_mflags &= ~MF_IMPL_HASH; 133960089Seric } 134060089Seric #endif 134160089Seric 134260089Seric #ifdef NDBM 134360207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 134460089Seric { 134560207Seric ndbm_map_close(map); 134660207Seric map->map_mflags &= ~MF_IMPL_NDBM; 134760089Seric } 134860089Seric #endif 134960089Seric } 135060207Seric /* 135167726Seric ** User map class. 135267726Seric ** 135367726Seric ** Provides access to the system password file. 135467726Seric */ 135567726Seric 135667726Seric /* 135767726Seric ** USER_MAP_OPEN -- open user map 135867726Seric ** 135967726Seric ** Really just binds field names to field numbers. 136067726Seric */ 136167726Seric 136267726Seric bool 136367726Seric user_map_open(map, mode) 136467726Seric MAP *map; 136567726Seric int mode; 136667726Seric { 136767726Seric if (tTd(38, 2)) 136867726Seric printf("user_map_open(%s)\n", map->map_mname); 136967726Seric 137067726Seric if (mode != O_RDONLY) 137167726Seric { 137267726Seric /* issue a pseudo-error message */ 137367726Seric #ifdef ENOSYS 137467726Seric errno = ENOSYS; 137567726Seric #else 137667726Seric # ifdef EFTYPE 137767726Seric errno = EFTYPE; 137867726Seric # else 137967726Seric errno = ENXIO; 138067726Seric # endif 138167726Seric #endif 138267726Seric return FALSE; 138367726Seric } 138467726Seric if (map->map_valcolnm == NULL) 138567726Seric /* nothing */ ; 138667726Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 138767726Seric map->map_valcolno = 1; 138867726Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 138967726Seric map->map_valcolno = 2; 139067726Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 139167726Seric map->map_valcolno = 3; 139267726Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 139367726Seric map->map_valcolno = 4; 139467726Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 139567726Seric map->map_valcolno = 5; 139667726Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 139767726Seric map->map_valcolno = 6; 139867726Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 139967726Seric map->map_valcolno = 7; 140067726Seric else 140167726Seric { 140267726Seric syserr("User map %s: unknown column name %s", 140367726Seric map->map_mname, map->map_valcolnm); 140467726Seric return FALSE; 140567726Seric } 140667726Seric return TRUE; 140767726Seric } 140867726Seric 140967726Seric 141067726Seric /* 141167726Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 141267726Seric */ 141367726Seric 141467726Seric #include <pwd.h> 141567726Seric 141667726Seric char * 141767726Seric user_map_lookup(map, key, av, statp) 141867726Seric MAP *map; 141967726Seric char *key; 142067726Seric char **av; 142167726Seric int *statp; 142267726Seric { 142367726Seric struct passwd *pw; 142467726Seric 142567726Seric if (tTd(38, 20)) 142667726Seric printf("user_map_lookup(%s, %s)\n", 142767726Seric map->map_mname, key); 142867726Seric 142967726Seric pw = getpwnam(key); 143067726Seric if (pw == NULL) 143167726Seric return NULL; 143267726Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 143367726Seric return map_rewrite(map, key, strlen(key), NULL); 143467726Seric else 143567726Seric { 143667726Seric char *rwval; 143767726Seric char buf[30]; 143867726Seric 143967726Seric switch (map->map_valcolno) 144067726Seric { 144167726Seric case 0: 144267726Seric case 1: 144367726Seric rwval = key; 144467726Seric break; 144567726Seric 144667726Seric case 2: 144767726Seric rwval = pw->pw_passwd; 144867726Seric break; 144967726Seric 145067726Seric case 3: 145167726Seric sprintf(buf, "%d", pw->pw_uid); 145267726Seric rwval = buf; 145367726Seric break; 145467726Seric 145567726Seric case 4: 145667726Seric sprintf(buf, "%d", pw->pw_gid); 145767726Seric rwval = buf; 145867726Seric break; 145967726Seric 146067726Seric case 5: 146167726Seric rwval = pw->pw_gecos; 146267726Seric break; 146367726Seric 146467726Seric case 6: 146567726Seric rwval = pw->pw_dir; 146667726Seric break; 146767726Seric 146867726Seric case 7: 146967726Seric rwval = pw->pw_shell; 147067726Seric break; 147167726Seric } 147267726Seric return map_rewrite(map, rwval, strlen(rwval), av); 147367726Seric } 147467726Seric } 147567726Seric /* 147667726Seric ** Sequenced map type. 147767726Seric ** 147867726Seric ** Tries each map in order until something matches, much like 147967726Seric ** implicit. Stores go to the first map in the list that can 148067726Seric ** support storing. 148167726Seric */ 148267726Seric 148367726Seric /* 148467726Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 148567726Seric */ 148667726Seric 148767726Seric bool 148867726Seric seq_map_parse(map, ap) 148967726Seric MAP *map; 149067726Seric char *ap; 149167726Seric { 149267726Seric int maxmap; 149367726Seric 149467726Seric if (tTd(38, 2)) 149567726Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 149667726Seric maxmap = 0; 149767726Seric while (*ap != '\0') 149867726Seric { 149967726Seric register char *p; 150067726Seric STAB *s; 150167726Seric 150267726Seric /* find beginning of map name */ 150367726Seric while (isascii(*ap) && isspace(*ap)) 150467726Seric ap++; 150567726Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 150667726Seric continue; 150767726Seric if (*p != '\0') 150867726Seric *p++ = '\0'; 150967726Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 151067726Seric p++; 151167726Seric if (*ap == '\0') 151267726Seric { 151367726Seric ap = p; 151467726Seric continue; 151567726Seric } 151667726Seric s = stab(ap, ST_MAP, ST_FIND); 151767726Seric if (s == NULL) 151867726Seric { 151967726Seric syserr("Sequence map %s: unknown member map %s", 152067726Seric map->map_mname, ap); 152167726Seric } 152267726Seric else if (maxmap == MAXMAPSTACK) 152367726Seric { 152467726Seric syserr("Sequence map %s: too many member maps (%d max)", 152567726Seric map->map_mname, MAXMAPSTACK); 152667726Seric maxmap++; 152767726Seric } 152867726Seric else if (maxmap < MAXMAPSTACK) 152967726Seric { 153067726Seric map->map_stack[maxmap++] = &s->s_map; 153167726Seric } 153267726Seric ap = p; 153367726Seric } 153467726Seric return TRUE; 153567726Seric } 153667726Seric 153767726Seric 153867726Seric /* 153967726Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 154067726Seric */ 154167726Seric 154267726Seric char * 154367726Seric seq_map_lookup(map, key, args, pstat) 154467726Seric MAP *map; 154567726Seric char *key; 154667726Seric char **args; 154767726Seric int *pstat; 154867726Seric { 154967726Seric int mapno; 155067726Seric int mapbit = 0x01; 155167726Seric 155267726Seric if (tTd(38, 20)) 155367726Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 155467726Seric 155567726Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 155667726Seric { 155767726Seric MAP *mm = map->map_stack[mapno]; 155867726Seric int stat = 0; 155967726Seric char *rv; 156067726Seric 156167726Seric if (mm == NULL) 156267726Seric continue; 156367726Seric if (!bitset(MF_OPEN, mm->map_mflags)) 156467726Seric { 156567726Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 156667726Seric return NULL; 156767726Seric continue; 156867726Seric } 156967726Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 157067726Seric if (rv != NULL) 157167726Seric return rv; 157267726Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 157367726Seric return NULL; 157467726Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 157567726Seric { 157667726Seric *pstat = stat; 157767726Seric return NULL; 157867726Seric } 157967726Seric } 158067726Seric return NULL; 158167726Seric } 158267726Seric 158367726Seric 158467726Seric /* 158567726Seric ** SEQ_MAP_STORE -- sequenced map store 158667726Seric */ 158767726Seric 158867726Seric void 158967726Seric seq_map_store(map, key, val) 159067726Seric MAP *map; 159167726Seric char *key; 159267726Seric char *val; 159367726Seric { 159467726Seric int mapno; 159567726Seric 159667726Seric if (tTd(38, 12)) 159767726Seric printf("seq_map_store(%s, %s, %s)\n", 159867726Seric map->map_mname, key, val); 159967726Seric 160067726Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 160167726Seric { 160267726Seric MAP *mm = map->map_stack[mapno]; 160367726Seric 160467726Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 160567726Seric continue; 160667726Seric 160767726Seric mm->map_class->map_store(mm, key, val); 160867726Seric return; 160967726Seric } 161067726Seric syserr("seq_map_store(%s, %s, %s): no writable map", 161167726Seric map->map_mname, key, val); 161267726Seric } 161367726Seric /* 161460207Seric ** NULL stubs 161560089Seric */ 161660089Seric 161760207Seric bool 161860207Seric null_map_open(map, mode) 161960089Seric MAP *map; 162060207Seric int mode; 162160089Seric { 162260207Seric return TRUE; 162360089Seric } 162460089Seric 162560207Seric void 162660207Seric null_map_close(map) 162760207Seric MAP *map; 162860089Seric { 162960207Seric return; 163060207Seric } 163160089Seric 163260207Seric void 163360207Seric null_map_store(map, key, val) 163460207Seric MAP *map; 163560207Seric char *key; 163660207Seric char *val; 163760089Seric { 163860207Seric return; 163960089Seric } 1640