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*68458Seric static char sccsid[] = "@(#)map.c 8.45 (Berkeley) 02/28/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 char *p; 136368350Seric 136468350Seric if (default_domain[0] != '\0') 136568350Seric return(default_domain); 136668350Seric 1367*68458Seric p = nis_local_directory(); 136868350Seric strcpy(default_domain, p); 1369*68458Seric return default_domain; 137068350Seric } 137168350Seric 137268350Seric #endif /* NISPLUS */ 137367848Seric /* 137468350Seric ** HESIOD Modules 137568350Seric */ 137668350Seric 137768350Seric #ifdef HESIOD 137868350Seric 137968350Seric #include <hesiod.h> 138068350Seric 138168350Seric char * 138268350Seric hes_map_lookup(map, name, av, statp) 138368350Seric MAP *map; 138468350Seric char *name; 138568350Seric char **av; 138668350Seric int *statp; 138768350Seric { 138868350Seric char **hp; 138968350Seric char *retdata = NULL; 139068350Seric int i; 139168350Seric 139268350Seric if (tTd(38, 20)) 139368350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 139468350Seric 139568350Seric hp = hes_resolve(name, map->map_file); 139668350Seric if (hp == NULL) 139768350Seric return NULL; 139868350Seric 139968350Seric if (hp[0] != NULL) 140068350Seric { 140168350Seric if (tTd(38, 20)) 140268395Seric printf(" %d %s\n", i, hp[0]); 140368350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 140468350Seric retdata = map_rewrite(map, name, strlen(name), NULL); 140568350Seric else 140668350Seric retdata = map_rewrite(map, hp[0], strlen(hp[0]), av); 140768350Seric } 140868350Seric 140968350Seric for (i = 0; hp[i] != NULL; i++) 141068350Seric free(hp[i]); 141168350Seric free(hp); 141268350Seric return retdata; 141368350Seric } 141468350Seric 141568350Seric #endif 141668350Seric /* 141768350Seric ** NeXT NETINFO Modules 141868350Seric */ 141968350Seric 142068350Seric #ifdef NETINFO 142168350Seric 142268350Seric #define NETINFO_DEFAULT_DIR "/aliases" 142368350Seric #define NETINFO_DEFAULT_PROPERTY "members" 142468350Seric 142568350Seric 142668350Seric /* 142768350Seric ** NI_MAP_OPEN -- open NetInfo Aliases 142868350Seric */ 142968350Seric 143068350Seric bool 143168350Seric ni_map_open(map, mode) 143268350Seric MAP *map; 143368350Seric int mode; 143468350Seric { 143568350Seric char *p; 143668350Seric 143768350Seric if (tTd(38, 20)) 143868350Seric printf("ni_map_open: %s\n", map->map_file); 143968350Seric 144068350Seric if (*map->map_file == '\0') 144168350Seric map->map_file = NETINFO_DEFAULT_DIR; 144268350Seric 144368350Seric if (map->map_valcolnm == NULL) 144468350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 144568350Seric 144668350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 144768350Seric map->map_coldelim = ','; 144868350Seric 144968350Seric return TRUE; 145068350Seric } 145168350Seric 145268350Seric 145368350Seric /* 145468350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 145568350Seric */ 145668350Seric 145768350Seric char * 145868350Seric ni_map_lookup(map, name, av, statp) 145968350Seric MAP *map; 146068350Seric char *name; 146168350Seric char **av; 146268350Seric int *statp; 146368350Seric { 146468350Seric char *res; 146568350Seric char *propval; 146668350Seric extern char *ni_propval(); 146768350Seric 146868350Seric if (tTd(38, 20)) 146968350Seric printf("ni_map_lookup(%s, %s)\n", 147068350Seric map->map_mname, name); 147168350Seric 147268350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 147368350Seric map->map_valcolnm, map->map_coldelim); 147468350Seric 147568350Seric if (propval == NULL) 147668350Seric return NULL; 147768350Seric 147868350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 147968350Seric res = map_rewrite(map, name, strlen(name), NULL); 148068350Seric else 148168350Seric res = map_rewrite(map, propval, strlen(propval), av); 148268350Seric free(propval); 148368350Seric return res; 148468350Seric } 148568350Seric 148668350Seric #endif 148768350Seric /* 148868350Seric ** TEXT (unindexed text file) Modules 148968350Seric ** 149068350Seric ** This code donated by Sun Microsystems. 149168350Seric */ 149268350Seric 149368350Seric 149468350Seric /* 149568350Seric ** TEXT_MAP_OPEN -- open text table 149668350Seric */ 149768350Seric 149868350Seric bool 149968350Seric text_map_open(map, mode) 150068350Seric MAP *map; 150168350Seric int mode; 150268350Seric { 150368350Seric struct stat sbuf; 150468350Seric 150568350Seric if (tTd(38, 2)) 150668350Seric printf("text_map_open(%s, %s, %d)\n", 150768350Seric map->map_mname, map->map_file, mode); 150868350Seric 150968350Seric if (mode != O_RDONLY) 151068350Seric { 151168350Seric errno = ENODEV; 151268350Seric return FALSE; 151368350Seric } 151468350Seric 151568350Seric if (*map->map_file == '\0') 151668350Seric { 151768350Seric if (tTd(38, 2)) 151868350Seric printf("text_map_open: file name required\n"); 151968350Seric return FALSE; 152068350Seric } 152168350Seric 152268350Seric if (map->map_file[0] != '/') 152368350Seric { 152468350Seric if (tTd(38, 2)) 152568350Seric printf("text_map_open(%s): file name must be fully qualified\n", 152668350Seric map->map_file); 152768350Seric return FALSE; 152868350Seric } 152968350Seric /* check to see if this map actually accessable */ 153068350Seric if (access(map->map_file, R_OK) <0) 153168350Seric return FALSE; 153268350Seric 153368350Seric /* check to see if this map actually exist */ 153468350Seric if (stat(map->map_file, &sbuf) <0) 153568350Seric { 153668350Seric if (tTd(38, 2)) 153768350Seric printf("text_map_open(%s): can not stat %s\n", 153868350Seric map->map_file, map->map_file); 153968350Seric return FALSE; 154068350Seric } 154168350Seric 154268350Seric if (!S_ISREG(sbuf.st_mode)) 154368350Seric { 154468350Seric if (tTd(38, 2)) 154568350Seric printf("text_map_open(%s): %s is not a file\n", 154668350Seric map->map_file, map->map_file); 154768350Seric return FALSE; 154868350Seric } 154968350Seric 155068350Seric if (map->map_keycolnm == NULL) 155168350Seric map->map_keycolno = 0; 155268350Seric else 155368350Seric { 155468350Seric if (!isdigit(*map->map_keycolnm)) 155568350Seric { 155668350Seric if (tTd(38, 2)) 155768350Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 155868350Seric map->map_file, map->map_keycolnm); 155968350Seric return FALSE; 156068350Seric } 156168350Seric map->map_keycolno = atoi(map->map_keycolnm); 156268350Seric } 156368350Seric 156468350Seric if (map->map_valcolnm == NULL) 156568350Seric map->map_valcolno = 0; 156668350Seric else 156768350Seric { 156868350Seric if (!isdigit(*map->map_valcolnm)) 156968350Seric { 157068350Seric if (tTd(38, 2)) 157168350Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 157268350Seric map->map_file, map->map_valcolnm); 157368350Seric return FALSE; 157468350Seric } 157568350Seric map->map_valcolno = atoi(map->map_valcolnm); 157668350Seric } 157768350Seric 157868350Seric if (map->map_coldelim == '\0') 157968350Seric map->map_coldelim = ':'; 158068350Seric 158168350Seric if (tTd(38, 2)) 158268350Seric { 158368350Seric printf("text_map_open(%s): delimiter = %c\n", 158468350Seric map->map_file, map->map_coldelim); 158568350Seric } 158668350Seric 158768350Seric return TRUE; 158868350Seric } 158968350Seric 159068350Seric 159168350Seric /* 159268350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 159368350Seric */ 159468350Seric 159568350Seric char * 159668350Seric text_map_lookup(map, name, av, statp) 159768350Seric MAP *map; 159868350Seric char *name; 159968350Seric char **av; 160068350Seric int *statp; 160168350Seric { 160268350Seric char *vp; 160368350Seric auto int vsize; 160468350Seric int buflen; 160568350Seric char search_key[MAXNAME + 1]; 160668350Seric char linebuf[MAXLINE]; 160768350Seric FILE *f; 160868350Seric char buf[MAXNAME+1]; 160968350Seric char delim; 161068350Seric int key_idx; 161168350Seric bool found_it; 161268350Seric extern char *get_column(); 161368350Seric 161468350Seric 161568350Seric found_it = FALSE; 161668350Seric if (tTd(38, 20)) 161768350Seric printf("text_map_lookup(%s)\n", name); 161868350Seric 161968350Seric buflen = strlen(name); 162068350Seric if (buflen > sizeof search_key - 1) 162168350Seric buflen = sizeof search_key - 1; 162268350Seric bcopy(name, search_key, buflen + 1); 162368350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 162468350Seric makelower(search_key); 162568350Seric 162668350Seric f = fopen(map->map_file, "r"); 162768350Seric if (f == NULL) 162868350Seric { 162968350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 163068350Seric *statp = EX_UNAVAILABLE; 163168350Seric return NULL; 163268350Seric } 163368350Seric key_idx = map->map_keycolno; 163468350Seric delim = map->map_coldelim; 163568350Seric while (fgets(linebuf, MAXLINE, f)) 163668350Seric { 163768350Seric char *lf; 163868350Seric if (linebuf[0] == '#') 163968350Seric continue; /* skip comment line */ 164068350Seric if (lf = strchr(linebuf, '\n')) 164168350Seric *lf = '\0'; 164268350Seric if (!strcasecmp(search_key, 164368350Seric get_column(linebuf, key_idx, delim, buf))) 164468350Seric { 164568350Seric found_it = TRUE; 164668350Seric break; 164768350Seric } 164868350Seric } 164968350Seric fclose(f); 165068350Seric if (!found_it) 165168350Seric { 165268350Seric #ifdef MAP_EXIT_STAT 165368350Seric *statp = EX_NOTFOUND; 165468350Seric #endif 165568350Seric return(NULL); 165668350Seric } 165768350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 165868350Seric vsize = strlen(vp); 165968350Seric #ifdef MAP_EXIT_STAT 166068350Seric *statp = EX_OK; 166168350Seric #endif 166268350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 166368350Seric return map_rewrite(map, name, strlen(name), NULL); 166468350Seric else 166568350Seric return map_rewrite(map, vp, vsize, av); 166668350Seric } 166768350Seric /* 166860089Seric ** STAB (Symbol Table) Modules 166960089Seric */ 167060089Seric 167160089Seric 167260089Seric /* 167360207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 167460089Seric */ 167560089Seric 167660089Seric char * 167761707Seric stab_map_lookup(map, name, av, pstat) 167860089Seric register MAP *map; 167960089Seric char *name; 168061707Seric char **av; 168161707Seric int *pstat; 168260089Seric { 168360089Seric register STAB *s; 168460089Seric 168560537Seric if (tTd(38, 20)) 168668350Seric printf("stab_lookup(%s, %s)\n", 168768350Seric map->map_mname, name); 168860089Seric 168960089Seric s = stab(name, ST_ALIAS, ST_FIND); 169060089Seric if (s != NULL) 169160089Seric return (s->s_alias); 169260089Seric return (NULL); 169360089Seric } 169460089Seric 169560089Seric 169660089Seric /* 169760207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 169860089Seric */ 169960089Seric 170060089Seric void 170160089Seric stab_map_store(map, lhs, rhs) 170260089Seric register MAP *map; 170360089Seric char *lhs; 170460089Seric char *rhs; 170560089Seric { 170660089Seric register STAB *s; 170760089Seric 170860089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 170960089Seric s->s_alias = newstr(rhs); 171060089Seric } 171160089Seric 171260089Seric 171360089Seric /* 171460207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 171560207Seric ** 171660207Seric ** This is a wierd case -- it is only intended as a fallback for 171760207Seric ** aliases. For this reason, opens for write (only during a 171860207Seric ** "newaliases") always fails, and opens for read open the 171960207Seric ** actual underlying text file instead of the database. 172060089Seric */ 172160089Seric 172260089Seric bool 172360089Seric stab_map_open(map, mode) 172460089Seric register MAP *map; 172560089Seric int mode; 172660089Seric { 172763835Seric FILE *af; 172864284Seric struct stat st; 172963835Seric 173060537Seric if (tTd(38, 2)) 173168350Seric printf("stab_map_open(%s, %s)\n", 173268350Seric map->map_mname, map->map_file); 173360089Seric 173460089Seric if (mode != O_RDONLY) 173560207Seric { 173660207Seric errno = ENODEV; 173760089Seric return FALSE; 173860207Seric } 173960089Seric 174063835Seric af = fopen(map->map_file, "r"); 174163835Seric if (af == NULL) 174263835Seric return FALSE; 174368350Seric readaliases(map, af, FALSE, FALSE); 174464284Seric 174564284Seric if (fstat(fileno(af), &st) >= 0) 174664284Seric map->map_mtime = st.st_mtime; 174763835Seric fclose(af); 174863835Seric 174960089Seric return TRUE; 175060089Seric } 175160089Seric /* 175260089Seric ** Implicit Modules 175356822Seric ** 175460089Seric ** Tries several types. For back compatibility of aliases. 175556822Seric */ 175656822Seric 175760089Seric 175860089Seric /* 175960207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 176060089Seric */ 176160089Seric 176260089Seric char * 176360089Seric impl_map_lookup(map, name, av, pstat) 176460089Seric MAP *map; 176560089Seric char *name; 176656822Seric char **av; 176760089Seric int *pstat; 176856822Seric { 176960537Seric if (tTd(38, 20)) 177068350Seric printf("impl_map_lookup(%s, %s)\n", 177168350Seric map->map_mname, name); 177256822Seric 177360089Seric #ifdef NEWDB 177460207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 177560089Seric return db_map_lookup(map, name, av, pstat); 177660089Seric #endif 177760089Seric #ifdef NDBM 177860207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 177960089Seric return ndbm_map_lookup(map, name, av, pstat); 178060089Seric #endif 178160089Seric return stab_map_lookup(map, name, av, pstat); 178260089Seric } 178360089Seric 178460089Seric /* 178560207Seric ** IMPL_MAP_STORE -- store in open databases 178660089Seric */ 178760089Seric 178860089Seric void 178960089Seric impl_map_store(map, lhs, rhs) 179060089Seric MAP *map; 179160089Seric char *lhs; 179260089Seric char *rhs; 179360089Seric { 179460089Seric #ifdef NEWDB 179560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 179660089Seric db_map_store(map, lhs, rhs); 179760089Seric #endif 179860089Seric #ifdef NDBM 179960207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 180060089Seric ndbm_map_store(map, lhs, rhs); 180160089Seric #endif 180260089Seric stab_map_store(map, lhs, rhs); 180360089Seric } 180460089Seric 180560089Seric /* 180660089Seric ** IMPL_MAP_OPEN -- implicit database open 180760089Seric */ 180860089Seric 180960089Seric bool 181060089Seric impl_map_open(map, mode) 181160089Seric MAP *map; 181260089Seric int mode; 181360089Seric { 181460089Seric struct stat stb; 181560089Seric 181660537Seric if (tTd(38, 2)) 181768350Seric printf("impl_map_open(%s, %s, %d)\n", 181868350Seric map->map_mname, map->map_file, mode); 181960089Seric 182060089Seric if (stat(map->map_file, &stb) < 0) 182156822Seric { 182260089Seric /* no alias file at all */ 182364718Seric if (tTd(38, 3)) 182464718Seric printf("no map file\n"); 182560089Seric return FALSE; 182656822Seric } 182756822Seric 182860089Seric #ifdef NEWDB 182960207Seric map->map_mflags |= MF_IMPL_HASH; 183060089Seric if (hash_map_open(map, mode)) 183156822Seric { 183264250Seric #if defined(NDBM) && defined(NIS) 183360561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 183460207Seric #endif 183560207Seric return TRUE; 183660089Seric } 183760207Seric else 183860207Seric map->map_mflags &= ~MF_IMPL_HASH; 183960089Seric #endif 184060089Seric #ifdef NDBM 184160207Seric map->map_mflags |= MF_IMPL_NDBM; 184260089Seric if (ndbm_map_open(map, mode)) 184360089Seric { 184460089Seric return TRUE; 184560089Seric } 184660207Seric else 184760207Seric map->map_mflags &= ~MF_IMPL_NDBM; 184860089Seric #endif 184956822Seric 185064650Seric #if defined(NEWDB) || defined(NDBM) 185160089Seric if (Verbose) 185260089Seric message("WARNING: cannot open alias database %s", map->map_file); 185364964Seric #else 185464964Seric if (mode != O_RDONLY) 185564964Seric usrerr("Cannot rebuild aliases: no database format defined"); 185660207Seric #endif 185760089Seric 185860207Seric return stab_map_open(map, mode); 185956822Seric } 186060089Seric 186160207Seric 186260089Seric /* 186360207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 186460089Seric */ 186560089Seric 186660089Seric void 186760207Seric impl_map_close(map) 186860089Seric MAP *map; 186960089Seric { 187068350Seric if (tTd(38, 20)) 187168350Seric printf("impl_map_close(%s, %s, %x)\n", 187268350Seric map->map_mname, map->map_file, map->map_mflags); 187360089Seric #ifdef NEWDB 187460207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 187560089Seric { 187660207Seric db_map_close(map); 187760207Seric map->map_mflags &= ~MF_IMPL_HASH; 187860089Seric } 187960089Seric #endif 188060089Seric 188160089Seric #ifdef NDBM 188260207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 188360089Seric { 188460207Seric ndbm_map_close(map); 188560207Seric map->map_mflags &= ~MF_IMPL_NDBM; 188660089Seric } 188760089Seric #endif 188860089Seric } 188960207Seric /* 189068350Seric ** User map class. 189168350Seric ** 189268350Seric ** Provides access to the system password file. 189368350Seric */ 189468350Seric 189568350Seric /* 189668350Seric ** USER_MAP_OPEN -- open user map 189768350Seric ** 189868350Seric ** Really just binds field names to field numbers. 189968350Seric */ 190068350Seric 190168350Seric bool 190268350Seric user_map_open(map, mode) 190368350Seric MAP *map; 190468350Seric int mode; 190568350Seric { 190668350Seric if (tTd(38, 2)) 190768350Seric printf("user_map_open(%s)\n", map->map_mname); 190868350Seric 190968350Seric if (mode != O_RDONLY) 191068350Seric { 191168350Seric /* issue a pseudo-error message */ 191268350Seric #ifdef ENOSYS 191368350Seric errno = ENOSYS; 191468350Seric #else 191568350Seric # ifdef EFTYPE 191668350Seric errno = EFTYPE; 191768350Seric # else 191868350Seric errno = ENXIO; 191968350Seric # endif 192068350Seric #endif 192168350Seric return FALSE; 192268350Seric } 192368350Seric if (map->map_valcolnm == NULL) 192468350Seric /* nothing */ ; 192568350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 192668350Seric map->map_valcolno = 1; 192768350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 192868350Seric map->map_valcolno = 2; 192968350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 193068350Seric map->map_valcolno = 3; 193168350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 193268350Seric map->map_valcolno = 4; 193368350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 193468350Seric map->map_valcolno = 5; 193568350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 193668350Seric map->map_valcolno = 6; 193768350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 193868350Seric map->map_valcolno = 7; 193968350Seric else 194068350Seric { 194168350Seric syserr("User map %s: unknown column name %s", 194268350Seric map->map_mname, map->map_valcolnm); 194368350Seric return FALSE; 194468350Seric } 194568350Seric return TRUE; 194668350Seric } 194768350Seric 194868350Seric 194968350Seric /* 195068350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 195168350Seric */ 195268350Seric 195368350Seric #include <pwd.h> 195468350Seric 195568350Seric char * 195668350Seric user_map_lookup(map, key, av, statp) 195768350Seric MAP *map; 195868350Seric char *key; 195968350Seric char **av; 196068350Seric int *statp; 196168350Seric { 196268350Seric struct passwd *pw; 196368350Seric 196468350Seric if (tTd(38, 20)) 196568350Seric printf("user_map_lookup(%s, %s)\n", 196668350Seric map->map_mname, key); 196768350Seric 196868350Seric pw = getpwnam(key); 196968350Seric if (pw == NULL) 197068350Seric return NULL; 197168350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 197268350Seric return map_rewrite(map, key, strlen(key), NULL); 197368350Seric else 197468350Seric { 197568433Seric char *rwval = NULL; 197668350Seric char buf[30]; 197768350Seric 197868350Seric switch (map->map_valcolno) 197968350Seric { 198068350Seric case 0: 198168350Seric case 1: 198268350Seric rwval = pw->pw_name; 198368350Seric break; 198468350Seric 198568350Seric case 2: 198668350Seric rwval = pw->pw_passwd; 198768350Seric break; 198868350Seric 198968350Seric case 3: 199068350Seric sprintf(buf, "%d", pw->pw_uid); 199168350Seric rwval = buf; 199268350Seric break; 199368350Seric 199468350Seric case 4: 199568350Seric sprintf(buf, "%d", pw->pw_gid); 199668350Seric rwval = buf; 199768350Seric break; 199868350Seric 199968350Seric case 5: 200068350Seric rwval = pw->pw_gecos; 200168350Seric break; 200268350Seric 200368350Seric case 6: 200468350Seric rwval = pw->pw_dir; 200568350Seric break; 200668350Seric 200768350Seric case 7: 200868350Seric rwval = pw->pw_shell; 200968350Seric break; 201068350Seric } 201168350Seric return map_rewrite(map, rwval, strlen(rwval), av); 201268350Seric } 201368350Seric } 201468350Seric /* 201568350Seric ** BESTMX -- find the best MX for a name 201668350Seric ** 201768350Seric ** This is really a hack, but I don't see any obvious way 201868350Seric ** to generalize it at the moment. 201968350Seric */ 202068350Seric 202168350Seric #if NAMED_BIND 202268350Seric 202368350Seric char * 202468350Seric bestmx_map_lookup(map, name, av, statp) 202568350Seric MAP *map; 202668350Seric char *name; 202768350Seric char **av; 202868350Seric int *statp; 202968350Seric { 203068350Seric int nmx; 203168350Seric auto int rcode; 203268350Seric char *mxhosts[MAXMXHOSTS + 1]; 203368350Seric 203468350Seric nmx = getmxrr(name, mxhosts, FALSE, &rcode); 203568350Seric if (nmx <= 0) 203668350Seric return NULL; 203768350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 203868350Seric return map_rewrite(map, name, strlen(name), NULL); 203968350Seric else 204068350Seric return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 204168350Seric } 204268350Seric 204368350Seric #endif 204468350Seric /* 204568350Seric ** Sequenced map type. 204668350Seric ** 204768350Seric ** Tries each map in order until something matches, much like 204868350Seric ** implicit. Stores go to the first map in the list that can 204968350Seric ** support storing. 205068350Seric ** 205168350Seric ** This is slightly unusual in that there are two interfaces. 205268350Seric ** The "sequence" interface lets you stack maps arbitrarily. 205368350Seric ** The "switch" interface builds a sequence map by looking 205468350Seric ** at a system-dependent configuration file such as 205568350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 205668350Seric ** 205768350Seric ** We don't need an explicit open, since all maps are 205868350Seric ** opened during startup, including underlying maps. 205968350Seric */ 206068350Seric 206168350Seric /* 206268350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 206368350Seric */ 206468350Seric 206568350Seric bool 206668350Seric seq_map_parse(map, ap) 206768350Seric MAP *map; 206868350Seric char *ap; 206968350Seric { 207068350Seric int maxmap; 207168350Seric 207268350Seric if (tTd(38, 2)) 207368350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 207468350Seric maxmap = 0; 207568350Seric while (*ap != '\0') 207668350Seric { 207768350Seric register char *p; 207868350Seric STAB *s; 207968350Seric 208068350Seric /* find beginning of map name */ 208168350Seric while (isascii(*ap) && isspace(*ap)) 208268350Seric ap++; 208368350Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 208468350Seric continue; 208568350Seric if (*p != '\0') 208668350Seric *p++ = '\0'; 208768350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 208868350Seric p++; 208968350Seric if (*ap == '\0') 209068350Seric { 209168350Seric ap = p; 209268350Seric continue; 209368350Seric } 209468350Seric s = stab(ap, ST_MAP, ST_FIND); 209568350Seric if (s == NULL) 209668350Seric { 209768350Seric syserr("Sequence map %s: unknown member map %s", 209868350Seric map->map_mname, ap); 209968350Seric } 210068350Seric else if (maxmap == MAXMAPSTACK) 210168350Seric { 210268350Seric syserr("Sequence map %s: too many member maps (%d max)", 210368350Seric map->map_mname, MAXMAPSTACK); 210468350Seric maxmap++; 210568350Seric } 210668350Seric else if (maxmap < MAXMAPSTACK) 210768350Seric { 210868350Seric map->map_stack[maxmap++] = &s->s_map; 210968350Seric } 211068350Seric ap = p; 211168350Seric } 211268350Seric return TRUE; 211368350Seric } 211468350Seric 211568350Seric 211668350Seric /* 211768350Seric ** SWITCH_MAP_OPEN -- open a switched map 211868350Seric ** 211968350Seric ** This looks at the system-dependent configuration and builds 212068350Seric ** a sequence map that does the same thing. 212168350Seric ** 212268350Seric ** Every system must define a switch_map_find routine in conf.c 212368350Seric ** that will return the list of service types associated with a 212468350Seric ** given service class. 212568350Seric */ 212668350Seric 212768350Seric bool 212868350Seric switch_map_open(map, mode) 212968350Seric MAP *map; 213068350Seric int mode; 213168350Seric { 213268350Seric int mapno; 213368350Seric int nmaps; 213468350Seric char *maptype[MAXMAPSTACK]; 213568350Seric 213668350Seric if (tTd(38, 2)) 213768350Seric printf("switch_map_open(%s, %s, %d)\n", 213868350Seric map->map_mname, map->map_file, mode); 213968350Seric 214068350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 214168350Seric if (tTd(38, 19)) 214268350Seric { 214368350Seric printf("\tswitch_map_find => %d\n", nmaps); 214468350Seric for (mapno = 0; mapno < nmaps; mapno++) 214568350Seric printf("\t\t%s\n", maptype[mapno]); 214668350Seric } 214768350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 214868350Seric return FALSE; 214968350Seric 215068350Seric for (mapno = 0; mapno < nmaps; mapno++) 215168350Seric { 215268350Seric register STAB *s; 215368350Seric char nbuf[MAXNAME + 1]; 215468350Seric 215568350Seric if (maptype[mapno] == NULL) 215668350Seric continue; 215768350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 215868350Seric s = stab(nbuf, ST_MAP, ST_FIND); 215968350Seric if (s == NULL) 216068350Seric { 216168350Seric syserr("Switch map %s: unknown member map %s", 216268350Seric map->map_mname, nbuf); 216368350Seric } 216468350Seric else 216568350Seric { 216668350Seric map->map_stack[mapno] = &s->s_map; 216768350Seric if (tTd(38, 4)) 216868350Seric printf("\tmap_stack[%d] = %s:%s\n", 216968350Seric mapno, s->s_map.map_class->map_cname, 217068350Seric nbuf); 217168350Seric } 217268350Seric } 217368350Seric return TRUE; 217468350Seric } 217568350Seric 217668350Seric 217768350Seric /* 217868350Seric ** SEQ_MAP_CLOSE -- close all underlying maps 217968350Seric */ 218068350Seric 218168350Seric seq_map_close(map) 218268350Seric MAP *map; 218368350Seric { 218468350Seric int mapno; 218568350Seric 218668350Seric if (tTd(38, 20)) 218768350Seric printf("seq_map_close(%s)\n", map->map_mname); 218868350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 218968350Seric { 219068350Seric MAP *mm = map->map_stack[mapno]; 219168350Seric 219268350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 219368350Seric continue; 219468350Seric mm->map_class->map_close(mm); 219568350Seric } 219668350Seric } 219768350Seric 219868350Seric 219968350Seric /* 220068350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 220168350Seric */ 220268350Seric 220368350Seric char * 220468350Seric seq_map_lookup(map, key, args, pstat) 220568350Seric MAP *map; 220668350Seric char *key; 220768350Seric char **args; 220868350Seric int *pstat; 220968350Seric { 221068350Seric int mapno; 221168350Seric int mapbit = 0x01; 221268350Seric 221368350Seric if (tTd(38, 20)) 221468350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 221568350Seric 221668350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 221768350Seric { 221868350Seric MAP *mm = map->map_stack[mapno]; 221968350Seric int stat = 0; 222068350Seric char *rv; 222168350Seric 222268350Seric if (mm == NULL) 222368350Seric continue; 222468350Seric if (!bitset(MF_OPEN, mm->map_mflags)) 222568350Seric { 222668350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 222768350Seric { 222868350Seric *pstat = EX_UNAVAILABLE; 222968350Seric return NULL; 223068350Seric } 223168350Seric continue; 223268350Seric } 223368350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 223468350Seric if (rv != NULL) 223568350Seric return rv; 223668350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 223768350Seric return NULL; 223868350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 223968350Seric { 224068350Seric *pstat = stat; 224168350Seric return NULL; 224268350Seric } 224368350Seric } 224468350Seric return NULL; 224568350Seric } 224668350Seric 224768350Seric 224868350Seric /* 224968350Seric ** SEQ_MAP_STORE -- sequenced map store 225068350Seric */ 225168350Seric 225268350Seric void 225368350Seric seq_map_store(map, key, val) 225468350Seric MAP *map; 225568350Seric char *key; 225668350Seric char *val; 225768350Seric { 225868350Seric int mapno; 225968350Seric 226068350Seric if (tTd(38, 12)) 226168350Seric printf("seq_map_store(%s, %s, %s)\n", 226268350Seric map->map_mname, key, val); 226368350Seric 226468350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 226568350Seric { 226668350Seric MAP *mm = map->map_stack[mapno]; 226768350Seric 226868350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 226968350Seric continue; 227068350Seric 227168350Seric mm->map_class->map_store(mm, key, val); 227268350Seric return; 227368350Seric } 227468350Seric syserr("seq_map_store(%s, %s, %s): no writable map", 227568350Seric map->map_mname, key, val); 227668350Seric } 227768350Seric /* 227860207Seric ** NULL stubs 227960089Seric */ 228060089Seric 228160207Seric bool 228260207Seric null_map_open(map, mode) 228360089Seric MAP *map; 228460207Seric int mode; 228560089Seric { 228660207Seric return TRUE; 228760089Seric } 228860089Seric 228960207Seric void 229060207Seric null_map_close(map) 229160207Seric MAP *map; 229260089Seric { 229360207Seric return; 229460207Seric } 229560089Seric 229660207Seric void 229760207Seric null_map_store(map, key, val) 229860207Seric MAP *map; 229960207Seric char *key; 230060207Seric char *val; 230160089Seric { 230260207Seric return; 230360089Seric } 230468350Seric 230568350Seric 230668350Seric /* 230768350Seric ** BOGUS stubs 230868350Seric */ 230968350Seric 231068350Seric char * 231168350Seric bogus_map_lookup(map, key, args, pstat) 231268350Seric MAP *map; 231368350Seric char *key; 231468350Seric char **args; 231568350Seric int *pstat; 231668350Seric { 231768350Seric *pstat = EX_TEMPFAIL; 231868350Seric return NULL; 231968350Seric } 232068350Seric 232168350Seric MAPCLASS BogusMapClass = 232268350Seric { 232368350Seric "bogus-map", NULL, 0, 232468350Seric NULL, bogus_map_lookup, null_map_store, 232568350Seric null_map_open, null_map_close, 232668350Seric }; 2327