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*68395Seric static char sccsid[] = "@(#)map.c 8.43 (Berkeley) 02/21/95"; 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; 12168350Seric 12268350Seric case 'k': 12368350Seric while (isascii(*++p) && isspace(*p)) 12468350Seric continue; 12568350Seric map->map_keycolnm = p; 12668350Seric break; 12768350Seric 12868350Seric case 'v': 12968350Seric while (isascii(*++p) && isspace(*p)) 13068350Seric continue; 13168350Seric map->map_valcolnm = p; 13268350Seric break; 13368350Seric 13468350Seric case 'z': 13568350Seric if (*++p != '\\') 13668350Seric map->map_coldelim = *p; 13768350Seric else 13868350Seric { 13968350Seric switch (*++p) 14068350Seric { 14168350Seric case 'n': 14268350Seric map->map_coldelim = '\n'; 14368350Seric break; 14468350Seric 14568350Seric case 't': 14668350Seric map->map_coldelim = '\t'; 14768350Seric break; 14868350Seric 14968350Seric default: 15068350Seric map->map_coldelim = '\\'; 15168350Seric } 15268350Seric } 15368350Seric 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); 16268350Seric if (map->map_keycolnm != NULL) 16368350Seric map->map_keycolnm = newstr(map->map_keycolnm); 16468350Seric if (map->map_valcolnm != NULL) 16568350Seric 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 18268350Seric if (map->map_file == NULL && 18368350Seric !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 18457208Seric { 18560089Seric syserr("No file name for %s map %s", 18660089Seric map->map_class->map_cname, map->map_mname); 18756822Seric return FALSE; 18857208Seric } 18960089Seric return TRUE; 19060089Seric } 19160089Seric /* 19260089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 19360089Seric ** 19460089Seric ** It also adds the map_app string. It can be used as a utility 19560089Seric ** in the map_lookup method. 19660089Seric ** 19760089Seric ** Parameters: 19860089Seric ** map -- the map that causes this. 19960089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 20060089Seric ** slen -- the length of s. 20160089Seric ** av -- arguments to interpolate into buf. 20260089Seric ** 20360089Seric ** Returns: 20467895Seric ** Pointer to rewritten result. This is static data that 20567895Seric ** should be copied if it is to be saved! 20660089Seric ** 20760089Seric ** Side Effects: 20860089Seric ** none. 20960089Seric */ 21060089Seric 21160089Seric char * 21260089Seric map_rewrite(map, s, slen, av) 21360089Seric register MAP *map; 21460089Seric register char *s; 21560089Seric int slen; 21660089Seric char **av; 21760089Seric { 21860089Seric register char *bp; 21960089Seric register char c; 22060089Seric char **avp; 22160089Seric register char *ap; 22260089Seric int i; 22360089Seric int len; 22467895Seric static int buflen = -1; 22567895Seric static char *buf = NULL; 22660089Seric 22760537Seric if (tTd(39, 1)) 22860089Seric { 22960256Seric printf("map_rewrite(%.*s), av =", slen, s); 23060256Seric if (av == NULL) 23160256Seric printf(" (nullv)"); 23260256Seric else 23360256Seric { 23460256Seric for (avp = av; *avp != NULL; avp++) 23560256Seric printf("\n\t%s", *avp); 23660256Seric } 23760256Seric printf("\n"); 23860089Seric } 23960089Seric 24060089Seric /* count expected size of output (can safely overestimate) */ 24160089Seric i = len = slen; 24260089Seric if (av != NULL) 24360089Seric { 24460089Seric bp = s; 24560089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 24660089Seric { 24760089Seric if (c != '%') 24860089Seric continue; 24960089Seric if (--i < 0) 25060089Seric break; 25160089Seric c = *bp++; 25260089Seric if (!(isascii(c) && isdigit(c))) 25360089Seric continue; 25463937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 25560089Seric continue; 25660089Seric if (*avp == NULL) 25760089Seric continue; 25860089Seric len += strlen(*avp); 25960089Seric } 26060089Seric } 26160089Seric if (map->map_app != NULL) 26260089Seric len += strlen(map->map_app); 26367895Seric if (buflen < ++len) 26460089Seric { 26560089Seric /* need to malloc additional space */ 26667895Seric buflen = len; 26767895Seric if (buf != NULL) 26867895Seric free(buf); 26967895Seric buf = xalloc(buflen); 27060089Seric } 27160089Seric 27267895Seric bp = buf; 27360089Seric if (av == NULL) 27460089Seric { 27560089Seric bcopy(s, bp, slen); 27660089Seric bp += slen; 27760089Seric } 27860089Seric else 27960089Seric { 28060089Seric while (--slen >= 0 && (c = *s++) != '\0') 28160089Seric { 28260089Seric if (c != '%') 28360089Seric { 28460089Seric pushc: 28560089Seric *bp++ = c; 28660089Seric continue; 28760089Seric } 28860089Seric if (--slen < 0 || (c = *s++) == '\0') 28960089Seric c = '%'; 29060089Seric if (c == '%') 29160089Seric goto pushc; 29260089Seric if (!(isascii(c) && isdigit(c))) 29360089Seric { 29460089Seric *bp++ = '%'; 29560089Seric goto pushc; 29660089Seric } 29763937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 29860089Seric continue; 29960089Seric if (*avp == NULL) 30060089Seric continue; 30160089Seric 30260089Seric /* transliterate argument into output string */ 30360089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 30460089Seric *bp++ = c; 30560089Seric } 30660089Seric } 30760089Seric if (map->map_app != NULL) 30860089Seric strcpy(bp, map->map_app); 30960089Seric else 31060089Seric *bp = '\0'; 31160537Seric if (tTd(39, 1)) 31267895Seric printf("map_rewrite => %s\n", buf); 31367895Seric return buf; 31460089Seric } 31560089Seric /* 31660537Seric ** INITMAPS -- initialize for aliasing 31760537Seric ** 31860537Seric ** Parameters: 31960537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 32060537Seric ** e -- current envelope. 32160537Seric ** 32260537Seric ** Returns: 32360537Seric ** none. 32460537Seric ** 32560537Seric ** Side Effects: 32660537Seric ** initializes aliases: 32760537Seric ** if NDBM: opens the database. 32860537Seric ** if ~NDBM: reads the aliases into the symbol table. 32960537Seric */ 33060537Seric 33160537Seric initmaps(rebuild, e) 33260537Seric bool rebuild; 33360537Seric register ENVELOPE *e; 33460537Seric { 33560537Seric extern void map_init(); 33660537Seric 33764671Seric #ifdef XDEBUG 33864671Seric checkfd012("entering initmaps"); 33964671Seric #endif 34060537Seric CurEnv = e; 34165085Seric if (rebuild) 34265085Seric { 34365085Seric stabapply(map_init, 1); 34465085Seric stabapply(map_init, 2); 34565085Seric } 34665085Seric else 34765085Seric { 34865085Seric stabapply(map_init, 0); 34965085Seric } 35064671Seric #ifdef XDEBUG 35164671Seric checkfd012("exiting initmaps"); 35264671Seric #endif 35360537Seric } 35460537Seric 35560537Seric void 35660537Seric map_init(s, rebuild) 35760537Seric register STAB *s; 35860537Seric int rebuild; 35960537Seric { 36060537Seric register MAP *map; 36160537Seric 36260537Seric /* has to be a map */ 36360537Seric if (s->s_type != ST_MAP) 36460537Seric return; 36560537Seric 36660537Seric map = &s->s_map; 36760537Seric if (!bitset(MF_VALID, map->map_mflags)) 36860537Seric return; 36960537Seric 37060537Seric if (tTd(38, 2)) 37168350Seric printf("map_init(%s:%s, %s, %d)\n", 37264690Seric map->map_class->map_cname == NULL ? "NULL" : 37364690Seric map->map_class->map_cname, 37468350Seric map->map_mname == NULL ? "NULL" : map->map_mname, 37565085Seric map->map_file == NULL ? "NULL" : map->map_file, 37665085Seric rebuild); 37760537Seric 37865085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && 37965085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) 38065085Seric { 38165085Seric if (tTd(38, 3)) 38265085Seric printf("\twrong pass\n"); 38365085Seric return; 38465085Seric } 38565085Seric 38660537Seric /* if already open, close it (for nested open) */ 38760537Seric if (bitset(MF_OPEN, map->map_mflags)) 38860537Seric { 38960537Seric map->map_class->map_close(map); 39060537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 39160537Seric } 39260537Seric 39365085Seric if (rebuild == 2) 39460537Seric { 39565085Seric rebuildaliases(map, FALSE); 39660537Seric } 39760537Seric else 39860537Seric { 39960537Seric if (map->map_class->map_open(map, O_RDONLY)) 40060537Seric { 40160537Seric if (tTd(38, 4)) 40268350Seric printf("\t%s:%s %s: valid\n", 40364690Seric map->map_class->map_cname == NULL ? "NULL" : 40464690Seric map->map_class->map_cname, 40568350Seric map->map_mname == NULL ? "NULL" : 40668350Seric map->map_mname, 40764690Seric map->map_file == NULL ? "NULL" : 40864690Seric map->map_file); 40960537Seric map->map_mflags |= MF_OPEN; 41060537Seric } 41168350Seric else 41268350Seric { 41368350Seric if (tTd(38, 4)) 41468350Seric printf("\t%s:%s %s: invalid: %s\n", 41568350Seric map->map_class->map_cname == NULL ? "NULL" : 41668350Seric map->map_class->map_cname, 41768350Seric map->map_mname == NULL ? "NULL" : 41868350Seric map->map_mname, 41968350Seric map->map_file == NULL ? "NULL" : 42068350Seric map->map_file, 42168350Seric errstring(errno)); 42268350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 42368350Seric { 42468350Seric extern MAPCLASS BogusMapClass; 42568350Seric 42668350Seric map->map_class = &BogusMapClass; 42768350Seric map->map_mflags |= MF_OPEN; 42868350Seric } 42968350Seric } 43060537Seric } 43160537Seric } 43260537Seric /* 43360089Seric ** NDBM modules 43460089Seric */ 43560089Seric 43660089Seric #ifdef NDBM 43760089Seric 43860089Seric /* 43960089Seric ** DBM_MAP_OPEN -- DBM-style map open 44060089Seric */ 44160089Seric 44260089Seric bool 44360089Seric ndbm_map_open(map, mode) 44460089Seric MAP *map; 44560089Seric int mode; 44660089Seric { 44764284Seric register DBM *dbm; 44864284Seric struct stat st; 44960089Seric 45060537Seric if (tTd(38, 2)) 45168350Seric printf("ndbm_map_open(%s, %s, %d)\n", 45268350Seric map->map_mname, map->map_file, mode); 45360089Seric 45460207Seric if (mode == O_RDWR) 45560207Seric mode |= O_CREAT|O_TRUNC; 45660207Seric 45760089Seric /* open the database */ 45860089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 45956822Seric if (dbm == NULL) 46056822Seric { 46164718Seric if (aliaswait(map, ".pag", FALSE)) 46264718Seric return TRUE; 46360207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 46456836Seric syserr("Cannot open DBM database %s", map->map_file); 46556822Seric return FALSE; 46656822Seric } 46760089Seric map->map_db1 = (void *) dbm; 46864964Seric if (mode == O_RDONLY) 46964964Seric { 47064964Seric if (bitset(MF_ALIAS, map->map_mflags) && 47164964Seric !aliaswait(map, ".pag", TRUE)) 47264718Seric return FALSE; 47364964Seric } 47464964Seric else 47564964Seric { 47664964Seric int fd; 47764964Seric 47864964Seric /* exclusive lock for duration of rebuild */ 47964964Seric fd = dbm_dirfno((DBM *) map->map_db1); 48064964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 48164964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 48264964Seric map->map_mflags |= MF_LOCKED; 48364964Seric } 48464718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 48564284Seric map->map_mtime = st.st_mtime; 48656822Seric return TRUE; 48756822Seric } 48860089Seric 48960089Seric 49060089Seric /* 49156822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 49256822Seric */ 49356822Seric 49456822Seric char * 49560089Seric ndbm_map_lookup(map, name, av, statp) 49656822Seric MAP *map; 49760089Seric char *name; 49856822Seric char **av; 49959084Seric int *statp; 50056822Seric { 50156822Seric datum key, val; 50264373Seric int fd; 50360089Seric char keybuf[MAXNAME + 1]; 50456822Seric 50560537Seric if (tTd(38, 20)) 50668350Seric printf("ndbm_map_lookup(%s, %s)\n", 50768350Seric map->map_mname, name); 50860089Seric 50960089Seric key.dptr = name; 51060089Seric key.dsize = strlen(name); 51160207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 51257014Seric { 51360089Seric if (key.dsize > sizeof keybuf - 1) 51460089Seric key.dsize = sizeof keybuf - 1; 51560089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 51660089Seric makelower(keybuf); 51760089Seric key.dptr = keybuf; 51857014Seric } 51964373Seric fd = dbm_dirfno((DBM *) map->map_db1); 52064388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 52164373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 52263753Seric val.dptr = NULL; 52363753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 52463753Seric { 52563753Seric val = dbm_fetch((DBM *) map->map_db1, key); 52663753Seric if (val.dptr != NULL) 52763753Seric map->map_mflags &= ~MF_TRY1NULL; 52863753Seric } 52963753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 53063753Seric { 53156822Seric key.dsize++; 53263753Seric val = dbm_fetch((DBM *) map->map_db1, key); 53363753Seric if (val.dptr != NULL) 53463753Seric map->map_mflags &= ~MF_TRY0NULL; 53563753Seric } 53664388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 53764373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 53856822Seric if (val.dptr == NULL) 53956822Seric return NULL; 54060207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 54163753Seric return map_rewrite(map, name, strlen(name), NULL); 54263753Seric else 54363753Seric return map_rewrite(map, val.dptr, val.dsize, av); 54456822Seric } 54556822Seric 54656822Seric 54756822Seric /* 54860089Seric ** DBM_MAP_STORE -- store a datum in the database 54956822Seric */ 55056822Seric 55160089Seric void 55260089Seric ndbm_map_store(map, lhs, rhs) 55360089Seric register MAP *map; 55460089Seric char *lhs; 55560089Seric char *rhs; 55660089Seric { 55760089Seric datum key; 55860089Seric datum data; 55960089Seric int stat; 56060089Seric 56160537Seric if (tTd(38, 12)) 56268350Seric printf("ndbm_map_store(%s, %s, %s)\n", 56368350Seric map->map_mname, lhs, rhs); 56460089Seric 56560089Seric key.dsize = strlen(lhs); 56660089Seric key.dptr = lhs; 56760089Seric 56860089Seric data.dsize = strlen(rhs); 56960089Seric data.dptr = rhs; 57060089Seric 57160207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 57260089Seric { 57360089Seric key.dsize++; 57460089Seric data.dsize++; 57560089Seric } 57660089Seric 57760089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 57860089Seric if (stat > 0) 57960089Seric { 58060089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 58160089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 58260089Seric } 58360089Seric if (stat != 0) 58460089Seric syserr("readaliases: dbm put (%s)", lhs); 58560089Seric } 58660089Seric 58760089Seric 58860089Seric /* 58960207Seric ** NDBM_MAP_CLOSE -- close the database 59060089Seric */ 59160089Seric 59260089Seric void 59360089Seric ndbm_map_close(map) 59460089Seric register MAP *map; 59560089Seric { 59666773Seric if (tTd(38, 9)) 59768350Seric printf("ndbm_map_close(%s, %s, %x)\n", 59868350Seric map->map_mname, map->map_file, map->map_mflags); 59966773Seric 60060207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 60160089Seric { 60264250Seric #ifdef NIS 60364075Seric bool inclnull; 60460089Seric char buf[200]; 60560089Seric 60664075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 60764075Seric map->map_mflags &= ~MF_INCLNULL; 60864075Seric 60960089Seric (void) sprintf(buf, "%010ld", curtime()); 61060089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 61160089Seric 61264941Seric (void) gethostname(buf, sizeof buf); 61360089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 61464075Seric 61564075Seric if (inclnull) 61664075Seric map->map_mflags |= MF_INCLNULL; 61760089Seric #endif 61860089Seric 61960089Seric /* write out the distinguished alias */ 62060089Seric ndbm_map_store(map, "@", "@"); 62160089Seric } 62260089Seric dbm_close((DBM *) map->map_db1); 62360089Seric } 62460089Seric 62560089Seric #endif 62660089Seric /* 62760582Seric ** NEWDB (Hash and BTree) Modules 62860089Seric */ 62960089Seric 63060089Seric #ifdef NEWDB 63160089Seric 63260089Seric /* 63360582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 63460582Seric ** 63560582Seric ** These do rather bizarre locking. If you can lock on open, 63660582Seric ** do that to avoid the condition of opening a database that 63760582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 63860582Seric ** there will be a race condition. If opening for read-only, 63960582Seric ** we immediately release the lock to avoid freezing things up. 64060582Seric ** We really ought to hold the lock, but guarantee that we won't 64160582Seric ** be pokey about it. That's hard to do. 64260089Seric */ 64360089Seric 64456822Seric bool 64560089Seric bt_map_open(map, mode) 64656822Seric MAP *map; 64760089Seric int mode; 64856822Seric { 64956822Seric DB *db; 65060228Seric int i; 65160582Seric int omode; 65264373Seric int fd; 65364284Seric struct stat st; 65460089Seric char buf[MAXNAME]; 65556822Seric 65660537Seric if (tTd(38, 2)) 65768350Seric printf("bt_map_open(%s, %s, %d)\n", 65868350Seric map->map_mname, map->map_file, mode); 65960089Seric 66060582Seric omode = mode; 66160582Seric if (omode == O_RDWR) 66260582Seric { 66360582Seric omode |= O_CREAT|O_TRUNC; 66465830Seric #if defined(O_EXLOCK) && HASFLOCK 66560582Seric omode |= O_EXLOCK; 66666843Seric # if !OLD_NEWDB 66760582Seric } 66860582Seric else 66960582Seric { 67060582Seric omode |= O_SHLOCK; 67160582Seric # endif 67260582Seric #endif 67360582Seric } 67460207Seric 67560228Seric (void) strcpy(buf, map->map_file); 67660228Seric i = strlen(buf); 67760228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 67860228Seric (void) strcat(buf, ".db"); 67960582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 68056822Seric if (db == NULL) 68156822Seric { 68264718Seric #ifdef MAYBENEXTRELEASE 68364718Seric if (aliaswait(map, ".db", FALSE)) 68464718Seric return TRUE; 68564718Seric #endif 68660207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 68756836Seric syserr("Cannot open BTREE database %s", map->map_file); 68856822Seric return FALSE; 68956822Seric } 69068350Seric #if !OLD_NEWDB 69164373Seric fd = db->fd(db); 69268350Seric # if HASFLOCK 69368350Seric # if !defined(O_EXLOCK) 69464373Seric if (mode == O_RDWR && fd >= 0) 69564388Seric { 69664388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 69764388Seric map->map_mflags |= MF_LOCKED; 69864388Seric } 69968350Seric # else 70064373Seric if (mode == O_RDONLY && fd >= 0) 70164373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 70264388Seric else 70364388Seric map->map_mflags |= MF_LOCKED; 70468350Seric # endif 70560582Seric # endif 70660582Seric #endif 70760585Seric 70860585Seric /* try to make sure that at least the database header is on disk */ 70960585Seric if (mode == O_RDWR) 71066843Seric #if OLD_NEWDB 71164373Seric (void) db->sync(db); 71264373Seric #else 71360585Seric (void) db->sync(db, 0); 71460585Seric 71564373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 71664284Seric map->map_mtime = st.st_mtime; 71764284Seric #endif 71864284Seric 71960089Seric map->map_db2 = (void *) db; 72060207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 72164718Seric if (!aliaswait(map, ".db", TRUE)) 72264718Seric return FALSE; 72356822Seric return TRUE; 72456822Seric } 72556822Seric 72656822Seric 72756822Seric /* 72856822Seric ** HASH_MAP_INIT -- HASH-style map initialization 72956822Seric */ 73056822Seric 73156822Seric bool 73260089Seric hash_map_open(map, mode) 73356822Seric MAP *map; 73460089Seric int mode; 73556822Seric { 73656822Seric DB *db; 73760228Seric int i; 73860582Seric int omode; 73964373Seric int fd; 74064284Seric struct stat st; 74160089Seric char buf[MAXNAME]; 74256822Seric 74360537Seric if (tTd(38, 2)) 74468350Seric printf("hash_map_open(%s, %s, %d)\n", 74568350Seric map->map_mname, map->map_file, mode); 74660089Seric 74760582Seric omode = mode; 74860582Seric if (omode == O_RDWR) 74960582Seric { 75060582Seric omode |= O_CREAT|O_TRUNC; 75165830Seric #if defined(O_EXLOCK) && HASFLOCK 75260582Seric omode |= O_EXLOCK; 75366843Seric # if !OLD_NEWDB 75460582Seric } 75560582Seric else 75660582Seric { 75760582Seric omode |= O_SHLOCK; 75860582Seric # endif 75960582Seric #endif 76060582Seric } 76160207Seric 76260228Seric (void) strcpy(buf, map->map_file); 76360228Seric i = strlen(buf); 76460228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 76560228Seric (void) strcat(buf, ".db"); 76660582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 76756822Seric if (db == NULL) 76856822Seric { 76964718Seric #ifdef MAYBENEXTRELEASE 77064718Seric if (aliaswait(map, ".db", FALSE)) 77164718Seric return TRUE; 77264718Seric #endif 77360207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 77456836Seric syserr("Cannot open HASH database %s", map->map_file); 77556822Seric return FALSE; 77656822Seric } 77768350Seric #if !OLD_NEWDB 77864373Seric fd = db->fd(db); 77968350Seric # if HASFLOCK 78068350Seric # if !defined(O_EXLOCK) 78164373Seric if (mode == O_RDWR && fd >= 0) 78264388Seric { 78364388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 78464388Seric map->map_mflags |= MF_LOCKED; 78564388Seric } 78668350Seric # else 78764373Seric if (mode == O_RDONLY && fd >= 0) 78864373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 78964388Seric else 79064388Seric map->map_mflags |= MF_LOCKED; 79168350Seric # endif 79260582Seric # endif 79360582Seric #endif 79460585Seric 79560585Seric /* try to make sure that at least the database header is on disk */ 79660585Seric if (mode == O_RDWR) 79766843Seric #if OLD_NEWDB 79864373Seric (void) db->sync(db); 79964373Seric #else 80060585Seric (void) db->sync(db, 0); 80160585Seric 80264373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 80364284Seric map->map_mtime = st.st_mtime; 80464284Seric #endif 80564284Seric 80660089Seric map->map_db2 = (void *) db; 80760207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 80864718Seric if (!aliaswait(map, ".db", TRUE)) 80964718Seric return FALSE; 81056822Seric return TRUE; 81156822Seric } 81256822Seric 81356822Seric 81456822Seric /* 81556822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 81656822Seric */ 81756822Seric 81856822Seric char * 81960089Seric db_map_lookup(map, name, av, statp) 82056822Seric MAP *map; 82160089Seric char *name; 82256822Seric char **av; 82359084Seric int *statp; 82456822Seric { 82556822Seric DBT key, val; 82660422Seric register DB *db = (DB *) map->map_db2; 82760422Seric int st; 82860422Seric int saveerrno; 82964373Seric int fd; 83060089Seric char keybuf[MAXNAME + 1]; 83156822Seric 83260537Seric if (tTd(38, 20)) 83368350Seric printf("db_map_lookup(%s, %s)\n", 83468350Seric map->map_mname, name); 83560089Seric 83660089Seric key.size = strlen(name); 83760089Seric if (key.size > sizeof keybuf - 1) 83860089Seric key.size = sizeof keybuf - 1; 83960089Seric key.data = keybuf; 84060089Seric bcopy(name, keybuf, key.size + 1); 84160207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 84260089Seric makelower(keybuf); 84366843Seric #if !OLD_NEWDB 84464388Seric fd = db->fd(db); 84564388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 84664388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 84760422Seric #endif 84863753Seric st = 1; 84963753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 85063753Seric { 85163753Seric st = db->get(db, &key, &val, 0); 85263753Seric if (st == 0) 85363753Seric map->map_mflags &= ~MF_TRY1NULL; 85463753Seric } 85563753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 85663753Seric { 85763753Seric key.size++; 85863753Seric st = db->get(db, &key, &val, 0); 85963753Seric if (st == 0) 86063753Seric map->map_mflags &= ~MF_TRY0NULL; 86163753Seric } 86260422Seric saveerrno = errno; 86366843Seric #if !OLD_NEWDB 86464388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 86564373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 86660422Seric #endif 86760422Seric if (st != 0) 86860422Seric { 86960422Seric errno = saveerrno; 87060422Seric if (st < 0) 87160422Seric syserr("db_map_lookup: get (%s)", name); 87256822Seric return NULL; 87360422Seric } 87460207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 87563753Seric return map_rewrite(map, name, strlen(name), NULL); 87663753Seric else 87763753Seric return map_rewrite(map, val.data, val.size, av); 87856822Seric } 87956822Seric 88060089Seric 88160089Seric /* 88260089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 88356822Seric */ 88456822Seric 88560089Seric void 88660089Seric db_map_store(map, lhs, rhs) 88760089Seric register MAP *map; 88860089Seric char *lhs; 88960089Seric char *rhs; 89056822Seric { 89160089Seric int stat; 89260089Seric DBT key; 89360089Seric DBT data; 89460089Seric register DB *db = map->map_db2; 89556822Seric 89660537Seric if (tTd(38, 20)) 89768350Seric printf("db_map_store(%s, %s, %s)\n", 89868350Seric map->map_mname, lhs, rhs); 89960089Seric 90060089Seric key.size = strlen(lhs); 90160089Seric key.data = lhs; 90260089Seric 90360089Seric data.size = strlen(rhs); 90460089Seric data.data = rhs; 90560089Seric 90660207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 90756822Seric { 90860089Seric key.size++; 90960089Seric data.size++; 91060089Seric } 91156836Seric 91260089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 91360089Seric if (stat > 0) 91460089Seric { 91560089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 91660089Seric stat = db->put(db, &key, &data, 0); 91760089Seric } 91860089Seric if (stat != 0) 91960089Seric syserr("readaliases: db put (%s)", lhs); 92060089Seric } 92156836Seric 92256847Seric 92360089Seric /* 92460089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 92560089Seric */ 92660089Seric 92760089Seric void 92860089Seric db_map_close(map) 92960089Seric MAP *map; 93060089Seric { 93160089Seric register DB *db = map->map_db2; 93260089Seric 93360537Seric if (tTd(38, 9)) 93468350Seric printf("db_map_close(%s, %s, %x)\n", 93568350Seric map->map_mname, map->map_file, map->map_mflags); 93660089Seric 93760207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 93858804Seric { 93960089Seric /* write out the distinguished alias */ 94060089Seric db_map_store(map, "@", "@"); 94158804Seric } 94258963Seric 94360089Seric if (db->close(db) != 0) 94460089Seric syserr("readaliases: db close failure"); 94556822Seric } 94657208Seric 94760089Seric #endif 94860089Seric /* 94960089Seric ** NIS Modules 95060089Seric */ 95160089Seric 95260089Seric # ifdef NIS 95360089Seric 95464369Seric # ifndef YPERR_BUSY 95564369Seric # define YPERR_BUSY 16 95664369Seric # endif 95764369Seric 95857208Seric /* 95960089Seric ** NIS_MAP_OPEN -- open DBM map 96057208Seric */ 96157208Seric 96257208Seric bool 96360089Seric nis_map_open(map, mode) 96457208Seric MAP *map; 96560089Seric int mode; 96657208Seric { 96757216Seric int yperr; 96860215Seric register char *p; 96960215Seric auto char *vp; 97060215Seric auto int vsize; 97157216Seric char *master; 97257216Seric 97360537Seric if (tTd(38, 2)) 97468350Seric printf("nis_map_open(%s, %s)\n", 97568350Seric map->map_mname, map->map_file); 97660089Seric 97760207Seric if (mode != O_RDONLY) 97860207Seric { 97964650Seric /* issue a pseudo-error message */ 98064650Seric #ifdef ENOSYS 98164650Seric errno = ENOSYS; 98264650Seric #else 98364650Seric # ifdef EFTYPE 98464650Seric errno = EFTYPE; 98564650Seric # else 98664650Seric errno = ENXIO; 98764650Seric # endif 98864650Seric #endif 98960207Seric return FALSE; 99060207Seric } 99160207Seric 99260089Seric p = strchr(map->map_file, '@'); 99360089Seric if (p != NULL) 99460089Seric { 99560089Seric *p++ = '\0'; 99660089Seric if (*p != '\0') 99760089Seric map->map_domain = p; 99860089Seric } 99960215Seric 100060089Seric if (*map->map_file == '\0') 100160089Seric map->map_file = "mail.aliases"; 100260089Seric 100366157Seric if (map->map_domain == NULL) 100466157Seric { 100566157Seric yperr = yp_get_default_domain(&map->map_domain); 100666157Seric if (yperr != 0) 100766157Seric { 100866744Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 100968350Seric syserr("421 NIS map %s specified, but NIS not running\n", 101066744Seric map->map_file); 101166157Seric return FALSE; 101266157Seric } 101366157Seric } 101466157Seric 101560215Seric /* check to see if this map actually exists */ 101660089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 101760089Seric &vp, &vsize); 101860537Seric if (tTd(38, 10)) 101960089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 102060089Seric map->map_domain, map->map_file, yperr_string(yperr)); 102160089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 102268350Seric { 102368350Seric if (!bitset(MF_ALIAS, map->map_mflags) || 102468350Seric aliaswait(map, NULL, TRUE)) 102568350Seric return TRUE; 102668350Seric } 102760215Seric 102860215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 102968350Seric syserr("421 Cannot bind to domain %s: %s", map->map_domain, 103060215Seric yperr_string(yperr)); 103160215Seric 103260089Seric return FALSE; 103360089Seric } 103460089Seric 103560089Seric 103660089Seric /* 103757208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 103857208Seric */ 103957208Seric 104057208Seric char * 104160089Seric nis_map_lookup(map, name, av, statp) 104257208Seric MAP *map; 104360089Seric char *name; 104457208Seric char **av; 104559084Seric int *statp; 104657208Seric { 104757208Seric char *vp; 104857642Seric auto int vsize; 104959274Seric int buflen; 105060215Seric int yperr; 105160089Seric char keybuf[MAXNAME + 1]; 105257208Seric 105360537Seric if (tTd(38, 20)) 105468350Seric printf("nis_map_lookup(%s, %s)\n", 105568350Seric map->map_mname, name); 105660089Seric 105760089Seric buflen = strlen(name); 105860089Seric if (buflen > sizeof keybuf - 1) 105960089Seric buflen = sizeof keybuf - 1; 106060089Seric bcopy(name, keybuf, buflen + 1); 106160207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 106260089Seric makelower(keybuf); 106363753Seric yperr = YPERR_KEY; 106463753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 106563753Seric { 106663753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 106763753Seric &vp, &vsize); 106863753Seric if (yperr == 0) 106963753Seric map->map_mflags &= ~MF_TRY1NULL; 107063753Seric } 107163753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 107263753Seric { 107359274Seric buflen++; 107463753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 107563753Seric &vp, &vsize); 107663753Seric if (yperr == 0) 107763753Seric map->map_mflags &= ~MF_TRY0NULL; 107863753Seric } 107960089Seric if (yperr != 0) 108060089Seric { 108160089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 108260215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 108357208Seric return NULL; 108460089Seric } 108560207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 108663753Seric return map_rewrite(map, name, strlen(name), NULL); 108763753Seric else 108863753Seric return map_rewrite(map, vp, vsize, av); 108957208Seric } 109057208Seric 109168350Seric #endif 109268350Seric /* 109368350Seric ** NISPLUS Modules 109468350Seric ** 109568350Seric ** This code donated by Sun Microsystems. 109668350Seric */ 109767848Seric 109868350Seric #ifdef NISPLUS 109968350Seric 110068350Seric #undef NIS /* symbol conflict in nis.h */ 110168350Seric #include <rpcsvc/nis.h> 110268350Seric #include <rpcsvc/nislib.h> 110368350Seric 110468350Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 110568350Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 110668350Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 110768350Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 110868350Seric 110967848Seric /* 111068350Seric ** NISPLUS_MAP_OPEN -- open nisplus table 111167848Seric */ 111267848Seric 111368350Seric bool 111468350Seric nisplus_map_open(map, mode) 111567848Seric MAP *map; 111668350Seric int mode; 111767848Seric { 111868350Seric register char *p; 111968350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 112068350Seric nis_result *res = NULL; 112168350Seric u_int objs_len; 112268350Seric nis_object *obj_ptr; 112368350Seric int retry_cnt, max_col, i; 112468350Seric 112568350Seric if (tTd(38, 2)) 112668350Seric printf("nisplus_map_open(%s, %s, %d)\n", 112768350Seric map->map_mname, map->map_file, mode); 112868350Seric 112968350Seric if (mode != O_RDONLY) 113068350Seric { 113168350Seric errno = ENODEV; 113268350Seric return FALSE; 113368350Seric } 113468350Seric 113568350Seric if (*map->map_file == '\0') 113668350Seric map->map_file = "mail_aliases.org_dir"; 113768350Seric 113868350Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 113968350Seric { 114068350Seric /* set default NISPLUS Domain to $m */ 114168350Seric extern char *nisplus_default_domain(); 114268350Seric 114368350Seric map->map_domain = newstr(nisplus_default_domain()); 114468350Seric if (tTd(38, 2)) 114568350Seric printf("nisplus_map_open(%s): using domain %s\n", 114668350Seric map->map_file, map->map_domain); 114768350Seric } 114868350Seric if (!PARTIAL_NAME(map->map_file)) 114968350Seric map->map_domain = newstr(""); 115068350Seric 115168350Seric /* check to see if this map actually exists */ 115268350Seric if (PARTIAL_NAME(map->map_file)) 115368350Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 115468350Seric else 115568350Seric strcpy(qbuf, map->map_file); 115668350Seric 115768350Seric retry_cnt = 0; 115868350Seric while (res == NULL || res->status != NIS_SUCCESS) 115968350Seric { 116068350Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 116168350Seric switch (res->status) 116268350Seric { 116368350Seric case NIS_SUCCESS: 116468350Seric case NIS_TRYAGAIN: 116568350Seric case NIS_RPCERROR: 116668350Seric case NIS_NAMEUNREACHABLE: 116768350Seric break; 116868350Seric 116968350Seric default: /* all other nisplus errors */ 117068350Seric #if 0 117168350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 117268350Seric syserr("421 Cannot find table %s.%s: %s", 117368350Seric map->map_file, map->map_domain, 117468350Seric nis_sperrno(res->status)); 117568350Seric #endif 117668350Seric errno = EBADR; 117768350Seric return FALSE; 117868350Seric } 117968350Seric sleep(2); /* try not to overwhelm hosed server */ 118068350Seric if (retry_cnt++ > 4) 118168350Seric { 118268350Seric errno = EBADR; 118368350Seric return FALSE; 118468350Seric } 118568350Seric } 118668350Seric 118768350Seric if (NIS_RES_NUMOBJ(res) != 1 || 118868350Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 118968350Seric { 119068350Seric if (tTd(38, 10)) 119168350Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 119268350Seric #if 0 119368350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 119468350Seric syserr("421 %s.%s: %s is not a table", 119568350Seric map->map_file, map->map_domain, 119668350Seric nis_sperrno(res->status)); 119768350Seric #endif 119868350Seric errno = EBADR; 119968350Seric return FALSE; 120068350Seric } 120168350Seric /* default key column is column 0 */ 120268350Seric if (map->map_keycolnm == NULL) 120368350Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 120468350Seric 120568350Seric max_col = COL_MAX(res); 120668350Seric 120768350Seric /* verify the key column exist */ 120868350Seric for (i=0; i< max_col; i++) 120968350Seric { 121068350Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 121168350Seric break; 121268350Seric } 121368350Seric if (i == max_col) 121468350Seric { 121568350Seric if (tTd(38, 2)) 121668350Seric printf("nisplus_map_open(%s): can not find key column %s\n", 121768350Seric map->map_file, map->map_keycolnm); 121868350Seric errno = EBADR; 121968350Seric return FALSE; 122068350Seric } 122168350Seric 122268350Seric /* default value column is the last column */ 122368350Seric if (map->map_valcolnm == NULL) 122468350Seric { 122568350Seric map->map_valcolno = max_col - 1; 122668350Seric return TRUE; 122768350Seric } 122868350Seric 122968350Seric for (i=0; i< max_col; i++) 123068350Seric { 123168350Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 123268350Seric { 123368350Seric map->map_valcolno = i; 123468350Seric return TRUE; 123568350Seric } 123668350Seric } 123768350Seric 123868350Seric if (tTd(38, 2)) 123968350Seric printf("nisplus_map_open(%s): can not find column %s\n", 124068350Seric map->map_file, map->map_keycolnm); 124168350Seric errno = EBADR; 124268350Seric return FALSE; 124367848Seric } 124467848Seric 124567848Seric 124667848Seric /* 124768350Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 124867848Seric */ 124967848Seric 125068350Seric char * 125168350Seric nisplus_map_lookup(map, name, av, statp) 125267848Seric MAP *map; 125368350Seric char *name; 125468350Seric char **av; 125568350Seric int *statp; 125667848Seric { 125768350Seric char *vp; 125868350Seric auto int vsize; 125968350Seric int buflen; 126068350Seric char search_key[MAXNAME + 1]; 126168350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 126268350Seric nis_result *result; 126368350Seric 126468350Seric if (tTd(38, 20)) 126568350Seric printf("nisplus_map_lookup(%s, %s)\n", 126668350Seric map->map_mname, name); 126768350Seric 126868350Seric if (!bitset(MF_OPEN, map->map_mflags)) 126968350Seric { 127068350Seric if (nisplus_map_open(map, O_RDONLY)) 127168350Seric map->map_mflags |= MF_OPEN; 127268350Seric else 127368350Seric { 127468350Seric *statp = EX_UNAVAILABLE; 127568350Seric return NULL; 127668350Seric } 127768350Seric } 127868350Seric 127968350Seric buflen = strlen(name); 128068350Seric if (buflen > sizeof search_key - 1) 128168350Seric buflen = sizeof search_key - 1; 128268350Seric bcopy(name, search_key, buflen + 1); 128368350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 128468350Seric makelower(search_key); 128568350Seric 128668350Seric /* construct the query */ 128768350Seric if (PARTIAL_NAME(map->map_file)) 128868350Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 128968350Seric search_key, map->map_file, map->map_domain); 129068350Seric else 129168350Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 129268350Seric search_key, map->map_file); 129368350Seric 129468350Seric if (tTd(38, 20)) 129568350Seric printf("qbuf=%s\n", qbuf); 129668350Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 129768350Seric if (result->status == NIS_SUCCESS) 129868350Seric { 129968350Seric int count; 130068350Seric char *str; 130168350Seric 130268350Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 130368350Seric { 130468350Seric if (LogLevel > 10) 130568350Seric syslog(LOG_WARNING, 130668350Seric "%s:Lookup error, expected 1 entry, got (%d)", 130768350Seric map->map_file, count); 130868350Seric 130968350Seric /* ignore second entry */ 131068350Seric if (tTd(38, 20)) 131168350Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 131268350Seric name, count); 131368350Seric } 131468350Seric 131568350Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 131668350Seric /* set the length of the result */ 131768350Seric if (vp == NULL) 131868350Seric vp = ""; 131968350Seric vsize = strlen(vp); 132068350Seric if (tTd(38, 20)) 132168350Seric printf("nisplus_map_lookup(%s), found %s\n", 132268350Seric name, vp); 132368350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 132468350Seric str = map_rewrite(map, name, strlen(name), NULL); 132568350Seric else 132668350Seric str = map_rewrite(map, vp, vsize, av); 132768350Seric nis_freeresult(result); 132868350Seric #ifdef MAP_EXIT_STAT 132968350Seric *statp = EX_OK; 133068350Seric #endif 133168350Seric return str; 133268350Seric } 133368350Seric else 133468350Seric { 133568350Seric #ifdef MAP_EXIT_STAT 133668350Seric if (result->status == NIS_NOTFOUND) 133768350Seric *statp = EX_NOTFOUND; 133868350Seric else if (result->status == NIS_TRYAGAIN) 133968350Seric *statp = EX_TEMPFAIL; 134068350Seric else 134168350Seric { 134268350Seric *statp = EX_UNAVAILABLE; 134368350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 134468350Seric } 134568350Seric #else 134668350Seric if ((result->status != NIS_NOTFOUND) && 134768350Seric (result->status != NIS_TRYAGAIN)) 134868350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 134968350Seric #endif 135068350Seric } 135168350Seric if (tTd(38, 20)) 135268350Seric printf("nisplus_map_lookup(%s), failed\n", name); 135368350Seric nis_freeresult(result); 135468350Seric return NULL; 135567848Seric } 135667848Seric 135768350Seric 135868350Seric char * 135968350Seric nisplus_default_domain() 136068350Seric { 136168350Seric static char default_domain[MAXNAME] = ""; 136268350Seric nis_result *res = NULL; 136368350Seric char *p; 136468350Seric 136568350Seric if (default_domain[0] != '\0') 136668350Seric return(default_domain); 136768350Seric 136868350Seric if (VendorCode == VENDOR_SUN && ConfigLevel < 2) 136968350Seric { 137068350Seric /* for old config, user nis+ local directory */ 137168350Seric /* have to be backward compatible with bugs too :-( */ 137268350Seric p = nis_local_directory(); 137368350Seric strcpy(default_domain, p); 137468350Seric return default_domain; 137568350Seric } 137668350Seric 137768350Seric if ((p = macvalue('m', CurEnv)) == NULL) 137868350Seric { 137968350Seric p = nis_local_directory(); 138068350Seric strcpy(default_domain, p); 138168350Seric return default_domain; 138268350Seric } 138368350Seric 138468350Seric strcpy(default_domain, p); 138568350Seric if (PARTIAL_NAME(default_domain)) 138668350Seric strcat(default_domain, "."); 138768350Seric 138868350Seric res = nis_lookup(default_domain, FOLLOW_LINKS); 138968350Seric if (res->status == NIS_NOTFOUND) 139068350Seric { 139168350Seric p = nis_local_directory(); 139268350Seric strcpy(default_domain, p); 139368350Seric } 139468350Seric return(default_domain); 139568350Seric } 139668350Seric 139768350Seric #endif /* NISPLUS */ 139867848Seric /* 139968350Seric ** HESIOD Modules 140068350Seric */ 140168350Seric 140268350Seric #ifdef HESIOD 140368350Seric 140468350Seric #include <hesiod.h> 140568350Seric 140668350Seric char * 140768350Seric hes_map_lookup(map, name, av, statp) 140868350Seric MAP *map; 140968350Seric char *name; 141068350Seric char **av; 141168350Seric int *statp; 141268350Seric { 141368350Seric char **hp; 141468350Seric char *retdata = NULL; 141568350Seric int i; 141668350Seric 141768350Seric if (tTd(38, 20)) 141868350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 141968350Seric 142068350Seric hp = hes_resolve(name, map->map_file); 142168350Seric if (hp == NULL) 142268350Seric return NULL; 142368350Seric 142468350Seric if (hp[0] != NULL) 142568350Seric { 142668350Seric if (tTd(38, 20)) 1427*68395Seric printf(" %d %s\n", i, hp[0]); 142868350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 142968350Seric retdata = map_rewrite(map, name, strlen(name), NULL); 143068350Seric else 143168350Seric retdata = map_rewrite(map, hp[0], strlen(hp[0]), av); 143268350Seric } 143368350Seric 143468350Seric for (i = 0; hp[i] != NULL; i++) 143568350Seric free(hp[i]); 143668350Seric free(hp); 143768350Seric return retdata; 143868350Seric } 143968350Seric 144068350Seric #endif 144168350Seric /* 144268350Seric ** NeXT NETINFO Modules 144368350Seric */ 144468350Seric 144568350Seric #ifdef NETINFO 144668350Seric 144768350Seric #define NETINFO_DEFAULT_DIR "/aliases" 144868350Seric #define NETINFO_DEFAULT_PROPERTY "members" 144968350Seric 145068350Seric 145168350Seric /* 145268350Seric ** NI_MAP_OPEN -- open NetInfo Aliases 145368350Seric */ 145468350Seric 145568350Seric bool 145668350Seric ni_map_open(map, mode) 145768350Seric MAP *map; 145868350Seric int mode; 145968350Seric { 146068350Seric char *p; 146168350Seric 146268350Seric if (tTd(38, 20)) 146368350Seric printf("ni_map_open: %s\n", map->map_file); 146468350Seric 146568350Seric if (*map->map_file == '\0') 146668350Seric map->map_file = NETINFO_DEFAULT_DIR; 146768350Seric 146868350Seric if (map->map_valcolnm == NULL) 146968350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 147068350Seric 147168350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 147268350Seric map->map_coldelim = ','; 147368350Seric 147468350Seric return TRUE; 147568350Seric } 147668350Seric 147768350Seric 147868350Seric /* 147968350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 148068350Seric */ 148168350Seric 148268350Seric char * 148368350Seric ni_map_lookup(map, name, av, statp) 148468350Seric MAP *map; 148568350Seric char *name; 148668350Seric char **av; 148768350Seric int *statp; 148868350Seric { 148968350Seric char *res; 149068350Seric char *propval; 149168350Seric extern char *ni_propval(); 149268350Seric 149368350Seric if (tTd(38, 20)) 149468350Seric printf("ni_map_lookup(%s, %s)\n", 149568350Seric map->map_mname, name); 149668350Seric 149768350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 149868350Seric map->map_valcolnm, map->map_coldelim); 149968350Seric 150068350Seric if (propval == NULL) 150168350Seric return NULL; 150268350Seric 150368350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 150468350Seric res = map_rewrite(map, name, strlen(name), NULL); 150568350Seric else 150668350Seric res = map_rewrite(map, propval, strlen(propval), av); 150768350Seric free(propval); 150868350Seric return res; 150968350Seric } 151068350Seric 151168350Seric #endif 151268350Seric /* 151368350Seric ** TEXT (unindexed text file) Modules 151468350Seric ** 151568350Seric ** This code donated by Sun Microsystems. 151668350Seric */ 151768350Seric 151868350Seric 151968350Seric /* 152068350Seric ** TEXT_MAP_OPEN -- open text table 152168350Seric */ 152268350Seric 152368350Seric bool 152468350Seric text_map_open(map, mode) 152568350Seric MAP *map; 152668350Seric int mode; 152768350Seric { 152868350Seric struct stat sbuf; 152968350Seric 153068350Seric if (tTd(38, 2)) 153168350Seric printf("text_map_open(%s, %s, %d)\n", 153268350Seric map->map_mname, map->map_file, mode); 153368350Seric 153468350Seric if (mode != O_RDONLY) 153568350Seric { 153668350Seric errno = ENODEV; 153768350Seric return FALSE; 153868350Seric } 153968350Seric 154068350Seric if (*map->map_file == '\0') 154168350Seric { 154268350Seric if (tTd(38, 2)) 154368350Seric printf("text_map_open: file name required\n"); 154468350Seric return FALSE; 154568350Seric } 154668350Seric 154768350Seric if (map->map_file[0] != '/') 154868350Seric { 154968350Seric if (tTd(38, 2)) 155068350Seric printf("text_map_open(%s): file name must be fully qualified\n", 155168350Seric map->map_file); 155268350Seric return FALSE; 155368350Seric } 155468350Seric /* check to see if this map actually accessable */ 155568350Seric if (access(map->map_file, R_OK) <0) 155668350Seric return FALSE; 155768350Seric 155868350Seric /* check to see if this map actually exist */ 155968350Seric if (stat(map->map_file, &sbuf) <0) 156068350Seric { 156168350Seric if (tTd(38, 2)) 156268350Seric printf("text_map_open(%s): can not stat %s\n", 156368350Seric map->map_file, map->map_file); 156468350Seric return FALSE; 156568350Seric } 156668350Seric 156768350Seric if (!S_ISREG(sbuf.st_mode)) 156868350Seric { 156968350Seric if (tTd(38, 2)) 157068350Seric printf("text_map_open(%s): %s is not a file\n", 157168350Seric map->map_file, map->map_file); 157268350Seric return FALSE; 157368350Seric } 157468350Seric 157568350Seric if (map->map_keycolnm == NULL) 157668350Seric map->map_keycolno = 0; 157768350Seric else 157868350Seric { 157968350Seric if (!isdigit(*map->map_keycolnm)) 158068350Seric { 158168350Seric if (tTd(38, 2)) 158268350Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 158368350Seric map->map_file, map->map_keycolnm); 158468350Seric return FALSE; 158568350Seric } 158668350Seric map->map_keycolno = atoi(map->map_keycolnm); 158768350Seric } 158868350Seric 158968350Seric if (map->map_valcolnm == NULL) 159068350Seric map->map_valcolno = 0; 159168350Seric else 159268350Seric { 159368350Seric if (!isdigit(*map->map_valcolnm)) 159468350Seric { 159568350Seric if (tTd(38, 2)) 159668350Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 159768350Seric map->map_file, map->map_valcolnm); 159868350Seric return FALSE; 159968350Seric } 160068350Seric map->map_valcolno = atoi(map->map_valcolnm); 160168350Seric } 160268350Seric 160368350Seric if (map->map_coldelim == '\0') 160468350Seric map->map_coldelim = ':'; 160568350Seric 160668350Seric if (tTd(38, 2)) 160768350Seric { 160868350Seric printf("text_map_open(%s): delimiter = %c\n", 160968350Seric map->map_file, map->map_coldelim); 161068350Seric } 161168350Seric 161268350Seric return TRUE; 161368350Seric } 161468350Seric 161568350Seric 161668350Seric /* 161768350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 161868350Seric */ 161968350Seric 162068350Seric char * 162168350Seric text_map_lookup(map, name, av, statp) 162268350Seric MAP *map; 162368350Seric char *name; 162468350Seric char **av; 162568350Seric int *statp; 162668350Seric { 162768350Seric char *vp; 162868350Seric auto int vsize; 162968350Seric int buflen; 163068350Seric char search_key[MAXNAME + 1]; 163168350Seric char linebuf[MAXLINE]; 163268350Seric FILE *f; 163368350Seric char buf[MAXNAME+1]; 163468350Seric char delim; 163568350Seric int key_idx; 163668350Seric bool found_it; 163768350Seric extern char *get_column(); 163868350Seric 163968350Seric 164068350Seric found_it = FALSE; 164168350Seric if (tTd(38, 20)) 164268350Seric printf("text_map_lookup(%s)\n", name); 164368350Seric 164468350Seric buflen = strlen(name); 164568350Seric if (buflen > sizeof search_key - 1) 164668350Seric buflen = sizeof search_key - 1; 164768350Seric bcopy(name, search_key, buflen + 1); 164868350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 164968350Seric makelower(search_key); 165068350Seric 165168350Seric f = fopen(map->map_file, "r"); 165268350Seric if (f == NULL) 165368350Seric { 165468350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 165568350Seric *statp = EX_UNAVAILABLE; 165668350Seric return NULL; 165768350Seric } 165868350Seric key_idx = map->map_keycolno; 165968350Seric delim = map->map_coldelim; 166068350Seric while (fgets(linebuf, MAXLINE, f)) 166168350Seric { 166268350Seric char *lf; 166368350Seric if (linebuf[0] == '#') 166468350Seric continue; /* skip comment line */ 166568350Seric if (lf = strchr(linebuf, '\n')) 166668350Seric *lf = '\0'; 166768350Seric if (!strcasecmp(search_key, 166868350Seric get_column(linebuf, key_idx, delim, buf))) 166968350Seric { 167068350Seric found_it = TRUE; 167168350Seric break; 167268350Seric } 167368350Seric } 167468350Seric fclose(f); 167568350Seric if (!found_it) 167668350Seric { 167768350Seric #ifdef MAP_EXIT_STAT 167868350Seric *statp = EX_NOTFOUND; 167968350Seric #endif 168068350Seric return(NULL); 168168350Seric } 168268350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 168368350Seric vsize = strlen(vp); 168468350Seric #ifdef MAP_EXIT_STAT 168568350Seric *statp = EX_OK; 168668350Seric #endif 168768350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 168868350Seric return map_rewrite(map, name, strlen(name), NULL); 168968350Seric else 169068350Seric return map_rewrite(map, vp, vsize, av); 169168350Seric } 169268350Seric /* 169360089Seric ** STAB (Symbol Table) Modules 169460089Seric */ 169560089Seric 169660089Seric 169760089Seric /* 169860207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 169960089Seric */ 170060089Seric 170160089Seric char * 170261707Seric stab_map_lookup(map, name, av, pstat) 170360089Seric register MAP *map; 170460089Seric char *name; 170561707Seric char **av; 170661707Seric int *pstat; 170760089Seric { 170860089Seric register STAB *s; 170960089Seric 171060537Seric if (tTd(38, 20)) 171168350Seric printf("stab_lookup(%s, %s)\n", 171268350Seric map->map_mname, name); 171360089Seric 171460089Seric s = stab(name, ST_ALIAS, ST_FIND); 171560089Seric if (s != NULL) 171660089Seric return (s->s_alias); 171760089Seric return (NULL); 171860089Seric } 171960089Seric 172060089Seric 172160089Seric /* 172260207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 172360089Seric */ 172460089Seric 172560089Seric void 172660089Seric stab_map_store(map, lhs, rhs) 172760089Seric register MAP *map; 172860089Seric char *lhs; 172960089Seric char *rhs; 173060089Seric { 173160089Seric register STAB *s; 173260089Seric 173360089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 173460089Seric s->s_alias = newstr(rhs); 173560089Seric } 173660089Seric 173760089Seric 173860089Seric /* 173960207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 174060207Seric ** 174160207Seric ** This is a wierd case -- it is only intended as a fallback for 174260207Seric ** aliases. For this reason, opens for write (only during a 174360207Seric ** "newaliases") always fails, and opens for read open the 174460207Seric ** actual underlying text file instead of the database. 174560089Seric */ 174660089Seric 174760089Seric bool 174860089Seric stab_map_open(map, mode) 174960089Seric register MAP *map; 175060089Seric int mode; 175160089Seric { 175263835Seric FILE *af; 175364284Seric struct stat st; 175463835Seric 175560537Seric if (tTd(38, 2)) 175668350Seric printf("stab_map_open(%s, %s)\n", 175768350Seric map->map_mname, map->map_file); 175860089Seric 175960089Seric if (mode != O_RDONLY) 176060207Seric { 176160207Seric errno = ENODEV; 176260089Seric return FALSE; 176360207Seric } 176460089Seric 176563835Seric af = fopen(map->map_file, "r"); 176663835Seric if (af == NULL) 176763835Seric return FALSE; 176868350Seric readaliases(map, af, FALSE, FALSE); 176964284Seric 177064284Seric if (fstat(fileno(af), &st) >= 0) 177164284Seric map->map_mtime = st.st_mtime; 177263835Seric fclose(af); 177363835Seric 177460089Seric return TRUE; 177560089Seric } 177660089Seric /* 177760089Seric ** Implicit Modules 177856822Seric ** 177960089Seric ** Tries several types. For back compatibility of aliases. 178056822Seric */ 178156822Seric 178260089Seric 178360089Seric /* 178460207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 178560089Seric */ 178660089Seric 178760089Seric char * 178860089Seric impl_map_lookup(map, name, av, pstat) 178960089Seric MAP *map; 179060089Seric char *name; 179156822Seric char **av; 179260089Seric int *pstat; 179356822Seric { 179460537Seric if (tTd(38, 20)) 179568350Seric printf("impl_map_lookup(%s, %s)\n", 179668350Seric map->map_mname, name); 179756822Seric 179860089Seric #ifdef NEWDB 179960207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 180060089Seric return db_map_lookup(map, name, av, pstat); 180160089Seric #endif 180260089Seric #ifdef NDBM 180360207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 180460089Seric return ndbm_map_lookup(map, name, av, pstat); 180560089Seric #endif 180660089Seric return stab_map_lookup(map, name, av, pstat); 180760089Seric } 180860089Seric 180960089Seric /* 181060207Seric ** IMPL_MAP_STORE -- store in open databases 181160089Seric */ 181260089Seric 181360089Seric void 181460089Seric impl_map_store(map, lhs, rhs) 181560089Seric MAP *map; 181660089Seric char *lhs; 181760089Seric char *rhs; 181860089Seric { 181960089Seric #ifdef NEWDB 182060207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 182160089Seric db_map_store(map, lhs, rhs); 182260089Seric #endif 182360089Seric #ifdef NDBM 182460207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 182560089Seric ndbm_map_store(map, lhs, rhs); 182660089Seric #endif 182760089Seric stab_map_store(map, lhs, rhs); 182860089Seric } 182960089Seric 183060089Seric /* 183160089Seric ** IMPL_MAP_OPEN -- implicit database open 183260089Seric */ 183360089Seric 183460089Seric bool 183560089Seric impl_map_open(map, mode) 183660089Seric MAP *map; 183760089Seric int mode; 183860089Seric { 183960089Seric struct stat stb; 184060089Seric 184160537Seric if (tTd(38, 2)) 184268350Seric printf("impl_map_open(%s, %s, %d)\n", 184368350Seric map->map_mname, map->map_file, mode); 184460089Seric 184560089Seric if (stat(map->map_file, &stb) < 0) 184656822Seric { 184760089Seric /* no alias file at all */ 184864718Seric if (tTd(38, 3)) 184964718Seric printf("no map file\n"); 185060089Seric return FALSE; 185156822Seric } 185256822Seric 185360089Seric #ifdef NEWDB 185460207Seric map->map_mflags |= MF_IMPL_HASH; 185560089Seric if (hash_map_open(map, mode)) 185656822Seric { 185764250Seric #if defined(NDBM) && defined(NIS) 185860561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 185960207Seric #endif 186060207Seric return TRUE; 186160089Seric } 186260207Seric else 186360207Seric map->map_mflags &= ~MF_IMPL_HASH; 186460089Seric #endif 186560089Seric #ifdef NDBM 186660207Seric map->map_mflags |= MF_IMPL_NDBM; 186760089Seric if (ndbm_map_open(map, mode)) 186860089Seric { 186960089Seric return TRUE; 187060089Seric } 187160207Seric else 187260207Seric map->map_mflags &= ~MF_IMPL_NDBM; 187360089Seric #endif 187456822Seric 187564650Seric #if defined(NEWDB) || defined(NDBM) 187660089Seric if (Verbose) 187760089Seric message("WARNING: cannot open alias database %s", map->map_file); 187864964Seric #else 187964964Seric if (mode != O_RDONLY) 188064964Seric usrerr("Cannot rebuild aliases: no database format defined"); 188160207Seric #endif 188260089Seric 188360207Seric return stab_map_open(map, mode); 188456822Seric } 188560089Seric 188660207Seric 188760089Seric /* 188860207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 188960089Seric */ 189060089Seric 189160089Seric void 189260207Seric impl_map_close(map) 189360089Seric MAP *map; 189460089Seric { 189568350Seric if (tTd(38, 20)) 189668350Seric printf("impl_map_close(%s, %s, %x)\n", 189768350Seric map->map_mname, map->map_file, map->map_mflags); 189860089Seric #ifdef NEWDB 189960207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 190060089Seric { 190160207Seric db_map_close(map); 190260207Seric map->map_mflags &= ~MF_IMPL_HASH; 190360089Seric } 190460089Seric #endif 190560089Seric 190660089Seric #ifdef NDBM 190760207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 190860089Seric { 190960207Seric ndbm_map_close(map); 191060207Seric map->map_mflags &= ~MF_IMPL_NDBM; 191160089Seric } 191260089Seric #endif 191360089Seric } 191460207Seric /* 191568350Seric ** User map class. 191668350Seric ** 191768350Seric ** Provides access to the system password file. 191868350Seric */ 191968350Seric 192068350Seric /* 192168350Seric ** USER_MAP_OPEN -- open user map 192268350Seric ** 192368350Seric ** Really just binds field names to field numbers. 192468350Seric */ 192568350Seric 192668350Seric bool 192768350Seric user_map_open(map, mode) 192868350Seric MAP *map; 192968350Seric int mode; 193068350Seric { 193168350Seric if (tTd(38, 2)) 193268350Seric printf("user_map_open(%s)\n", map->map_mname); 193368350Seric 193468350Seric if (mode != O_RDONLY) 193568350Seric { 193668350Seric /* issue a pseudo-error message */ 193768350Seric #ifdef ENOSYS 193868350Seric errno = ENOSYS; 193968350Seric #else 194068350Seric # ifdef EFTYPE 194168350Seric errno = EFTYPE; 194268350Seric # else 194368350Seric errno = ENXIO; 194468350Seric # endif 194568350Seric #endif 194668350Seric return FALSE; 194768350Seric } 194868350Seric if (map->map_valcolnm == NULL) 194968350Seric /* nothing */ ; 195068350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 195168350Seric map->map_valcolno = 1; 195268350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 195368350Seric map->map_valcolno = 2; 195468350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 195568350Seric map->map_valcolno = 3; 195668350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 195768350Seric map->map_valcolno = 4; 195868350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 195968350Seric map->map_valcolno = 5; 196068350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 196168350Seric map->map_valcolno = 6; 196268350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 196368350Seric map->map_valcolno = 7; 196468350Seric else 196568350Seric { 196668350Seric syserr("User map %s: unknown column name %s", 196768350Seric map->map_mname, map->map_valcolnm); 196868350Seric return FALSE; 196968350Seric } 197068350Seric return TRUE; 197168350Seric } 197268350Seric 197368350Seric 197468350Seric /* 197568350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 197668350Seric */ 197768350Seric 197868350Seric #include <pwd.h> 197968350Seric 198068350Seric char * 198168350Seric user_map_lookup(map, key, av, statp) 198268350Seric MAP *map; 198368350Seric char *key; 198468350Seric char **av; 198568350Seric int *statp; 198668350Seric { 198768350Seric struct passwd *pw; 198868350Seric 198968350Seric if (tTd(38, 20)) 199068350Seric printf("user_map_lookup(%s, %s)\n", 199168350Seric map->map_mname, key); 199268350Seric 199368350Seric pw = getpwnam(key); 199468350Seric if (pw == NULL) 199568350Seric return NULL; 199668350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 199768350Seric return map_rewrite(map, key, strlen(key), NULL); 199868350Seric else 199968350Seric { 200068350Seric char *rwval; 200168350Seric char buf[30]; 200268350Seric 200368350Seric switch (map->map_valcolno) 200468350Seric { 200568350Seric case 0: 200668350Seric case 1: 200768350Seric rwval = pw->pw_name; 200868350Seric break; 200968350Seric 201068350Seric case 2: 201168350Seric rwval = pw->pw_passwd; 201268350Seric break; 201368350Seric 201468350Seric case 3: 201568350Seric sprintf(buf, "%d", pw->pw_uid); 201668350Seric rwval = buf; 201768350Seric break; 201868350Seric 201968350Seric case 4: 202068350Seric sprintf(buf, "%d", pw->pw_gid); 202168350Seric rwval = buf; 202268350Seric break; 202368350Seric 202468350Seric case 5: 202568350Seric rwval = pw->pw_gecos; 202668350Seric break; 202768350Seric 202868350Seric case 6: 202968350Seric rwval = pw->pw_dir; 203068350Seric break; 203168350Seric 203268350Seric case 7: 203368350Seric rwval = pw->pw_shell; 203468350Seric break; 203568350Seric } 203668350Seric return map_rewrite(map, rwval, strlen(rwval), av); 203768350Seric } 203868350Seric } 203968350Seric /* 204068350Seric ** BESTMX -- find the best MX for a name 204168350Seric ** 204268350Seric ** This is really a hack, but I don't see any obvious way 204368350Seric ** to generalize it at the moment. 204468350Seric */ 204568350Seric 204668350Seric #if NAMED_BIND 204768350Seric 204868350Seric char * 204968350Seric bestmx_map_lookup(map, name, av, statp) 205068350Seric MAP *map; 205168350Seric char *name; 205268350Seric char **av; 205368350Seric int *statp; 205468350Seric { 205568350Seric int nmx; 205668350Seric auto int rcode; 205768350Seric char *mxhosts[MAXMXHOSTS + 1]; 205868350Seric 205968350Seric nmx = getmxrr(name, mxhosts, FALSE, &rcode); 206068350Seric if (nmx <= 0) 206168350Seric return NULL; 206268350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 206368350Seric return map_rewrite(map, name, strlen(name), NULL); 206468350Seric else 206568350Seric return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 206668350Seric } 206768350Seric 206868350Seric #endif 206968350Seric /* 207068350Seric ** Sequenced map type. 207168350Seric ** 207268350Seric ** Tries each map in order until something matches, much like 207368350Seric ** implicit. Stores go to the first map in the list that can 207468350Seric ** support storing. 207568350Seric ** 207668350Seric ** This is slightly unusual in that there are two interfaces. 207768350Seric ** The "sequence" interface lets you stack maps arbitrarily. 207868350Seric ** The "switch" interface builds a sequence map by looking 207968350Seric ** at a system-dependent configuration file such as 208068350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 208168350Seric ** 208268350Seric ** We don't need an explicit open, since all maps are 208368350Seric ** opened during startup, including underlying maps. 208468350Seric */ 208568350Seric 208668350Seric /* 208768350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 208868350Seric */ 208968350Seric 209068350Seric bool 209168350Seric seq_map_parse(map, ap) 209268350Seric MAP *map; 209368350Seric char *ap; 209468350Seric { 209568350Seric int maxmap; 209668350Seric 209768350Seric if (tTd(38, 2)) 209868350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 209968350Seric maxmap = 0; 210068350Seric while (*ap != '\0') 210168350Seric { 210268350Seric register char *p; 210368350Seric STAB *s; 210468350Seric 210568350Seric /* find beginning of map name */ 210668350Seric while (isascii(*ap) && isspace(*ap)) 210768350Seric ap++; 210868350Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 210968350Seric continue; 211068350Seric if (*p != '\0') 211168350Seric *p++ = '\0'; 211268350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 211368350Seric p++; 211468350Seric if (*ap == '\0') 211568350Seric { 211668350Seric ap = p; 211768350Seric continue; 211868350Seric } 211968350Seric s = stab(ap, ST_MAP, ST_FIND); 212068350Seric if (s == NULL) 212168350Seric { 212268350Seric syserr("Sequence map %s: unknown member map %s", 212368350Seric map->map_mname, ap); 212468350Seric } 212568350Seric else if (maxmap == MAXMAPSTACK) 212668350Seric { 212768350Seric syserr("Sequence map %s: too many member maps (%d max)", 212868350Seric map->map_mname, MAXMAPSTACK); 212968350Seric maxmap++; 213068350Seric } 213168350Seric else if (maxmap < MAXMAPSTACK) 213268350Seric { 213368350Seric map->map_stack[maxmap++] = &s->s_map; 213468350Seric } 213568350Seric ap = p; 213668350Seric } 213768350Seric return TRUE; 213868350Seric } 213968350Seric 214068350Seric 214168350Seric /* 214268350Seric ** SWITCH_MAP_OPEN -- open a switched map 214368350Seric ** 214468350Seric ** This looks at the system-dependent configuration and builds 214568350Seric ** a sequence map that does the same thing. 214668350Seric ** 214768350Seric ** Every system must define a switch_map_find routine in conf.c 214868350Seric ** that will return the list of service types associated with a 214968350Seric ** given service class. 215068350Seric */ 215168350Seric 215268350Seric bool 215368350Seric switch_map_open(map, mode) 215468350Seric MAP *map; 215568350Seric int mode; 215668350Seric { 215768350Seric int mapno; 215868350Seric int nmaps; 215968350Seric char *maptype[MAXMAPSTACK]; 216068350Seric 216168350Seric if (tTd(38, 2)) 216268350Seric printf("switch_map_open(%s, %s, %d)\n", 216368350Seric map->map_mname, map->map_file, mode); 216468350Seric 216568350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 216668350Seric if (tTd(38, 19)) 216768350Seric { 216868350Seric printf("\tswitch_map_find => %d\n", nmaps); 216968350Seric for (mapno = 0; mapno < nmaps; mapno++) 217068350Seric printf("\t\t%s\n", maptype[mapno]); 217168350Seric } 217268350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 217368350Seric return FALSE; 217468350Seric 217568350Seric for (mapno = 0; mapno < nmaps; mapno++) 217668350Seric { 217768350Seric register STAB *s; 217868350Seric char nbuf[MAXNAME + 1]; 217968350Seric 218068350Seric if (maptype[mapno] == NULL) 218168350Seric continue; 218268350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 218368350Seric s = stab(nbuf, ST_MAP, ST_FIND); 218468350Seric if (s == NULL) 218568350Seric { 218668350Seric syserr("Switch map %s: unknown member map %s", 218768350Seric map->map_mname, nbuf); 218868350Seric } 218968350Seric else 219068350Seric { 219168350Seric map->map_stack[mapno] = &s->s_map; 219268350Seric if (tTd(38, 4)) 219368350Seric printf("\tmap_stack[%d] = %s:%s\n", 219468350Seric mapno, s->s_map.map_class->map_cname, 219568350Seric nbuf); 219668350Seric } 219768350Seric } 219868350Seric return TRUE; 219968350Seric } 220068350Seric 220168350Seric 220268350Seric /* 220368350Seric ** SEQ_MAP_CLOSE -- close all underlying maps 220468350Seric */ 220568350Seric 220668350Seric seq_map_close(map) 220768350Seric MAP *map; 220868350Seric { 220968350Seric int mapno; 221068350Seric 221168350Seric if (tTd(38, 20)) 221268350Seric printf("seq_map_close(%s)\n", map->map_mname); 221368350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 221468350Seric { 221568350Seric MAP *mm = map->map_stack[mapno]; 221668350Seric 221768350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 221868350Seric continue; 221968350Seric mm->map_class->map_close(mm); 222068350Seric } 222168350Seric } 222268350Seric 222368350Seric 222468350Seric /* 222568350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 222668350Seric */ 222768350Seric 222868350Seric char * 222968350Seric seq_map_lookup(map, key, args, pstat) 223068350Seric MAP *map; 223168350Seric char *key; 223268350Seric char **args; 223368350Seric int *pstat; 223468350Seric { 223568350Seric int mapno; 223668350Seric int mapbit = 0x01; 223768350Seric 223868350Seric if (tTd(38, 20)) 223968350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 224068350Seric 224168350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 224268350Seric { 224368350Seric MAP *mm = map->map_stack[mapno]; 224468350Seric int stat = 0; 224568350Seric char *rv; 224668350Seric 224768350Seric if (mm == NULL) 224868350Seric continue; 224968350Seric if (!bitset(MF_OPEN, mm->map_mflags)) 225068350Seric { 225168350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 225268350Seric { 225368350Seric *pstat = EX_UNAVAILABLE; 225468350Seric return NULL; 225568350Seric } 225668350Seric continue; 225768350Seric } 225868350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 225968350Seric if (rv != NULL) 226068350Seric return rv; 226168350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 226268350Seric return NULL; 226368350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 226468350Seric { 226568350Seric *pstat = stat; 226668350Seric return NULL; 226768350Seric } 226868350Seric } 226968350Seric return NULL; 227068350Seric } 227168350Seric 227268350Seric 227368350Seric /* 227468350Seric ** SEQ_MAP_STORE -- sequenced map store 227568350Seric */ 227668350Seric 227768350Seric void 227868350Seric seq_map_store(map, key, val) 227968350Seric MAP *map; 228068350Seric char *key; 228168350Seric char *val; 228268350Seric { 228368350Seric int mapno; 228468350Seric 228568350Seric if (tTd(38, 12)) 228668350Seric printf("seq_map_store(%s, %s, %s)\n", 228768350Seric map->map_mname, key, val); 228868350Seric 228968350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 229068350Seric { 229168350Seric MAP *mm = map->map_stack[mapno]; 229268350Seric 229368350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 229468350Seric continue; 229568350Seric 229668350Seric mm->map_class->map_store(mm, key, val); 229768350Seric return; 229868350Seric } 229968350Seric syserr("seq_map_store(%s, %s, %s): no writable map", 230068350Seric map->map_mname, key, val); 230168350Seric } 230268350Seric /* 230360207Seric ** NULL stubs 230460089Seric */ 230560089Seric 230660207Seric bool 230760207Seric null_map_open(map, mode) 230860089Seric MAP *map; 230960207Seric int mode; 231060089Seric { 231160207Seric return TRUE; 231260089Seric } 231360089Seric 231460207Seric void 231560207Seric null_map_close(map) 231660207Seric MAP *map; 231760089Seric { 231860207Seric return; 231960207Seric } 232060089Seric 232160207Seric void 232260207Seric null_map_store(map, key, val) 232360207Seric MAP *map; 232460207Seric char *key; 232560207Seric char *val; 232660089Seric { 232760207Seric return; 232860089Seric } 232968350Seric 233068350Seric 233168350Seric /* 233268350Seric ** BOGUS stubs 233368350Seric */ 233468350Seric 233568350Seric char * 233668350Seric bogus_map_lookup(map, key, args, pstat) 233768350Seric MAP *map; 233868350Seric char *key; 233968350Seric char **args; 234068350Seric int *pstat; 234168350Seric { 234268350Seric *pstat = EX_TEMPFAIL; 234368350Seric return NULL; 234468350Seric } 234568350Seric 234668350Seric MAPCLASS BogusMapClass = 234768350Seric { 234868350Seric "bogus-map", NULL, 0, 234968350Seric NULL, bogus_map_lookup, null_map_store, 235068350Seric null_map_open, null_map_close, 235168350Seric }; 2352