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*67848Seric static char sccsid[] = "@(#)map.c 8.32 (Berkeley) 10/24/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*67848Seric ** NISPLUS Modules 1091*67848Seric ** 1092*67848Seric ** This code donated by Sun Microsystems. 1093*67848Seric */ 1094*67848Seric 1095*67848Seric #ifdef NISPLUS 1096*67848Seric 1097*67848Seric #undef NIS /* symbol conflict in nis.h */ 1098*67848Seric #include <rpcsvc/nis.h> 1099*67848Seric #include <rpcsvc/nislib.h> 1100*67848Seric 1101*67848Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 1102*67848Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 1103*67848Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 1104*67848Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 1105*67848Seric 1106*67848Seric /* 1107*67848Seric ** NISPLUS_MAP_OPEN -- open nisplus table 1108*67848Seric */ 1109*67848Seric 1110*67848Seric bool 1111*67848Seric nisplus_map_open(map, mode) 1112*67848Seric MAP *map; 1113*67848Seric int mode; 1114*67848Seric { 1115*67848Seric register char *p; 1116*67848Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 1117*67848Seric nis_result *res = NULL; 1118*67848Seric u_int objs_len; 1119*67848Seric nis_object *obj_ptr; 1120*67848Seric int retry_cnt, max_col, i; 1121*67848Seric 1122*67848Seric if (tTd(38, 2)) 1123*67848Seric printf("nisplus_map_open(%s, %s, %d)\n", 1124*67848Seric map->map_mname, map->map_file, mode); 1125*67848Seric 1126*67848Seric if (mode != O_RDONLY) 1127*67848Seric { 1128*67848Seric errno = ENODEV; 1129*67848Seric return FALSE; 1130*67848Seric } 1131*67848Seric 1132*67848Seric if (*map->map_file == '\0') 1133*67848Seric map->map_file = "mail_aliases.org_dir"; 1134*67848Seric 1135*67848Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 1136*67848Seric { 1137*67848Seric /* set default NISPLUS Domain to $m */ 1138*67848Seric extern char *nisplus_default_domain(); 1139*67848Seric 1140*67848Seric map->map_domain = newstr(nisplus_default_domain()); 1141*67848Seric if (tTd(38, 2)) 1142*67848Seric printf("nisplus_map_open(%s): using domain %s\n", 1143*67848Seric map->map_file, map->map_domain); 1144*67848Seric } 1145*67848Seric if (!PARTIAL_NAME(map->map_file)) 1146*67848Seric map->map_domain = newstr(""); 1147*67848Seric 1148*67848Seric /* check to see if this map actually exists */ 1149*67848Seric if (PARTIAL_NAME(map->map_file)) 1150*67848Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 1151*67848Seric else 1152*67848Seric strcpy(qbuf, map->map_file); 1153*67848Seric 1154*67848Seric retry_cnt = 0; 1155*67848Seric while (res == NULL || res->status != NIS_SUCCESS) 1156*67848Seric { 1157*67848Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 1158*67848Seric switch (res->status) 1159*67848Seric { 1160*67848Seric case NIS_SUCCESS: 1161*67848Seric case NIS_TRYAGAIN: 1162*67848Seric case NIS_RPCERROR: 1163*67848Seric case NIS_NAMEUNREACHABLE: 1164*67848Seric break; 1165*67848Seric 1166*67848Seric default: /* all other nisplus errors */ 1167*67848Seric #if 0 1168*67848Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 1169*67848Seric syserr("Cannot find table %s.%s: %s", 1170*67848Seric map->map_file, map->map_domain, 1171*67848Seric nis_sperrno(res->status)); 1172*67848Seric #endif 1173*67848Seric errno = EBADR; 1174*67848Seric return FALSE; 1175*67848Seric } 1176*67848Seric sleep(2); /* try not to overwhelm hosed server */ 1177*67848Seric if (retry_cnt++ > 4) 1178*67848Seric { 1179*67848Seric errno = EBADR; 1180*67848Seric return FALSE; 1181*67848Seric } 1182*67848Seric } 1183*67848Seric 1184*67848Seric if (NIS_RES_NUMOBJ(res) != 1 || 1185*67848Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 1186*67848Seric { 1187*67848Seric if (tTd(38, 10)) 1188*67848Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 1189*67848Seric #if 0 1190*67848Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 1191*67848Seric syserr("%s.%s: %s is not a table", 1192*67848Seric map->map_file, map->map_domain, 1193*67848Seric nis_sperrno(res->status)); 1194*67848Seric #endif 1195*67848Seric errno = EBADR; 1196*67848Seric return FALSE; 1197*67848Seric } 1198*67848Seric /* default key column is column 0 */ 1199*67848Seric if (map->map_keycolnm == NULL) 1200*67848Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 1201*67848Seric 1202*67848Seric max_col = COL_MAX(res); 1203*67848Seric 1204*67848Seric /* verify the key column exist */ 1205*67848Seric for (i=0; i< max_col; i++) 1206*67848Seric { 1207*67848Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 1208*67848Seric break; 1209*67848Seric } 1210*67848Seric if (i == max_col) 1211*67848Seric { 1212*67848Seric if (tTd(38, 2)) 1213*67848Seric printf("nisplus_map_open(%s): can not find key column %s\n", 1214*67848Seric map->map_file, map->map_keycolnm); 1215*67848Seric errno = EBADR; 1216*67848Seric return FALSE; 1217*67848Seric } 1218*67848Seric 1219*67848Seric /* default value column is the last column */ 1220*67848Seric if (map->map_valcolnm == NULL) 1221*67848Seric { 1222*67848Seric map->map_valcolno = max_col - 1; 1223*67848Seric return TRUE; 1224*67848Seric } 1225*67848Seric 1226*67848Seric for (i=0; i< max_col; i++) 1227*67848Seric { 1228*67848Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 1229*67848Seric { 1230*67848Seric map->map_valcolno = i; 1231*67848Seric return TRUE; 1232*67848Seric } 1233*67848Seric } 1234*67848Seric 1235*67848Seric if (tTd(38, 2)) 1236*67848Seric printf("nisplus_map_open(%s): can not find column %s\n", 1237*67848Seric map->map_file, map->map_keycolnm); 1238*67848Seric errno = EBADR; 1239*67848Seric return FALSE; 1240*67848Seric } 1241*67848Seric 1242*67848Seric 1243*67848Seric /* 1244*67848Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 1245*67848Seric */ 1246*67848Seric 1247*67848Seric char * 1248*67848Seric nisplus_map_lookup(map, name, av, statp) 1249*67848Seric MAP *map; 1250*67848Seric char *name; 1251*67848Seric char **av; 1252*67848Seric int *statp; 1253*67848Seric { 1254*67848Seric char *vp; 1255*67848Seric auto int vsize; 1256*67848Seric int buflen; 1257*67848Seric char search_key[MAXNAME + 1]; 1258*67848Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 1259*67848Seric nis_result *result; 1260*67848Seric 1261*67848Seric if (tTd(38, 20)) 1262*67848Seric printf("nisplus_map_lookup(%s, %s)\n", 1263*67848Seric map->map_mname, name); 1264*67848Seric 1265*67848Seric if (!bitset(MF_OPEN, map->map_mflags)) 1266*67848Seric { 1267*67848Seric if (nisplus_map_open(map, O_RDONLY)) 1268*67848Seric map->map_mflags |= MF_OPEN; 1269*67848Seric else 1270*67848Seric { 1271*67848Seric *statp = EX_UNAVAILABLE; 1272*67848Seric return NULL; 1273*67848Seric } 1274*67848Seric } 1275*67848Seric 1276*67848Seric buflen = strlen(name); 1277*67848Seric if (buflen > sizeof search_key - 1) 1278*67848Seric buflen = sizeof search_key - 1; 1279*67848Seric bcopy(name, search_key, buflen + 1); 1280*67848Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 1281*67848Seric makelower(search_key); 1282*67848Seric 1283*67848Seric /* construct the query */ 1284*67848Seric if (PARTIAL_NAME(map->map_file)) 1285*67848Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 1286*67848Seric search_key, map->map_file, map->map_domain); 1287*67848Seric else 1288*67848Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 1289*67848Seric search_key, map->map_file); 1290*67848Seric 1291*67848Seric if (tTd(38, 20)) 1292*67848Seric printf("qbuf=%s\n", qbuf); 1293*67848Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 1294*67848Seric if (result->status == NIS_SUCCESS) 1295*67848Seric { 1296*67848Seric int count; 1297*67848Seric char *str; 1298*67848Seric 1299*67848Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 1300*67848Seric { 1301*67848Seric if (LogLevel > 10) 1302*67848Seric syslog(LOG_WARNING, 1303*67848Seric "%s:Lookup error, expected 1 entry, got (%d)", 1304*67848Seric map->map_file, count); 1305*67848Seric 1306*67848Seric /* ignore second entry */ 1307*67848Seric if (tTd(38, 20)) 1308*67848Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 1309*67848Seric name, count); 1310*67848Seric } 1311*67848Seric 1312*67848Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 1313*67848Seric /* set the length of the result */ 1314*67848Seric if (vp == NULL) 1315*67848Seric vp = ""; 1316*67848Seric vsize = strlen(vp); 1317*67848Seric if (tTd(38, 20)) 1318*67848Seric printf("nisplus_map_lookup(%s), found %s\n", 1319*67848Seric name, vp); 1320*67848Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 1321*67848Seric str = map_rewrite(map, name, strlen(name), NULL); 1322*67848Seric else 1323*67848Seric str = map_rewrite(map, vp, vsize, av); 1324*67848Seric nis_freeresult(result); 1325*67848Seric #ifdef MAP_EXIT_STAT 1326*67848Seric *statp = EX_OK; 1327*67848Seric #endif 1328*67848Seric return str; 1329*67848Seric } 1330*67848Seric else 1331*67848Seric { 1332*67848Seric #ifdef MAP_EXIT_STAT 1333*67848Seric if (result->status == NIS_NOTFOUND) 1334*67848Seric *statp = EX_NOTFOUND; 1335*67848Seric else if (result->status == NIS_TRYAGAIN) 1336*67848Seric *statp = EX_TEMPFAIL; 1337*67848Seric else 1338*67848Seric { 1339*67848Seric *statp = EX_UNAVAILABLE; 1340*67848Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 1341*67848Seric } 1342*67848Seric #else 1343*67848Seric if ((result->status != NIS_NOTFOUND) && 1344*67848Seric (result->status != NIS_TRYAGAIN)) 1345*67848Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 1346*67848Seric #endif 1347*67848Seric } 1348*67848Seric if (tTd(38, 20)) 1349*67848Seric printf("nisplus_map_lookup(%s), failed\n", name); 1350*67848Seric nis_freeresult(result); 1351*67848Seric return NULL; 1352*67848Seric } 1353*67848Seric 1354*67848Seric 1355*67848Seric char * 1356*67848Seric nisplus_default_domain() 1357*67848Seric { 1358*67848Seric static char default_domain[MAXNAME] = ""; 1359*67848Seric nis_result *res = NULL; 1360*67848Seric char *p; 1361*67848Seric 1362*67848Seric if (default_domain[0] != '\0') 1363*67848Seric return(default_domain); 1364*67848Seric 1365*67848Seric if (VendorCode == VENDOR_SUN && ConfigLevel < 2) 1366*67848Seric { 1367*67848Seric /* for old config, user nis+ local directory */ 1368*67848Seric /* have to be backward compatible with bugs too :-( */ 1369*67848Seric p = nis_local_directory(); 1370*67848Seric strcpy(default_domain, p); 1371*67848Seric return default_domain; 1372*67848Seric } 1373*67848Seric 1374*67848Seric if ((p = macvalue('m', CurEnv)) == NULL) 1375*67848Seric { 1376*67848Seric p = nis_local_directory(); 1377*67848Seric strcpy(default_domain, p); 1378*67848Seric return default_domain; 1379*67848Seric } 1380*67848Seric 1381*67848Seric strcpy(default_domain, p); 1382*67848Seric if (PARTIAL_NAME(default_domain)) 1383*67848Seric strcat(default_domain, "."); 1384*67848Seric 1385*67848Seric res = nis_lookup(default_domain, FOLLOW_LINKS); 1386*67848Seric if (res->status == NIS_NOTFOUND) 1387*67848Seric { 1388*67848Seric p = nis_local_directory(); 1389*67848Seric strcpy(default_domain, p); 1390*67848Seric } 1391*67848Seric return(default_domain); 1392*67848Seric } 1393*67848Seric 1394*67848Seric #endif /* NISPLUS */ 1395*67848Seric /* 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) 1431*67848Seric { 1432*67848Seric *statp = EX_DATAERR; 143367832Seric return NULL; 1434*67848Seric } 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 1454*67848Seric 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 147767842Seric if (map->map_sepchar == '\0' && bitset(MF_ALIAS, map->map_mflags)) 147867842Seric map->map_sepchar = ','; 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)) 1500*67848Seric 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 1506*67848Seric 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 /* 1519*67848Seric ** TEXT (unindexed text file) Modules 1520*67848Seric ** 1521*67848Seric ** This code donated by Sun Microsystems. 1522*67848Seric */ 1523*67848Seric 1524*67848Seric 1525*67848Seric /* 1526*67848Seric ** TEXT_MAP_OPEN -- open text table 1527*67848Seric */ 1528*67848Seric 1529*67848Seric bool 1530*67848Seric text_map_open(map, mode) 1531*67848Seric MAP *map; 1532*67848Seric int mode; 1533*67848Seric { 1534*67848Seric struct stat sbuf; 1535*67848Seric 1536*67848Seric if (tTd(38, 2)) 1537*67848Seric printf("text_map_open(%s, %s, %d)\n", 1538*67848Seric map->map_mname, map->map_file, mode); 1539*67848Seric 1540*67848Seric if (mode != O_RDONLY) 1541*67848Seric { 1542*67848Seric errno = ENODEV; 1543*67848Seric return FALSE; 1544*67848Seric } 1545*67848Seric 1546*67848Seric if (*map->map_file == '\0') 1547*67848Seric { 1548*67848Seric if (tTd(38, 2)) 1549*67848Seric printf("text_map_open: file name required\n"); 1550*67848Seric return FALSE; 1551*67848Seric } 1552*67848Seric 1553*67848Seric if (map->map_file[0] != '/') 1554*67848Seric { 1555*67848Seric if (tTd(38, 2)) 1556*67848Seric printf("text_map_open(%s): file name must be fully qualified\n", 1557*67848Seric map->map_file); 1558*67848Seric return FALSE; 1559*67848Seric } 1560*67848Seric /* check to see if this map actually accessable */ 1561*67848Seric if (access(map->map_file, R_OK) <0) 1562*67848Seric return FALSE; 1563*67848Seric 1564*67848Seric /* check to see if this map actually exist */ 1565*67848Seric if (stat(map->map_file, &sbuf) <0) 1566*67848Seric { 1567*67848Seric if (tTd(38, 2)) 1568*67848Seric printf("text_map_open(%s): can not stat %s\n", 1569*67848Seric map->map_file, map->map_file); 1570*67848Seric return FALSE; 1571*67848Seric } 1572*67848Seric 1573*67848Seric if (!S_ISREG(sbuf.st_mode)) 1574*67848Seric { 1575*67848Seric if (tTd(38, 2)) 1576*67848Seric printf("text_map_open(%s): %s is not a file\n", 1577*67848Seric map->map_file, map->map_file); 1578*67848Seric return FALSE; 1579*67848Seric } 1580*67848Seric 1581*67848Seric if (map->map_keycolnm == NULL) 1582*67848Seric map->map_keycolno = 0; 1583*67848Seric else 1584*67848Seric { 1585*67848Seric if (!isdigit(*map->map_keycolnm)) 1586*67848Seric { 1587*67848Seric if (tTd(38, 2)) 1588*67848Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 1589*67848Seric map->map_file, map->map_keycolnm); 1590*67848Seric return FALSE; 1591*67848Seric } 1592*67848Seric map->map_keycolno = atoi(map->map_keycolnm); 1593*67848Seric } 1594*67848Seric 1595*67848Seric if (map->map_valcolnm == NULL) 1596*67848Seric map->map_valcolno = 0; 1597*67848Seric else 1598*67848Seric { 1599*67848Seric if (!isdigit(*map->map_valcolnm)) 1600*67848Seric { 1601*67848Seric if (tTd(38, 2)) 1602*67848Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 1603*67848Seric map->map_file, map->map_valcolnm); 1604*67848Seric return FALSE; 1605*67848Seric } 1606*67848Seric map->map_valcolno = atoi(map->map_valcolnm); 1607*67848Seric } 1608*67848Seric 1609*67848Seric if (map->map_coldelim == '\0') 1610*67848Seric map->map_coldelim = ':'; 1611*67848Seric 1612*67848Seric if (tTd(38, 2)) 1613*67848Seric { 1614*67848Seric printf("text_map_open(%s): delimiter = %c\n", 1615*67848Seric map->map_file, map->map_coldelim); 1616*67848Seric } 1617*67848Seric 1618*67848Seric return TRUE; 1619*67848Seric } 1620*67848Seric 1621*67848Seric 1622*67848Seric /* 1623*67848Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 1624*67848Seric */ 1625*67848Seric 1626*67848Seric char * 1627*67848Seric text_map_lookup(map, name, av, statp) 1628*67848Seric MAP *map; 1629*67848Seric char *name; 1630*67848Seric char **av; 1631*67848Seric int *statp; 1632*67848Seric { 1633*67848Seric char *vp; 1634*67848Seric auto int vsize; 1635*67848Seric int buflen; 1636*67848Seric char search_key[MAXNAME + 1]; 1637*67848Seric char linebuf[MAXLINE]; 1638*67848Seric FILE *f; 1639*67848Seric char buf[MAXNAME+1]; 1640*67848Seric char delim; 1641*67848Seric int key_idx; 1642*67848Seric bool found_it; 1643*67848Seric extern char *get_column(); 1644*67848Seric 1645*67848Seric 1646*67848Seric found_it = FALSE; 1647*67848Seric if (tTd(38, 20)) 1648*67848Seric printf("text_map_lookup(%s)\n", name); 1649*67848Seric 1650*67848Seric buflen = strlen(name); 1651*67848Seric if (buflen > sizeof search_key - 1) 1652*67848Seric buflen = sizeof search_key - 1; 1653*67848Seric bcopy(name, search_key, buflen + 1); 1654*67848Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 1655*67848Seric makelower(search_key); 1656*67848Seric 1657*67848Seric f = fopen(map->map_file, "r"); 1658*67848Seric if (f == NULL) 1659*67848Seric { 1660*67848Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 1661*67848Seric *statp = EX_UNAVAILABLE; 1662*67848Seric return NULL; 1663*67848Seric } 1664*67848Seric key_idx = map->map_keycolno; 1665*67848Seric delim = map->map_coldelim; 1666*67848Seric while (fgets(linebuf, MAXLINE, f)) 1667*67848Seric { 1668*67848Seric char *lf; 1669*67848Seric if (linebuf[0] == '#') 1670*67848Seric continue; /* skip comment line */ 1671*67848Seric if (lf = strchr(linebuf, '\n')) 1672*67848Seric *lf = '\0'; 1673*67848Seric if (!strcasecmp(search_key, 1674*67848Seric get_column(linebuf, key_idx, delim, buf))) 1675*67848Seric { 1676*67848Seric found_it = TRUE; 1677*67848Seric break; 1678*67848Seric } 1679*67848Seric } 1680*67848Seric fclose(f); 1681*67848Seric if (!found_it) 1682*67848Seric { 1683*67848Seric #ifdef MAP_EXIT_STAT 1684*67848Seric *statp = EX_NOTFOUND; 1685*67848Seric #endif 1686*67848Seric return(NULL); 1687*67848Seric } 1688*67848Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 1689*67848Seric vsize = strlen(vp); 1690*67848Seric #ifdef MAP_EXIT_STAT 1691*67848Seric *statp = EX_OK; 1692*67848Seric #endif 1693*67848Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 1694*67848Seric return map_rewrite(map, name, strlen(name), NULL); 1695*67848Seric else 1696*67848Seric return map_rewrite(map, vp, vsize, av); 1697*67848Seric } 1698*67848Seric /* 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: 2010*67848Seric 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. 2048*67848Seric ** 2049*67848Seric ** This is slightly unusual in that there are two interfaces. 2050*67848Seric ** The "sequence" interface lets you stack maps arbitrarily. 2051*67848Seric ** The "switch" interface builds a sequence map by looking 2052*67848Seric ** at a system-dependent configuration file such as 2053*67848Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 2054*67848Seric ** 2055*67848Seric ** We don't need an explicit open, since all maps are 2056*67848Seric ** 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 /* 2115*67848Seric ** SWITCH_MAP_OPEN -- open a switched map 2116*67848Seric ** 2117*67848Seric ** This looks at the system-dependent configuration and builds 2118*67848Seric ** a sequence map that does the same thing. 2119*67848Seric ** 2120*67848Seric ** Every system must define a switch_map_find routine in conf.c 2121*67848Seric ** that will return the list of service types associated with a 2122*67848Seric ** given service class. 2123*67848Seric */ 2124*67848Seric 2125*67848Seric bool 2126*67848Seric switch_map_open(map, mode) 2127*67848Seric MAP *map; 2128*67848Seric int mode; 2129*67848Seric { 2130*67848Seric int mapno; 2131*67848Seric int nmaps; 2132*67848Seric char *maptype[MAXMAPSTACK]; 2133*67848Seric 2134*67848Seric if (tTd(38, 2)) 2135*67848Seric printf("switch_map_open(%s, %s, %d)\n", 2136*67848Seric map->map_mname, map->map_file, mode); 2137*67848Seric 2138*67848Seric nmaps = switch_map_find(map->map_file, maptype); 2139*67848Seric if (tTd(38, 19)) 2140*67848Seric { 2141*67848Seric printf("\tswitch_map_find => %d\n", nmaps); 2142*67848Seric for (mapno = 0; mapno < nmaps; mapno++) 2143*67848Seric printf("\t\t%s\n", maptype[mapno]); 2144*67848Seric } 2145*67848Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 2146*67848Seric return FALSE; 2147*67848Seric 2148*67848Seric for (mapno = 0; mapno < nmaps; mapno++) 2149*67848Seric { 2150*67848Seric register STAB *s; 2151*67848Seric char nbuf[MAXNAME + 1]; 2152*67848Seric 2153*67848Seric if (maptype[mapno] == NULL) 2154*67848Seric continue; 2155*67848Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 2156*67848Seric s = stab(nbuf, ST_MAP, ST_FIND); 2157*67848Seric if (s == NULL) 2158*67848Seric { 2159*67848Seric syserr("Switch map %s: unknown member map %s", 2160*67848Seric map->map_mname, nbuf); 2161*67848Seric } 2162*67848Seric else 2163*67848Seric { 2164*67848Seric map->map_stack[mapno] = &s->s_map; 2165*67848Seric if (tTd(38, 4)) 2166*67848Seric printf("\tmap_stack[%d] = %s:%s\n", 2167*67848Seric mapno, s->s_map.map_class->map_cname, 2168*67848Seric nbuf); 2169*67848Seric } 2170*67848Seric } 2171*67848Seric return TRUE; 2172*67848Seric } 2173*67848Seric 2174*67848Seric 2175*67848Seric /* 2176*67848Seric ** SEQ_MAP_CLOSE -- close all underlying maps 2177*67848Seric */ 2178*67848Seric 2179*67848Seric seq_map_close(map) 2180*67848Seric MAP *map; 2181*67848Seric { 2182*67848Seric int mapno; 2183*67848Seric 2184*67848Seric if (tTd(38, 20)) 2185*67848Seric printf("seq_map_close(%s)\n", map->map_mname); 2186*67848Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 2187*67848Seric { 2188*67848Seric MAP *mm = map->map_stack[mapno]; 2189*67848Seric 2190*67848Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 2191*67848Seric continue; 2192*67848Seric mm->map_class->map_close(mm); 2193*67848Seric } 2194*67848Seric } 2195*67848Seric 2196*67848Seric 2197*67848Seric /* 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])) 2225*67848Seric { 2226*67848Seric *pstat = EX_UNAVAILABLE; 222767726Seric return NULL; 2228*67848Seric } 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