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*67857Seric static char sccsid[] = "@(#)map.c 8.34 (Berkeley) 10/25/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 /* 109067848Seric ** NISPLUS Modules 109167848Seric ** 109267848Seric ** This code donated by Sun Microsystems. 109367848Seric */ 109467848Seric 109567848Seric #ifdef NISPLUS 109667848Seric 109767848Seric #undef NIS /* symbol conflict in nis.h */ 109867848Seric #include <rpcsvc/nis.h> 109967848Seric #include <rpcsvc/nislib.h> 110067848Seric 110167848Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 110267848Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 110367848Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 110467848Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 110567848Seric 110667848Seric /* 110767848Seric ** NISPLUS_MAP_OPEN -- open nisplus table 110867848Seric */ 110967848Seric 111067848Seric bool 111167848Seric nisplus_map_open(map, mode) 111267848Seric MAP *map; 111367848Seric int mode; 111467848Seric { 111567848Seric register char *p; 111667848Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 111767848Seric nis_result *res = NULL; 111867848Seric u_int objs_len; 111967848Seric nis_object *obj_ptr; 112067848Seric int retry_cnt, max_col, i; 112167848Seric 112267848Seric if (tTd(38, 2)) 112367848Seric printf("nisplus_map_open(%s, %s, %d)\n", 112467848Seric map->map_mname, map->map_file, mode); 112567848Seric 112667848Seric if (mode != O_RDONLY) 112767848Seric { 112867848Seric errno = ENODEV; 112967848Seric return FALSE; 113067848Seric } 113167848Seric 113267848Seric if (*map->map_file == '\0') 113367848Seric map->map_file = "mail_aliases.org_dir"; 113467848Seric 113567848Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 113667848Seric { 113767848Seric /* set default NISPLUS Domain to $m */ 113867848Seric extern char *nisplus_default_domain(); 113967848Seric 114067848Seric map->map_domain = newstr(nisplus_default_domain()); 114167848Seric if (tTd(38, 2)) 114267848Seric printf("nisplus_map_open(%s): using domain %s\n", 114367848Seric map->map_file, map->map_domain); 114467848Seric } 114567848Seric if (!PARTIAL_NAME(map->map_file)) 114667848Seric map->map_domain = newstr(""); 114767848Seric 114867848Seric /* check to see if this map actually exists */ 114967848Seric if (PARTIAL_NAME(map->map_file)) 115067848Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 115167848Seric else 115267848Seric strcpy(qbuf, map->map_file); 115367848Seric 115467848Seric retry_cnt = 0; 115567848Seric while (res == NULL || res->status != NIS_SUCCESS) 115667848Seric { 115767848Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 115867848Seric switch (res->status) 115967848Seric { 116067848Seric case NIS_SUCCESS: 116167848Seric case NIS_TRYAGAIN: 116267848Seric case NIS_RPCERROR: 116367848Seric case NIS_NAMEUNREACHABLE: 116467848Seric break; 116567848Seric 116667848Seric default: /* all other nisplus errors */ 116767848Seric #if 0 116867848Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 116967848Seric syserr("Cannot find table %s.%s: %s", 117067848Seric map->map_file, map->map_domain, 117167848Seric nis_sperrno(res->status)); 117267848Seric #endif 117367848Seric errno = EBADR; 117467848Seric return FALSE; 117567848Seric } 117667848Seric sleep(2); /* try not to overwhelm hosed server */ 117767848Seric if (retry_cnt++ > 4) 117867848Seric { 117967848Seric errno = EBADR; 118067848Seric return FALSE; 118167848Seric } 118267848Seric } 118367848Seric 118467848Seric if (NIS_RES_NUMOBJ(res) != 1 || 118567848Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 118667848Seric { 118767848Seric if (tTd(38, 10)) 118867848Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 118967848Seric #if 0 119067848Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 119167848Seric syserr("%s.%s: %s is not a table", 119267848Seric map->map_file, map->map_domain, 119367848Seric nis_sperrno(res->status)); 119467848Seric #endif 119567848Seric errno = EBADR; 119667848Seric return FALSE; 119767848Seric } 119867848Seric /* default key column is column 0 */ 119967848Seric if (map->map_keycolnm == NULL) 120067848Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 120167848Seric 120267848Seric max_col = COL_MAX(res); 120367848Seric 120467848Seric /* verify the key column exist */ 120567848Seric for (i=0; i< max_col; i++) 120667848Seric { 120767848Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 120867848Seric break; 120967848Seric } 121067848Seric if (i == max_col) 121167848Seric { 121267848Seric if (tTd(38, 2)) 121367848Seric printf("nisplus_map_open(%s): can not find key column %s\n", 121467848Seric map->map_file, map->map_keycolnm); 121567848Seric errno = EBADR; 121667848Seric return FALSE; 121767848Seric } 121867848Seric 121967848Seric /* default value column is the last column */ 122067848Seric if (map->map_valcolnm == NULL) 122167848Seric { 122267848Seric map->map_valcolno = max_col - 1; 122367848Seric return TRUE; 122467848Seric } 122567848Seric 122667848Seric for (i=0; i< max_col; i++) 122767848Seric { 122867848Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 122967848Seric { 123067848Seric map->map_valcolno = i; 123167848Seric return TRUE; 123267848Seric } 123367848Seric } 123467848Seric 123567848Seric if (tTd(38, 2)) 123667848Seric printf("nisplus_map_open(%s): can not find column %s\n", 123767848Seric map->map_file, map->map_keycolnm); 123867848Seric errno = EBADR; 123967848Seric return FALSE; 124067848Seric } 124167848Seric 124267848Seric 124367848Seric /* 124467848Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 124567848Seric */ 124667848Seric 124767848Seric char * 124867848Seric nisplus_map_lookup(map, name, av, statp) 124967848Seric MAP *map; 125067848Seric char *name; 125167848Seric char **av; 125267848Seric int *statp; 125367848Seric { 125467848Seric char *vp; 125567848Seric auto int vsize; 125667848Seric int buflen; 125767848Seric char search_key[MAXNAME + 1]; 125867848Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 125967848Seric nis_result *result; 126067848Seric 126167848Seric if (tTd(38, 20)) 126267848Seric printf("nisplus_map_lookup(%s, %s)\n", 126367848Seric map->map_mname, name); 126467848Seric 126567848Seric if (!bitset(MF_OPEN, map->map_mflags)) 126667848Seric { 126767848Seric if (nisplus_map_open(map, O_RDONLY)) 126867848Seric map->map_mflags |= MF_OPEN; 126967848Seric else 127067848Seric { 127167848Seric *statp = EX_UNAVAILABLE; 127267848Seric return NULL; 127367848Seric } 127467848Seric } 127567848Seric 127667848Seric buflen = strlen(name); 127767848Seric if (buflen > sizeof search_key - 1) 127867848Seric buflen = sizeof search_key - 1; 127967848Seric bcopy(name, search_key, buflen + 1); 128067848Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 128167848Seric makelower(search_key); 128267848Seric 128367848Seric /* construct the query */ 128467848Seric if (PARTIAL_NAME(map->map_file)) 128567848Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 128667848Seric search_key, map->map_file, map->map_domain); 128767848Seric else 128867848Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 128967848Seric search_key, map->map_file); 129067848Seric 129167848Seric if (tTd(38, 20)) 129267848Seric printf("qbuf=%s\n", qbuf); 129367848Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 129467848Seric if (result->status == NIS_SUCCESS) 129567848Seric { 129667848Seric int count; 129767848Seric char *str; 129867848Seric 129967848Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 130067848Seric { 130167848Seric if (LogLevel > 10) 130267848Seric syslog(LOG_WARNING, 130367848Seric "%s:Lookup error, expected 1 entry, got (%d)", 130467848Seric map->map_file, count); 130567848Seric 130667848Seric /* ignore second entry */ 130767848Seric if (tTd(38, 20)) 130867848Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 130967848Seric name, count); 131067848Seric } 131167848Seric 131267848Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 131367848Seric /* set the length of the result */ 131467848Seric if (vp == NULL) 131567848Seric vp = ""; 131667848Seric vsize = strlen(vp); 131767848Seric if (tTd(38, 20)) 131867848Seric printf("nisplus_map_lookup(%s), found %s\n", 131967848Seric name, vp); 132067848Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 132167848Seric str = map_rewrite(map, name, strlen(name), NULL); 132267848Seric else 132367848Seric str = map_rewrite(map, vp, vsize, av); 132467848Seric nis_freeresult(result); 132567848Seric #ifdef MAP_EXIT_STAT 132667848Seric *statp = EX_OK; 132767848Seric #endif 132867848Seric return str; 132967848Seric } 133067848Seric else 133167848Seric { 133267848Seric #ifdef MAP_EXIT_STAT 133367848Seric if (result->status == NIS_NOTFOUND) 133467848Seric *statp = EX_NOTFOUND; 133567848Seric else if (result->status == NIS_TRYAGAIN) 133667848Seric *statp = EX_TEMPFAIL; 133767848Seric else 133867848Seric { 133967848Seric *statp = EX_UNAVAILABLE; 134067848Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 134167848Seric } 134267848Seric #else 134367848Seric if ((result->status != NIS_NOTFOUND) && 134467848Seric (result->status != NIS_TRYAGAIN)) 134567848Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 134667848Seric #endif 134767848Seric } 134867848Seric if (tTd(38, 20)) 134967848Seric printf("nisplus_map_lookup(%s), failed\n", name); 135067848Seric nis_freeresult(result); 135167848Seric return NULL; 135267848Seric } 135367848Seric 135467848Seric 135567848Seric char * 135667848Seric nisplus_default_domain() 135767848Seric { 135867848Seric static char default_domain[MAXNAME] = ""; 135967848Seric nis_result *res = NULL; 136067848Seric char *p; 136167848Seric 136267848Seric if (default_domain[0] != '\0') 136367848Seric return(default_domain); 136467848Seric 136567848Seric if (VendorCode == VENDOR_SUN && ConfigLevel < 2) 136667848Seric { 136767848Seric /* for old config, user nis+ local directory */ 136867848Seric /* have to be backward compatible with bugs too :-( */ 136967848Seric p = nis_local_directory(); 137067848Seric strcpy(default_domain, p); 137167848Seric return default_domain; 137267848Seric } 137367848Seric 137467848Seric if ((p = macvalue('m', CurEnv)) == NULL) 137567848Seric { 137667848Seric p = nis_local_directory(); 137767848Seric strcpy(default_domain, p); 137867848Seric return default_domain; 137967848Seric } 138067848Seric 138167848Seric strcpy(default_domain, p); 138267848Seric if (PARTIAL_NAME(default_domain)) 138367848Seric strcat(default_domain, "."); 138467848Seric 138567848Seric res = nis_lookup(default_domain, FOLLOW_LINKS); 138667848Seric if (res->status == NIS_NOTFOUND) 138767848Seric { 138867848Seric p = nis_local_directory(); 138967848Seric strcpy(default_domain, p); 139067848Seric } 139167848Seric return(default_domain); 139267848Seric } 139367848Seric 139467848Seric #endif /* NISPLUS */ 139567848Seric /* 139667832Seric ** HESIOD Modules 139767832Seric ** 139867832Seric ** Only works for aliases (for now). 139967832Seric */ 140067832Seric 140167832Seric #ifdef HESIOD 140267832Seric 140367832Seric char * 140467832Seric hes_map_lookup(map, name, av, statp) 140567832Seric MAP *map; 140667832Seric char *name; 140767832Seric char **av; 140867832Seric int *statp; 140967832Seric { 141067832Seric struct hes_postoffice *pobox; 141167832Seric char keybuf[MAXNAME + 1]; 141267832Seric 141367832Seric if (tTd(38, 20)) 141467832Seric printf("hes_map_lookup(%s)\n", name); 141567832Seric 141667832Seric pobox = hes_getmailhost(name); 141767832Seric if (pobox == NULL) 141867832Seric return NULL; 141967832Seric 142067832Seric /* We only know how to deal with the SMTP types right now */ 142167832Seric if (strcmp(pobox->po_type, "SMTP") != 0 && 142267832Seric strcmp(pobox->po_type, "ESMTP") != 0) 142367832Seric return NULL; 142467832Seric 142567832Seric /* if just checking for a match, we are done */ 142667832Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 142767832Seric return map_rewrite(map, name, strlen(name), NULL); 142867832Seric 142967832Seric /* Do the rewriting with new values */ 143067832Seric if (strlen(pobox->po_name) + strlen(pobox->po_host) + 1 > sizeof keybuf) 143167848Seric { 143267848Seric *statp = EX_DATAERR; 143367832Seric return NULL; 143467848Seric } 143567832Seric (void) sprintf(keybuf, "%s@%s", pobox->po_name, pobox->po_host); 143667832Seric return map_rewrite(map, keybuf, strlen(keybuf), av); 143767832Seric } 143867832Seric 143967832Seric #endif 144067832Seric /* 144167842Seric ** NeXT NETINFO Modules 144267842Seric */ 144367842Seric 144467842Seric #ifdef NETINFO 144567842Seric 144667842Seric #define NETINFO_DEFAULT_DIR "/aliases" 144767842Seric #define NETINFO_DEFAULT_PROPERTY "members" 144867842Seric 144967842Seric 145067842Seric /* 145167842Seric ** NI_MAP_OPEN -- open NetInfo Aliases 145267842Seric */ 145367842Seric 145467848Seric bool 145567842Seric ni_map_open(map, mode) 145667842Seric MAP *map; 145767842Seric int mode; 145867842Seric { 145967842Seric char *p; 146067842Seric 146167842Seric if (tTd(38, 20)) 146267842Seric printf("ni_map_open: %s\n", map->map_file); 146367842Seric 146467842Seric p = strchr(map->map_file, '@'); 146567842Seric if (p != NULL) 146667842Seric { 146767842Seric *p++ = '\0'; 146867842Seric if (*p != '\0') 146967842Seric map->map_domain = p; 147067842Seric } 147167842Seric if (*map->map_file == '\0') 147267842Seric map->map_file = NETINFO_DEFAULT_DIR; 147367842Seric 147467842Seric if (map->map_domain == NULL) 147567842Seric map->map_domain = NETINFO_DEFAULT_PROPERTY; 147667842Seric 1477*67857Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 1478*67857Seric map->map_coldelim = ','; 147967842Seric 148067842Seric return TRUE; 148167842Seric } 148267842Seric 148367842Seric 148467842Seric /* 148567842Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 148667842Seric */ 148767842Seric 148867842Seric char * 148967842Seric ni_map_lookup(map, name, av, statp) 149067842Seric MAP *map; 149167842Seric char *name; 149267842Seric char **av; 149367842Seric int *statp; 149467842Seric { 149567842Seric char *res; 149667842Seric char *propval; 149767842Seric extern char *ni_propval(); 149867842Seric 149967842Seric if (tTd(38, 20)) 150067848Seric printf("ni_map_lookup(%s, %s)\n", 150167842Seric map->map_mname, name); 150267842Seric 150367842Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 150467842Seric map->map_valcolnm, map->map_coldelim); 150567842Seric 150667848Seric if (propval == NULL) 150767842Seric return NULL; 150867842Seric 150967842Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 151067842Seric res = map_rewrite(map, name, strlen(name), NULL); 151167842Seric else 151267842Seric res = map_rewrite(map, propval, strlen(propval), av); 151367842Seric free(propval); 151467842Seric return res; 151567842Seric } 151667842Seric 151767842Seric #endif 151867842Seric /* 151967848Seric ** TEXT (unindexed text file) Modules 152067848Seric ** 152167848Seric ** This code donated by Sun Microsystems. 152267848Seric */ 152367848Seric 152467848Seric 152567848Seric /* 152667848Seric ** TEXT_MAP_OPEN -- open text table 152767848Seric */ 152867848Seric 152967848Seric bool 153067848Seric text_map_open(map, mode) 153167848Seric MAP *map; 153267848Seric int mode; 153367848Seric { 153467848Seric struct stat sbuf; 153567848Seric 153667848Seric if (tTd(38, 2)) 153767848Seric printf("text_map_open(%s, %s, %d)\n", 153867848Seric map->map_mname, map->map_file, mode); 153967848Seric 154067848Seric if (mode != O_RDONLY) 154167848Seric { 154267848Seric errno = ENODEV; 154367848Seric return FALSE; 154467848Seric } 154567848Seric 154667848Seric if (*map->map_file == '\0') 154767848Seric { 154867848Seric if (tTd(38, 2)) 154967848Seric printf("text_map_open: file name required\n"); 155067848Seric return FALSE; 155167848Seric } 155267848Seric 155367848Seric if (map->map_file[0] != '/') 155467848Seric { 155567848Seric if (tTd(38, 2)) 155667848Seric printf("text_map_open(%s): file name must be fully qualified\n", 155767848Seric map->map_file); 155867848Seric return FALSE; 155967848Seric } 156067848Seric /* check to see if this map actually accessable */ 156167848Seric if (access(map->map_file, R_OK) <0) 156267848Seric return FALSE; 156367848Seric 156467848Seric /* check to see if this map actually exist */ 156567848Seric if (stat(map->map_file, &sbuf) <0) 156667848Seric { 156767848Seric if (tTd(38, 2)) 156867848Seric printf("text_map_open(%s): can not stat %s\n", 156967848Seric map->map_file, map->map_file); 157067848Seric return FALSE; 157167848Seric } 157267848Seric 157367848Seric if (!S_ISREG(sbuf.st_mode)) 157467848Seric { 157567848Seric if (tTd(38, 2)) 157667848Seric printf("text_map_open(%s): %s is not a file\n", 157767848Seric map->map_file, map->map_file); 157867848Seric return FALSE; 157967848Seric } 158067848Seric 158167848Seric if (map->map_keycolnm == NULL) 158267848Seric map->map_keycolno = 0; 158367848Seric else 158467848Seric { 158567848Seric if (!isdigit(*map->map_keycolnm)) 158667848Seric { 158767848Seric if (tTd(38, 2)) 158867848Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 158967848Seric map->map_file, map->map_keycolnm); 159067848Seric return FALSE; 159167848Seric } 159267848Seric map->map_keycolno = atoi(map->map_keycolnm); 159367848Seric } 159467848Seric 159567848Seric if (map->map_valcolnm == NULL) 159667848Seric map->map_valcolno = 0; 159767848Seric else 159867848Seric { 159967848Seric if (!isdigit(*map->map_valcolnm)) 160067848Seric { 160167848Seric if (tTd(38, 2)) 160267848Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 160367848Seric map->map_file, map->map_valcolnm); 160467848Seric return FALSE; 160567848Seric } 160667848Seric map->map_valcolno = atoi(map->map_valcolnm); 160767848Seric } 160867848Seric 160967848Seric if (map->map_coldelim == '\0') 161067848Seric map->map_coldelim = ':'; 161167848Seric 161267848Seric if (tTd(38, 2)) 161367848Seric { 161467848Seric printf("text_map_open(%s): delimiter = %c\n", 161567848Seric map->map_file, map->map_coldelim); 161667848Seric } 161767848Seric 161867848Seric return TRUE; 161967848Seric } 162067848Seric 162167848Seric 162267848Seric /* 162367848Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 162467848Seric */ 162567848Seric 162667848Seric char * 162767848Seric text_map_lookup(map, name, av, statp) 162867848Seric MAP *map; 162967848Seric char *name; 163067848Seric char **av; 163167848Seric int *statp; 163267848Seric { 163367848Seric char *vp; 163467848Seric auto int vsize; 163567848Seric int buflen; 163667848Seric char search_key[MAXNAME + 1]; 163767848Seric char linebuf[MAXLINE]; 163867848Seric FILE *f; 163967848Seric char buf[MAXNAME+1]; 164067848Seric char delim; 164167848Seric int key_idx; 164267848Seric bool found_it; 164367848Seric extern char *get_column(); 164467848Seric 164567848Seric 164667848Seric found_it = FALSE; 164767848Seric if (tTd(38, 20)) 164867848Seric printf("text_map_lookup(%s)\n", name); 164967848Seric 165067848Seric buflen = strlen(name); 165167848Seric if (buflen > sizeof search_key - 1) 165267848Seric buflen = sizeof search_key - 1; 165367848Seric bcopy(name, search_key, buflen + 1); 165467848Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 165567848Seric makelower(search_key); 165667848Seric 165767848Seric f = fopen(map->map_file, "r"); 165867848Seric if (f == NULL) 165967848Seric { 166067848Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 166167848Seric *statp = EX_UNAVAILABLE; 166267848Seric return NULL; 166367848Seric } 166467848Seric key_idx = map->map_keycolno; 166567848Seric delim = map->map_coldelim; 166667848Seric while (fgets(linebuf, MAXLINE, f)) 166767848Seric { 166867848Seric char *lf; 166967848Seric if (linebuf[0] == '#') 167067848Seric continue; /* skip comment line */ 167167848Seric if (lf = strchr(linebuf, '\n')) 167267848Seric *lf = '\0'; 167367848Seric if (!strcasecmp(search_key, 167467848Seric get_column(linebuf, key_idx, delim, buf))) 167567848Seric { 167667848Seric found_it = TRUE; 167767848Seric break; 167867848Seric } 167967848Seric } 168067848Seric fclose(f); 168167848Seric if (!found_it) 168267848Seric { 168367848Seric #ifdef MAP_EXIT_STAT 168467848Seric *statp = EX_NOTFOUND; 168567848Seric #endif 168667848Seric return(NULL); 168767848Seric } 168867848Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 168967848Seric vsize = strlen(vp); 169067848Seric #ifdef MAP_EXIT_STAT 169167848Seric *statp = EX_OK; 169267848Seric #endif 169367848Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 169467848Seric return map_rewrite(map, name, strlen(name), NULL); 169567848Seric else 169667848Seric return map_rewrite(map, vp, vsize, av); 169767848Seric } 169867848Seric /* 169960089Seric ** STAB (Symbol Table) Modules 170060089Seric */ 170160089Seric 170260089Seric 170360089Seric /* 170460207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 170560089Seric */ 170660089Seric 170760089Seric char * 170861707Seric stab_map_lookup(map, name, av, pstat) 170960089Seric register MAP *map; 171060089Seric char *name; 171161707Seric char **av; 171261707Seric int *pstat; 171360089Seric { 171460089Seric register STAB *s; 171560089Seric 171660537Seric if (tTd(38, 20)) 171767726Seric printf("stab_lookup(%s, %s)\n", 171867726Seric map->map_mname, name); 171960089Seric 172060089Seric s = stab(name, ST_ALIAS, ST_FIND); 172160089Seric if (s != NULL) 172260089Seric return (s->s_alias); 172360089Seric return (NULL); 172460089Seric } 172560089Seric 172660089Seric 172760089Seric /* 172860207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 172960089Seric */ 173060089Seric 173160089Seric void 173260089Seric stab_map_store(map, lhs, rhs) 173360089Seric register MAP *map; 173460089Seric char *lhs; 173560089Seric char *rhs; 173660089Seric { 173760089Seric register STAB *s; 173860089Seric 173960089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 174060089Seric s->s_alias = newstr(rhs); 174160089Seric } 174260089Seric 174360089Seric 174460089Seric /* 174560207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 174660207Seric ** 174760207Seric ** This is a wierd case -- it is only intended as a fallback for 174860207Seric ** aliases. For this reason, opens for write (only during a 174960207Seric ** "newaliases") always fails, and opens for read open the 175060207Seric ** actual underlying text file instead of the database. 175160089Seric */ 175260089Seric 175360089Seric bool 175460089Seric stab_map_open(map, mode) 175560089Seric register MAP *map; 175660089Seric int mode; 175760089Seric { 175863835Seric FILE *af; 175964284Seric struct stat st; 176063835Seric 176160537Seric if (tTd(38, 2)) 176267726Seric printf("stab_map_open(%s, %s)\n", 176367726Seric map->map_mname, map->map_file); 176460089Seric 176560089Seric if (mode != O_RDONLY) 176660207Seric { 176760207Seric errno = ENODEV; 176860089Seric return FALSE; 176960207Seric } 177060089Seric 177163835Seric af = fopen(map->map_file, "r"); 177263835Seric if (af == NULL) 177363835Seric return FALSE; 177467263Seric readaliases(map, af, FALSE, FALSE); 177564284Seric 177664284Seric if (fstat(fileno(af), &st) >= 0) 177764284Seric map->map_mtime = st.st_mtime; 177863835Seric fclose(af); 177963835Seric 178060089Seric return TRUE; 178160089Seric } 178260089Seric /* 178360089Seric ** Implicit Modules 178456822Seric ** 178560089Seric ** Tries several types. For back compatibility of aliases. 178656822Seric */ 178756822Seric 178860089Seric 178960089Seric /* 179060207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 179160089Seric */ 179260089Seric 179360089Seric char * 179460089Seric impl_map_lookup(map, name, av, pstat) 179560089Seric MAP *map; 179660089Seric char *name; 179756822Seric char **av; 179860089Seric int *pstat; 179956822Seric { 180060537Seric if (tTd(38, 20)) 180167726Seric printf("impl_map_lookup(%s, %s)\n", 180267726Seric map->map_mname, name); 180356822Seric 180460089Seric #ifdef NEWDB 180560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 180660089Seric return db_map_lookup(map, name, av, pstat); 180760089Seric #endif 180860089Seric #ifdef NDBM 180960207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 181060089Seric return ndbm_map_lookup(map, name, av, pstat); 181160089Seric #endif 181260089Seric return stab_map_lookup(map, name, av, pstat); 181360089Seric } 181460089Seric 181560089Seric /* 181660207Seric ** IMPL_MAP_STORE -- store in open databases 181760089Seric */ 181860089Seric 181960089Seric void 182060089Seric impl_map_store(map, lhs, rhs) 182160089Seric MAP *map; 182260089Seric char *lhs; 182360089Seric char *rhs; 182460089Seric { 182560089Seric #ifdef NEWDB 182660207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 182760089Seric db_map_store(map, lhs, rhs); 182860089Seric #endif 182960089Seric #ifdef NDBM 183060207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 183160089Seric ndbm_map_store(map, lhs, rhs); 183260089Seric #endif 183360089Seric stab_map_store(map, lhs, rhs); 183460089Seric } 183560089Seric 183660089Seric /* 183760089Seric ** IMPL_MAP_OPEN -- implicit database open 183860089Seric */ 183960089Seric 184060089Seric bool 184160089Seric impl_map_open(map, mode) 184260089Seric MAP *map; 184360089Seric int mode; 184460089Seric { 184560089Seric struct stat stb; 184660089Seric 184760537Seric if (tTd(38, 2)) 184867726Seric printf("impl_map_open(%s, %s, %d)\n", 184967726Seric map->map_mname, map->map_file, mode); 185060089Seric 185160089Seric if (stat(map->map_file, &stb) < 0) 185256822Seric { 185360089Seric /* no alias file at all */ 185464718Seric if (tTd(38, 3)) 185564718Seric printf("no map file\n"); 185660089Seric return FALSE; 185756822Seric } 185856822Seric 185960089Seric #ifdef NEWDB 186060207Seric map->map_mflags |= MF_IMPL_HASH; 186160089Seric if (hash_map_open(map, mode)) 186256822Seric { 186364250Seric #if defined(NDBM) && defined(NIS) 186460561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 186560207Seric #endif 186660207Seric return TRUE; 186760089Seric } 186860207Seric else 186960207Seric map->map_mflags &= ~MF_IMPL_HASH; 187060089Seric #endif 187160089Seric #ifdef NDBM 187260207Seric map->map_mflags |= MF_IMPL_NDBM; 187360089Seric if (ndbm_map_open(map, mode)) 187460089Seric { 187560089Seric return TRUE; 187660089Seric } 187760207Seric else 187860207Seric map->map_mflags &= ~MF_IMPL_NDBM; 187960089Seric #endif 188056822Seric 188164650Seric #if defined(NEWDB) || defined(NDBM) 188260089Seric if (Verbose) 188360089Seric message("WARNING: cannot open alias database %s", map->map_file); 188464964Seric #else 188564964Seric if (mode != O_RDONLY) 188664964Seric usrerr("Cannot rebuild aliases: no database format defined"); 188760207Seric #endif 188860089Seric 188960207Seric return stab_map_open(map, mode); 189056822Seric } 189160089Seric 189260207Seric 189360089Seric /* 189460207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 189560089Seric */ 189660089Seric 189760089Seric void 189860207Seric impl_map_close(map) 189960089Seric MAP *map; 190060089Seric { 190160089Seric #ifdef NEWDB 190260207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 190360089Seric { 190460207Seric db_map_close(map); 190560207Seric map->map_mflags &= ~MF_IMPL_HASH; 190660089Seric } 190760089Seric #endif 190860089Seric 190960089Seric #ifdef NDBM 191060207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 191160089Seric { 191260207Seric ndbm_map_close(map); 191360207Seric map->map_mflags &= ~MF_IMPL_NDBM; 191460089Seric } 191560089Seric #endif 191660089Seric } 191760207Seric /* 191867726Seric ** User map class. 191967726Seric ** 192067726Seric ** Provides access to the system password file. 192167726Seric */ 192267726Seric 192367726Seric /* 192467726Seric ** USER_MAP_OPEN -- open user map 192567726Seric ** 192667726Seric ** Really just binds field names to field numbers. 192767726Seric */ 192867726Seric 192967726Seric bool 193067726Seric user_map_open(map, mode) 193167726Seric MAP *map; 193267726Seric int mode; 193367726Seric { 193467726Seric if (tTd(38, 2)) 193567726Seric printf("user_map_open(%s)\n", map->map_mname); 193667726Seric 193767726Seric if (mode != O_RDONLY) 193867726Seric { 193967726Seric /* issue a pseudo-error message */ 194067726Seric #ifdef ENOSYS 194167726Seric errno = ENOSYS; 194267726Seric #else 194367726Seric # ifdef EFTYPE 194467726Seric errno = EFTYPE; 194567726Seric # else 194667726Seric errno = ENXIO; 194767726Seric # endif 194867726Seric #endif 194967726Seric return FALSE; 195067726Seric } 195167726Seric if (map->map_valcolnm == NULL) 195267726Seric /* nothing */ ; 195367726Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 195467726Seric map->map_valcolno = 1; 195567726Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 195667726Seric map->map_valcolno = 2; 195767726Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 195867726Seric map->map_valcolno = 3; 195967726Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 196067726Seric map->map_valcolno = 4; 196167726Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 196267726Seric map->map_valcolno = 5; 196367726Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 196467726Seric map->map_valcolno = 6; 196567726Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 196667726Seric map->map_valcolno = 7; 196767726Seric else 196867726Seric { 196967726Seric syserr("User map %s: unknown column name %s", 197067726Seric map->map_mname, map->map_valcolnm); 197167726Seric return FALSE; 197267726Seric } 197367726Seric return TRUE; 197467726Seric } 197567726Seric 197667726Seric 197767726Seric /* 197867726Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 197967726Seric */ 198067726Seric 198167726Seric #include <pwd.h> 198267726Seric 198367726Seric char * 198467726Seric user_map_lookup(map, key, av, statp) 198567726Seric MAP *map; 198667726Seric char *key; 198767726Seric char **av; 198867726Seric int *statp; 198967726Seric { 199067726Seric struct passwd *pw; 199167726Seric 199267726Seric if (tTd(38, 20)) 199367726Seric printf("user_map_lookup(%s, %s)\n", 199467726Seric map->map_mname, key); 199567726Seric 199667726Seric pw = getpwnam(key); 199767726Seric if (pw == NULL) 199867726Seric return NULL; 199967726Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 200067726Seric return map_rewrite(map, key, strlen(key), NULL); 200167726Seric else 200267726Seric { 200367726Seric char *rwval; 200467726Seric char buf[30]; 200567726Seric 200667726Seric switch (map->map_valcolno) 200767726Seric { 200867726Seric case 0: 200967726Seric case 1: 201067848Seric rwval = pw->pw_name; 201167726Seric break; 201267726Seric 201367726Seric case 2: 201467726Seric rwval = pw->pw_passwd; 201567726Seric break; 201667726Seric 201767726Seric case 3: 201867726Seric sprintf(buf, "%d", pw->pw_uid); 201967726Seric rwval = buf; 202067726Seric break; 202167726Seric 202267726Seric case 4: 202367726Seric sprintf(buf, "%d", pw->pw_gid); 202467726Seric rwval = buf; 202567726Seric break; 202667726Seric 202767726Seric case 5: 202867726Seric rwval = pw->pw_gecos; 202967726Seric break; 203067726Seric 203167726Seric case 6: 203267726Seric rwval = pw->pw_dir; 203367726Seric break; 203467726Seric 203567726Seric case 7: 203667726Seric rwval = pw->pw_shell; 203767726Seric break; 203867726Seric } 203967726Seric return map_rewrite(map, rwval, strlen(rwval), av); 204067726Seric } 204167726Seric } 204267726Seric /* 204367726Seric ** Sequenced map type. 204467726Seric ** 204567726Seric ** Tries each map in order until something matches, much like 204667726Seric ** implicit. Stores go to the first map in the list that can 204767726Seric ** support storing. 204867848Seric ** 204967848Seric ** This is slightly unusual in that there are two interfaces. 205067848Seric ** The "sequence" interface lets you stack maps arbitrarily. 205167848Seric ** The "switch" interface builds a sequence map by looking 205267848Seric ** at a system-dependent configuration file such as 205367848Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 205467848Seric ** 205567848Seric ** We don't need an explicit open, since all maps are 205667848Seric ** opened during startup, including underlying maps. 205767726Seric */ 205867726Seric 205967726Seric /* 206067726Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 206167726Seric */ 206267726Seric 206367726Seric bool 206467726Seric seq_map_parse(map, ap) 206567726Seric MAP *map; 206667726Seric char *ap; 206767726Seric { 206867726Seric int maxmap; 206967726Seric 207067726Seric if (tTd(38, 2)) 207167726Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 207267726Seric maxmap = 0; 207367726Seric while (*ap != '\0') 207467726Seric { 207567726Seric register char *p; 207667726Seric STAB *s; 207767726Seric 207867726Seric /* find beginning of map name */ 207967726Seric while (isascii(*ap) && isspace(*ap)) 208067726Seric ap++; 208167726Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 208267726Seric continue; 208367726Seric if (*p != '\0') 208467726Seric *p++ = '\0'; 208567726Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 208667726Seric p++; 208767726Seric if (*ap == '\0') 208867726Seric { 208967726Seric ap = p; 209067726Seric continue; 209167726Seric } 209267726Seric s = stab(ap, ST_MAP, ST_FIND); 209367726Seric if (s == NULL) 209467726Seric { 209567726Seric syserr("Sequence map %s: unknown member map %s", 209667726Seric map->map_mname, ap); 209767726Seric } 209867726Seric else if (maxmap == MAXMAPSTACK) 209967726Seric { 210067726Seric syserr("Sequence map %s: too many member maps (%d max)", 210167726Seric map->map_mname, MAXMAPSTACK); 210267726Seric maxmap++; 210367726Seric } 210467726Seric else if (maxmap < MAXMAPSTACK) 210567726Seric { 210667726Seric map->map_stack[maxmap++] = &s->s_map; 210767726Seric } 210867726Seric ap = p; 210967726Seric } 211067726Seric return TRUE; 211167726Seric } 211267726Seric 211367726Seric 211467726Seric /* 211567848Seric ** SWITCH_MAP_OPEN -- open a switched map 211667848Seric ** 211767848Seric ** This looks at the system-dependent configuration and builds 211867848Seric ** a sequence map that does the same thing. 211967848Seric ** 212067848Seric ** Every system must define a switch_map_find routine in conf.c 212167848Seric ** that will return the list of service types associated with a 212267848Seric ** given service class. 212367848Seric */ 212467848Seric 212567848Seric bool 212667848Seric switch_map_open(map, mode) 212767848Seric MAP *map; 212867848Seric int mode; 212967848Seric { 213067848Seric int mapno; 213167848Seric int nmaps; 213267848Seric char *maptype[MAXMAPSTACK]; 213367848Seric 213467848Seric if (tTd(38, 2)) 213567848Seric printf("switch_map_open(%s, %s, %d)\n", 213667848Seric map->map_mname, map->map_file, mode); 213767848Seric 213867850Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 213967848Seric if (tTd(38, 19)) 214067848Seric { 214167848Seric printf("\tswitch_map_find => %d\n", nmaps); 214267848Seric for (mapno = 0; mapno < nmaps; mapno++) 214367848Seric printf("\t\t%s\n", maptype[mapno]); 214467848Seric } 214567848Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 214667848Seric return FALSE; 214767848Seric 214867848Seric for (mapno = 0; mapno < nmaps; mapno++) 214967848Seric { 215067848Seric register STAB *s; 215167848Seric char nbuf[MAXNAME + 1]; 215267848Seric 215367848Seric if (maptype[mapno] == NULL) 215467848Seric continue; 215567848Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 215667848Seric s = stab(nbuf, ST_MAP, ST_FIND); 215767848Seric if (s == NULL) 215867848Seric { 215967848Seric syserr("Switch map %s: unknown member map %s", 216067848Seric map->map_mname, nbuf); 216167848Seric } 216267848Seric else 216367848Seric { 216467848Seric map->map_stack[mapno] = &s->s_map; 216567848Seric if (tTd(38, 4)) 216667848Seric printf("\tmap_stack[%d] = %s:%s\n", 216767848Seric mapno, s->s_map.map_class->map_cname, 216867848Seric nbuf); 216967848Seric } 217067848Seric } 217167848Seric return TRUE; 217267848Seric } 217367848Seric 217467848Seric 217567848Seric /* 217667848Seric ** SEQ_MAP_CLOSE -- close all underlying maps 217767848Seric */ 217867848Seric 217967848Seric seq_map_close(map) 218067848Seric MAP *map; 218167848Seric { 218267848Seric int mapno; 218367848Seric 218467848Seric if (tTd(38, 20)) 218567848Seric printf("seq_map_close(%s)\n", map->map_mname); 218667848Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 218767848Seric { 218867848Seric MAP *mm = map->map_stack[mapno]; 218967848Seric 219067848Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 219167848Seric continue; 219267848Seric mm->map_class->map_close(mm); 219367848Seric } 219467848Seric } 219567848Seric 219667848Seric 219767848Seric /* 219867726Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 219967726Seric */ 220067726Seric 220167726Seric char * 220267726Seric seq_map_lookup(map, key, args, pstat) 220367726Seric MAP *map; 220467726Seric char *key; 220567726Seric char **args; 220667726Seric int *pstat; 220767726Seric { 220867726Seric int mapno; 220967726Seric int mapbit = 0x01; 221067726Seric 221167726Seric if (tTd(38, 20)) 221267726Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 221367726Seric 221467726Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 221567726Seric { 221667726Seric MAP *mm = map->map_stack[mapno]; 221767726Seric int stat = 0; 221867726Seric char *rv; 221967726Seric 222067726Seric if (mm == NULL) 222167726Seric continue; 222267726Seric if (!bitset(MF_OPEN, mm->map_mflags)) 222367726Seric { 222467726Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 222567848Seric { 222667848Seric *pstat = EX_UNAVAILABLE; 222767726Seric return NULL; 222867848Seric } 222967726Seric continue; 223067726Seric } 223167726Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 223267726Seric if (rv != NULL) 223367726Seric return rv; 223467726Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 223567726Seric return NULL; 223667726Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 223767726Seric { 223867726Seric *pstat = stat; 223967726Seric return NULL; 224067726Seric } 224167726Seric } 224267726Seric return NULL; 224367726Seric } 224467726Seric 224567726Seric 224667726Seric /* 224767726Seric ** SEQ_MAP_STORE -- sequenced map store 224867726Seric */ 224967726Seric 225067726Seric void 225167726Seric seq_map_store(map, key, val) 225267726Seric MAP *map; 225367726Seric char *key; 225467726Seric char *val; 225567726Seric { 225667726Seric int mapno; 225767726Seric 225867726Seric if (tTd(38, 12)) 225967726Seric printf("seq_map_store(%s, %s, %s)\n", 226067726Seric map->map_mname, key, val); 226167726Seric 226267726Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 226367726Seric { 226467726Seric MAP *mm = map->map_stack[mapno]; 226567726Seric 226667726Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 226767726Seric continue; 226867726Seric 226967726Seric mm->map_class->map_store(mm, key, val); 227067726Seric return; 227167726Seric } 227267726Seric syserr("seq_map_store(%s, %s, %s): no writable map", 227367726Seric map->map_mname, key, val); 227467726Seric } 227567726Seric /* 227660207Seric ** NULL stubs 227760089Seric */ 227860089Seric 227960207Seric bool 228060207Seric null_map_open(map, mode) 228160089Seric MAP *map; 228260207Seric int mode; 228360089Seric { 228460207Seric return TRUE; 228560089Seric } 228660089Seric 228760207Seric void 228860207Seric null_map_close(map) 228960207Seric MAP *map; 229060089Seric { 229160207Seric return; 229260207Seric } 229360089Seric 229460207Seric void 229560207Seric null_map_store(map, key, val) 229660207Seric MAP *map; 229760207Seric char *key; 229860207Seric char *val; 229960089Seric { 230060207Seric return; 230160089Seric } 2302