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*68350Seric static char sccsid[] = "@(#)map.c 8.42 (Berkeley) 02/17/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; 121*68350Seric 122*68350Seric case 'k': 123*68350Seric while (isascii(*++p) && isspace(*p)) 124*68350Seric continue; 125*68350Seric map->map_keycolnm = p; 126*68350Seric break; 127*68350Seric 128*68350Seric case 'v': 129*68350Seric while (isascii(*++p) && isspace(*p)) 130*68350Seric continue; 131*68350Seric map->map_valcolnm = p; 132*68350Seric break; 133*68350Seric 134*68350Seric case 'z': 135*68350Seric if (*++p != '\\') 136*68350Seric map->map_coldelim = *p; 137*68350Seric else 138*68350Seric { 139*68350Seric switch (*++p) 140*68350Seric { 141*68350Seric case 'n': 142*68350Seric map->map_coldelim = '\n'; 143*68350Seric break; 144*68350Seric 145*68350Seric case 't': 146*68350Seric map->map_coldelim = '\t'; 147*68350Seric break; 148*68350Seric 149*68350Seric default: 150*68350Seric map->map_coldelim = '\\'; 151*68350Seric } 152*68350Seric } 153*68350Seric 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); 162*68350Seric if (map->map_keycolnm != NULL) 163*68350Seric map->map_keycolnm = newstr(map->map_keycolnm); 164*68350Seric if (map->map_valcolnm != NULL) 165*68350Seric 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 182*68350Seric if (map->map_file == NULL && 183*68350Seric !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)) 371*68350Seric printf("map_init(%s:%s, %s, %d)\n", 37264690Seric map->map_class->map_cname == NULL ? "NULL" : 37364690Seric map->map_class->map_cname, 374*68350Seric 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)) 402*68350Seric printf("\t%s:%s %s: valid\n", 40364690Seric map->map_class->map_cname == NULL ? "NULL" : 40464690Seric map->map_class->map_cname, 405*68350Seric map->map_mname == NULL ? "NULL" : 406*68350Seric map->map_mname, 40764690Seric map->map_file == NULL ? "NULL" : 40864690Seric map->map_file); 40960537Seric map->map_mflags |= MF_OPEN; 41060537Seric } 411*68350Seric else 412*68350Seric { 413*68350Seric if (tTd(38, 4)) 414*68350Seric printf("\t%s:%s %s: invalid: %s\n", 415*68350Seric map->map_class->map_cname == NULL ? "NULL" : 416*68350Seric map->map_class->map_cname, 417*68350Seric map->map_mname == NULL ? "NULL" : 418*68350Seric map->map_mname, 419*68350Seric map->map_file == NULL ? "NULL" : 420*68350Seric map->map_file, 421*68350Seric errstring(errno)); 422*68350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 423*68350Seric { 424*68350Seric extern MAPCLASS BogusMapClass; 425*68350Seric 426*68350Seric map->map_class = &BogusMapClass; 427*68350Seric map->map_mflags |= MF_OPEN; 428*68350Seric } 429*68350Seric } 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)) 451*68350Seric printf("ndbm_map_open(%s, %s, %d)\n", 452*68350Seric 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)) 506*68350Seric printf("ndbm_map_lookup(%s, %s)\n", 507*68350Seric 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)) 562*68350Seric printf("ndbm_map_store(%s, %s, %s)\n", 563*68350Seric 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)) 597*68350Seric printf("ndbm_map_close(%s, %s, %x)\n", 598*68350Seric 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)) 657*68350Seric printf("bt_map_open(%s, %s, %d)\n", 658*68350Seric 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 } 690*68350Seric #if !OLD_NEWDB 69164373Seric fd = db->fd(db); 692*68350Seric # if HASFLOCK 693*68350Seric # 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 } 699*68350Seric # 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; 704*68350Seric # 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)) 744*68350Seric printf("hash_map_open(%s, %s, %d)\n", 745*68350Seric 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 } 777*68350Seric #if !OLD_NEWDB 77864373Seric fd = db->fd(db); 779*68350Seric # if HASFLOCK 780*68350Seric # 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 } 786*68350Seric # 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; 791*68350Seric # 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)) 833*68350Seric printf("db_map_lookup(%s, %s)\n", 834*68350Seric 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)) 897*68350Seric printf("db_map_store(%s, %s, %s)\n", 898*68350Seric 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)) 934*68350Seric printf("db_map_close(%s, %s, %x)\n", 935*68350Seric 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)) 974*68350Seric printf("nis_map_open(%s, %s)\n", 975*68350Seric 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)) 1009*68350Seric 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) 1022*68350Seric { 1023*68350Seric if (!bitset(MF_ALIAS, map->map_mflags) || 1024*68350Seric aliaswait(map, NULL, TRUE)) 1025*68350Seric return TRUE; 1026*68350Seric } 102760215Seric 102860215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 1029*68350Seric 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)) 1054*68350Seric printf("nis_map_lookup(%s, %s)\n", 1055*68350Seric 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 1091*68350Seric #endif 1092*68350Seric /* 1093*68350Seric ** NISPLUS Modules 1094*68350Seric ** 1095*68350Seric ** This code donated by Sun Microsystems. 1096*68350Seric */ 109767848Seric 1098*68350Seric #ifdef NISPLUS 1099*68350Seric 1100*68350Seric #undef NIS /* symbol conflict in nis.h */ 1101*68350Seric #include <rpcsvc/nis.h> 1102*68350Seric #include <rpcsvc/nislib.h> 1103*68350Seric 1104*68350Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 1105*68350Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 1106*68350Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 1107*68350Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 1108*68350Seric 110967848Seric /* 1110*68350Seric ** NISPLUS_MAP_OPEN -- open nisplus table 111167848Seric */ 111267848Seric 1113*68350Seric bool 1114*68350Seric nisplus_map_open(map, mode) 111567848Seric MAP *map; 1116*68350Seric int mode; 111767848Seric { 1118*68350Seric register char *p; 1119*68350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 1120*68350Seric nis_result *res = NULL; 1121*68350Seric u_int objs_len; 1122*68350Seric nis_object *obj_ptr; 1123*68350Seric int retry_cnt, max_col, i; 1124*68350Seric 1125*68350Seric if (tTd(38, 2)) 1126*68350Seric printf("nisplus_map_open(%s, %s, %d)\n", 1127*68350Seric map->map_mname, map->map_file, mode); 1128*68350Seric 1129*68350Seric if (mode != O_RDONLY) 1130*68350Seric { 1131*68350Seric errno = ENODEV; 1132*68350Seric return FALSE; 1133*68350Seric } 1134*68350Seric 1135*68350Seric if (*map->map_file == '\0') 1136*68350Seric map->map_file = "mail_aliases.org_dir"; 1137*68350Seric 1138*68350Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 1139*68350Seric { 1140*68350Seric /* set default NISPLUS Domain to $m */ 1141*68350Seric extern char *nisplus_default_domain(); 1142*68350Seric 1143*68350Seric map->map_domain = newstr(nisplus_default_domain()); 1144*68350Seric if (tTd(38, 2)) 1145*68350Seric printf("nisplus_map_open(%s): using domain %s\n", 1146*68350Seric map->map_file, map->map_domain); 1147*68350Seric } 1148*68350Seric if (!PARTIAL_NAME(map->map_file)) 1149*68350Seric map->map_domain = newstr(""); 1150*68350Seric 1151*68350Seric /* check to see if this map actually exists */ 1152*68350Seric if (PARTIAL_NAME(map->map_file)) 1153*68350Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 1154*68350Seric else 1155*68350Seric strcpy(qbuf, map->map_file); 1156*68350Seric 1157*68350Seric retry_cnt = 0; 1158*68350Seric while (res == NULL || res->status != NIS_SUCCESS) 1159*68350Seric { 1160*68350Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 1161*68350Seric switch (res->status) 1162*68350Seric { 1163*68350Seric case NIS_SUCCESS: 1164*68350Seric case NIS_TRYAGAIN: 1165*68350Seric case NIS_RPCERROR: 1166*68350Seric case NIS_NAMEUNREACHABLE: 1167*68350Seric break; 1168*68350Seric 1169*68350Seric default: /* all other nisplus errors */ 1170*68350Seric #if 0 1171*68350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 1172*68350Seric syserr("421 Cannot find table %s.%s: %s", 1173*68350Seric map->map_file, map->map_domain, 1174*68350Seric nis_sperrno(res->status)); 1175*68350Seric #endif 1176*68350Seric errno = EBADR; 1177*68350Seric return FALSE; 1178*68350Seric } 1179*68350Seric sleep(2); /* try not to overwhelm hosed server */ 1180*68350Seric if (retry_cnt++ > 4) 1181*68350Seric { 1182*68350Seric errno = EBADR; 1183*68350Seric return FALSE; 1184*68350Seric } 1185*68350Seric } 1186*68350Seric 1187*68350Seric if (NIS_RES_NUMOBJ(res) != 1 || 1188*68350Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 1189*68350Seric { 1190*68350Seric if (tTd(38, 10)) 1191*68350Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 1192*68350Seric #if 0 1193*68350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 1194*68350Seric syserr("421 %s.%s: %s is not a table", 1195*68350Seric map->map_file, map->map_domain, 1196*68350Seric nis_sperrno(res->status)); 1197*68350Seric #endif 1198*68350Seric errno = EBADR; 1199*68350Seric return FALSE; 1200*68350Seric } 1201*68350Seric /* default key column is column 0 */ 1202*68350Seric if (map->map_keycolnm == NULL) 1203*68350Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 1204*68350Seric 1205*68350Seric max_col = COL_MAX(res); 1206*68350Seric 1207*68350Seric /* verify the key column exist */ 1208*68350Seric for (i=0; i< max_col; i++) 1209*68350Seric { 1210*68350Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 1211*68350Seric break; 1212*68350Seric } 1213*68350Seric if (i == max_col) 1214*68350Seric { 1215*68350Seric if (tTd(38, 2)) 1216*68350Seric printf("nisplus_map_open(%s): can not find key column %s\n", 1217*68350Seric map->map_file, map->map_keycolnm); 1218*68350Seric errno = EBADR; 1219*68350Seric return FALSE; 1220*68350Seric } 1221*68350Seric 1222*68350Seric /* default value column is the last column */ 1223*68350Seric if (map->map_valcolnm == NULL) 1224*68350Seric { 1225*68350Seric map->map_valcolno = max_col - 1; 1226*68350Seric return TRUE; 1227*68350Seric } 1228*68350Seric 1229*68350Seric for (i=0; i< max_col; i++) 1230*68350Seric { 1231*68350Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 1232*68350Seric { 1233*68350Seric map->map_valcolno = i; 1234*68350Seric return TRUE; 1235*68350Seric } 1236*68350Seric } 1237*68350Seric 1238*68350Seric if (tTd(38, 2)) 1239*68350Seric printf("nisplus_map_open(%s): can not find column %s\n", 1240*68350Seric map->map_file, map->map_keycolnm); 1241*68350Seric errno = EBADR; 1242*68350Seric return FALSE; 124367848Seric } 124467848Seric 124567848Seric 124667848Seric /* 1247*68350Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 124867848Seric */ 124967848Seric 1250*68350Seric char * 1251*68350Seric nisplus_map_lookup(map, name, av, statp) 125267848Seric MAP *map; 1253*68350Seric char *name; 1254*68350Seric char **av; 1255*68350Seric int *statp; 125667848Seric { 1257*68350Seric char *vp; 1258*68350Seric auto int vsize; 1259*68350Seric int buflen; 1260*68350Seric char search_key[MAXNAME + 1]; 1261*68350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 1262*68350Seric nis_result *result; 1263*68350Seric 1264*68350Seric if (tTd(38, 20)) 1265*68350Seric printf("nisplus_map_lookup(%s, %s)\n", 1266*68350Seric map->map_mname, name); 1267*68350Seric 1268*68350Seric if (!bitset(MF_OPEN, map->map_mflags)) 1269*68350Seric { 1270*68350Seric if (nisplus_map_open(map, O_RDONLY)) 1271*68350Seric map->map_mflags |= MF_OPEN; 1272*68350Seric else 1273*68350Seric { 1274*68350Seric *statp = EX_UNAVAILABLE; 1275*68350Seric return NULL; 1276*68350Seric } 1277*68350Seric } 1278*68350Seric 1279*68350Seric buflen = strlen(name); 1280*68350Seric if (buflen > sizeof search_key - 1) 1281*68350Seric buflen = sizeof search_key - 1; 1282*68350Seric bcopy(name, search_key, buflen + 1); 1283*68350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 1284*68350Seric makelower(search_key); 1285*68350Seric 1286*68350Seric /* construct the query */ 1287*68350Seric if (PARTIAL_NAME(map->map_file)) 1288*68350Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 1289*68350Seric search_key, map->map_file, map->map_domain); 1290*68350Seric else 1291*68350Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 1292*68350Seric search_key, map->map_file); 1293*68350Seric 1294*68350Seric if (tTd(38, 20)) 1295*68350Seric printf("qbuf=%s\n", qbuf); 1296*68350Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 1297*68350Seric if (result->status == NIS_SUCCESS) 1298*68350Seric { 1299*68350Seric int count; 1300*68350Seric char *str; 1301*68350Seric 1302*68350Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 1303*68350Seric { 1304*68350Seric if (LogLevel > 10) 1305*68350Seric syslog(LOG_WARNING, 1306*68350Seric "%s:Lookup error, expected 1 entry, got (%d)", 1307*68350Seric map->map_file, count); 1308*68350Seric 1309*68350Seric /* ignore second entry */ 1310*68350Seric if (tTd(38, 20)) 1311*68350Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 1312*68350Seric name, count); 1313*68350Seric } 1314*68350Seric 1315*68350Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 1316*68350Seric /* set the length of the result */ 1317*68350Seric if (vp == NULL) 1318*68350Seric vp = ""; 1319*68350Seric vsize = strlen(vp); 1320*68350Seric if (tTd(38, 20)) 1321*68350Seric printf("nisplus_map_lookup(%s), found %s\n", 1322*68350Seric name, vp); 1323*68350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 1324*68350Seric str = map_rewrite(map, name, strlen(name), NULL); 1325*68350Seric else 1326*68350Seric str = map_rewrite(map, vp, vsize, av); 1327*68350Seric nis_freeresult(result); 1328*68350Seric #ifdef MAP_EXIT_STAT 1329*68350Seric *statp = EX_OK; 1330*68350Seric #endif 1331*68350Seric return str; 1332*68350Seric } 1333*68350Seric else 1334*68350Seric { 1335*68350Seric #ifdef MAP_EXIT_STAT 1336*68350Seric if (result->status == NIS_NOTFOUND) 1337*68350Seric *statp = EX_NOTFOUND; 1338*68350Seric else if (result->status == NIS_TRYAGAIN) 1339*68350Seric *statp = EX_TEMPFAIL; 1340*68350Seric else 1341*68350Seric { 1342*68350Seric *statp = EX_UNAVAILABLE; 1343*68350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 1344*68350Seric } 1345*68350Seric #else 1346*68350Seric if ((result->status != NIS_NOTFOUND) && 1347*68350Seric (result->status != NIS_TRYAGAIN)) 1348*68350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 1349*68350Seric #endif 1350*68350Seric } 1351*68350Seric if (tTd(38, 20)) 1352*68350Seric printf("nisplus_map_lookup(%s), failed\n", name); 1353*68350Seric nis_freeresult(result); 1354*68350Seric return NULL; 135567848Seric } 135667848Seric 1357*68350Seric 1358*68350Seric char * 1359*68350Seric nisplus_default_domain() 1360*68350Seric { 1361*68350Seric static char default_domain[MAXNAME] = ""; 1362*68350Seric nis_result *res = NULL; 1363*68350Seric char *p; 1364*68350Seric 1365*68350Seric if (default_domain[0] != '\0') 1366*68350Seric return(default_domain); 1367*68350Seric 1368*68350Seric if (VendorCode == VENDOR_SUN && ConfigLevel < 2) 1369*68350Seric { 1370*68350Seric /* for old config, user nis+ local directory */ 1371*68350Seric /* have to be backward compatible with bugs too :-( */ 1372*68350Seric p = nis_local_directory(); 1373*68350Seric strcpy(default_domain, p); 1374*68350Seric return default_domain; 1375*68350Seric } 1376*68350Seric 1377*68350Seric if ((p = macvalue('m', CurEnv)) == NULL) 1378*68350Seric { 1379*68350Seric p = nis_local_directory(); 1380*68350Seric strcpy(default_domain, p); 1381*68350Seric return default_domain; 1382*68350Seric } 1383*68350Seric 1384*68350Seric strcpy(default_domain, p); 1385*68350Seric if (PARTIAL_NAME(default_domain)) 1386*68350Seric strcat(default_domain, "."); 1387*68350Seric 1388*68350Seric res = nis_lookup(default_domain, FOLLOW_LINKS); 1389*68350Seric if (res->status == NIS_NOTFOUND) 1390*68350Seric { 1391*68350Seric p = nis_local_directory(); 1392*68350Seric strcpy(default_domain, p); 1393*68350Seric } 1394*68350Seric return(default_domain); 1395*68350Seric } 1396*68350Seric 1397*68350Seric #endif /* NISPLUS */ 139867848Seric /* 1399*68350Seric ** HESIOD Modules 1400*68350Seric ** 1401*68350Seric ** Only works for aliases (for now). 1402*68350Seric */ 1403*68350Seric 1404*68350Seric #ifdef HESIOD 1405*68350Seric 1406*68350Seric #include <hesiod.h> 1407*68350Seric 1408*68350Seric char * 1409*68350Seric hes_map_lookup(map, name, av, statp) 1410*68350Seric MAP *map; 1411*68350Seric char *name; 1412*68350Seric char **av; 1413*68350Seric int *statp; 1414*68350Seric { 1415*68350Seric char **hp; 1416*68350Seric char *retdata = NULL; 1417*68350Seric int i; 1418*68350Seric 1419*68350Seric if (tTd(38, 20)) 1420*68350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 1421*68350Seric 1422*68350Seric hp = hes_resolve(name, map->map_file); 1423*68350Seric if (hp == NULL) 1424*68350Seric return NULL; 1425*68350Seric 1426*68350Seric if (hp[0] != NULL) 1427*68350Seric { 1428*68350Seric if (tTd(38, 20)) 1429*68350Seric printf(" %d %s\n", i, p); 1430*68350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 1431*68350Seric retdata = map_rewrite(map, name, strlen(name), NULL); 1432*68350Seric else 1433*68350Seric retdata = map_rewrite(map, hp[0], strlen(hp[0]), av); 1434*68350Seric } 1435*68350Seric 1436*68350Seric for (i = 0; hp[i] != NULL; i++) 1437*68350Seric free(hp[i]); 1438*68350Seric free(hp); 1439*68350Seric return retdata; 1440*68350Seric } 1441*68350Seric 1442*68350Seric #endif 1443*68350Seric /* 1444*68350Seric ** NeXT NETINFO Modules 1445*68350Seric */ 1446*68350Seric 1447*68350Seric #ifdef NETINFO 1448*68350Seric 1449*68350Seric #define NETINFO_DEFAULT_DIR "/aliases" 1450*68350Seric #define NETINFO_DEFAULT_PROPERTY "members" 1451*68350Seric 1452*68350Seric 1453*68350Seric /* 1454*68350Seric ** NI_MAP_OPEN -- open NetInfo Aliases 1455*68350Seric */ 1456*68350Seric 1457*68350Seric bool 1458*68350Seric ni_map_open(map, mode) 1459*68350Seric MAP *map; 1460*68350Seric int mode; 1461*68350Seric { 1462*68350Seric char *p; 1463*68350Seric 1464*68350Seric if (tTd(38, 20)) 1465*68350Seric printf("ni_map_open: %s\n", map->map_file); 1466*68350Seric 1467*68350Seric if (*map->map_file == '\0') 1468*68350Seric map->map_file = NETINFO_DEFAULT_DIR; 1469*68350Seric 1470*68350Seric if (map->map_valcolnm == NULL) 1471*68350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 1472*68350Seric 1473*68350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 1474*68350Seric map->map_coldelim = ','; 1475*68350Seric 1476*68350Seric return TRUE; 1477*68350Seric } 1478*68350Seric 1479*68350Seric 1480*68350Seric /* 1481*68350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 1482*68350Seric */ 1483*68350Seric 1484*68350Seric char * 1485*68350Seric ni_map_lookup(map, name, av, statp) 1486*68350Seric MAP *map; 1487*68350Seric char *name; 1488*68350Seric char **av; 1489*68350Seric int *statp; 1490*68350Seric { 1491*68350Seric char *res; 1492*68350Seric char *propval; 1493*68350Seric extern char *ni_propval(); 1494*68350Seric 1495*68350Seric if (tTd(38, 20)) 1496*68350Seric printf("ni_map_lookup(%s, %s)\n", 1497*68350Seric map->map_mname, name); 1498*68350Seric 1499*68350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 1500*68350Seric map->map_valcolnm, map->map_coldelim); 1501*68350Seric 1502*68350Seric if (propval == NULL) 1503*68350Seric return NULL; 1504*68350Seric 1505*68350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 1506*68350Seric res = map_rewrite(map, name, strlen(name), NULL); 1507*68350Seric else 1508*68350Seric res = map_rewrite(map, propval, strlen(propval), av); 1509*68350Seric free(propval); 1510*68350Seric return res; 1511*68350Seric } 1512*68350Seric 1513*68350Seric #endif 1514*68350Seric /* 1515*68350Seric ** TEXT (unindexed text file) Modules 1516*68350Seric ** 1517*68350Seric ** This code donated by Sun Microsystems. 1518*68350Seric */ 1519*68350Seric 1520*68350Seric 1521*68350Seric /* 1522*68350Seric ** TEXT_MAP_OPEN -- open text table 1523*68350Seric */ 1524*68350Seric 1525*68350Seric bool 1526*68350Seric text_map_open(map, mode) 1527*68350Seric MAP *map; 1528*68350Seric int mode; 1529*68350Seric { 1530*68350Seric struct stat sbuf; 1531*68350Seric 1532*68350Seric if (tTd(38, 2)) 1533*68350Seric printf("text_map_open(%s, %s, %d)\n", 1534*68350Seric map->map_mname, map->map_file, mode); 1535*68350Seric 1536*68350Seric if (mode != O_RDONLY) 1537*68350Seric { 1538*68350Seric errno = ENODEV; 1539*68350Seric return FALSE; 1540*68350Seric } 1541*68350Seric 1542*68350Seric if (*map->map_file == '\0') 1543*68350Seric { 1544*68350Seric if (tTd(38, 2)) 1545*68350Seric printf("text_map_open: file name required\n"); 1546*68350Seric return FALSE; 1547*68350Seric } 1548*68350Seric 1549*68350Seric if (map->map_file[0] != '/') 1550*68350Seric { 1551*68350Seric if (tTd(38, 2)) 1552*68350Seric printf("text_map_open(%s): file name must be fully qualified\n", 1553*68350Seric map->map_file); 1554*68350Seric return FALSE; 1555*68350Seric } 1556*68350Seric /* check to see if this map actually accessable */ 1557*68350Seric if (access(map->map_file, R_OK) <0) 1558*68350Seric return FALSE; 1559*68350Seric 1560*68350Seric /* check to see if this map actually exist */ 1561*68350Seric if (stat(map->map_file, &sbuf) <0) 1562*68350Seric { 1563*68350Seric if (tTd(38, 2)) 1564*68350Seric printf("text_map_open(%s): can not stat %s\n", 1565*68350Seric map->map_file, map->map_file); 1566*68350Seric return FALSE; 1567*68350Seric } 1568*68350Seric 1569*68350Seric if (!S_ISREG(sbuf.st_mode)) 1570*68350Seric { 1571*68350Seric if (tTd(38, 2)) 1572*68350Seric printf("text_map_open(%s): %s is not a file\n", 1573*68350Seric map->map_file, map->map_file); 1574*68350Seric return FALSE; 1575*68350Seric } 1576*68350Seric 1577*68350Seric if (map->map_keycolnm == NULL) 1578*68350Seric map->map_keycolno = 0; 1579*68350Seric else 1580*68350Seric { 1581*68350Seric if (!isdigit(*map->map_keycolnm)) 1582*68350Seric { 1583*68350Seric if (tTd(38, 2)) 1584*68350Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 1585*68350Seric map->map_file, map->map_keycolnm); 1586*68350Seric return FALSE; 1587*68350Seric } 1588*68350Seric map->map_keycolno = atoi(map->map_keycolnm); 1589*68350Seric } 1590*68350Seric 1591*68350Seric if (map->map_valcolnm == NULL) 1592*68350Seric map->map_valcolno = 0; 1593*68350Seric else 1594*68350Seric { 1595*68350Seric if (!isdigit(*map->map_valcolnm)) 1596*68350Seric { 1597*68350Seric if (tTd(38, 2)) 1598*68350Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 1599*68350Seric map->map_file, map->map_valcolnm); 1600*68350Seric return FALSE; 1601*68350Seric } 1602*68350Seric map->map_valcolno = atoi(map->map_valcolnm); 1603*68350Seric } 1604*68350Seric 1605*68350Seric if (map->map_coldelim == '\0') 1606*68350Seric map->map_coldelim = ':'; 1607*68350Seric 1608*68350Seric if (tTd(38, 2)) 1609*68350Seric { 1610*68350Seric printf("text_map_open(%s): delimiter = %c\n", 1611*68350Seric map->map_file, map->map_coldelim); 1612*68350Seric } 1613*68350Seric 1614*68350Seric return TRUE; 1615*68350Seric } 1616*68350Seric 1617*68350Seric 1618*68350Seric /* 1619*68350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 1620*68350Seric */ 1621*68350Seric 1622*68350Seric char * 1623*68350Seric text_map_lookup(map, name, av, statp) 1624*68350Seric MAP *map; 1625*68350Seric char *name; 1626*68350Seric char **av; 1627*68350Seric int *statp; 1628*68350Seric { 1629*68350Seric char *vp; 1630*68350Seric auto int vsize; 1631*68350Seric int buflen; 1632*68350Seric char search_key[MAXNAME + 1]; 1633*68350Seric char linebuf[MAXLINE]; 1634*68350Seric FILE *f; 1635*68350Seric char buf[MAXNAME+1]; 1636*68350Seric char delim; 1637*68350Seric int key_idx; 1638*68350Seric bool found_it; 1639*68350Seric extern char *get_column(); 1640*68350Seric 1641*68350Seric 1642*68350Seric found_it = FALSE; 1643*68350Seric if (tTd(38, 20)) 1644*68350Seric printf("text_map_lookup(%s)\n", name); 1645*68350Seric 1646*68350Seric buflen = strlen(name); 1647*68350Seric if (buflen > sizeof search_key - 1) 1648*68350Seric buflen = sizeof search_key - 1; 1649*68350Seric bcopy(name, search_key, buflen + 1); 1650*68350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 1651*68350Seric makelower(search_key); 1652*68350Seric 1653*68350Seric f = fopen(map->map_file, "r"); 1654*68350Seric if (f == NULL) 1655*68350Seric { 1656*68350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 1657*68350Seric *statp = EX_UNAVAILABLE; 1658*68350Seric return NULL; 1659*68350Seric } 1660*68350Seric key_idx = map->map_keycolno; 1661*68350Seric delim = map->map_coldelim; 1662*68350Seric while (fgets(linebuf, MAXLINE, f)) 1663*68350Seric { 1664*68350Seric char *lf; 1665*68350Seric if (linebuf[0] == '#') 1666*68350Seric continue; /* skip comment line */ 1667*68350Seric if (lf = strchr(linebuf, '\n')) 1668*68350Seric *lf = '\0'; 1669*68350Seric if (!strcasecmp(search_key, 1670*68350Seric get_column(linebuf, key_idx, delim, buf))) 1671*68350Seric { 1672*68350Seric found_it = TRUE; 1673*68350Seric break; 1674*68350Seric } 1675*68350Seric } 1676*68350Seric fclose(f); 1677*68350Seric if (!found_it) 1678*68350Seric { 1679*68350Seric #ifdef MAP_EXIT_STAT 1680*68350Seric *statp = EX_NOTFOUND; 1681*68350Seric #endif 1682*68350Seric return(NULL); 1683*68350Seric } 1684*68350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 1685*68350Seric vsize = strlen(vp); 1686*68350Seric #ifdef MAP_EXIT_STAT 1687*68350Seric *statp = EX_OK; 1688*68350Seric #endif 1689*68350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 1690*68350Seric return map_rewrite(map, name, strlen(name), NULL); 1691*68350Seric else 1692*68350Seric return map_rewrite(map, vp, vsize, av); 1693*68350Seric } 1694*68350Seric /* 169560089Seric ** STAB (Symbol Table) Modules 169660089Seric */ 169760089Seric 169860089Seric 169960089Seric /* 170060207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 170160089Seric */ 170260089Seric 170360089Seric char * 170461707Seric stab_map_lookup(map, name, av, pstat) 170560089Seric register MAP *map; 170660089Seric char *name; 170761707Seric char **av; 170861707Seric int *pstat; 170960089Seric { 171060089Seric register STAB *s; 171160089Seric 171260537Seric if (tTd(38, 20)) 1713*68350Seric printf("stab_lookup(%s, %s)\n", 1714*68350Seric map->map_mname, name); 171560089Seric 171660089Seric s = stab(name, ST_ALIAS, ST_FIND); 171760089Seric if (s != NULL) 171860089Seric return (s->s_alias); 171960089Seric return (NULL); 172060089Seric } 172160089Seric 172260089Seric 172360089Seric /* 172460207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 172560089Seric */ 172660089Seric 172760089Seric void 172860089Seric stab_map_store(map, lhs, rhs) 172960089Seric register MAP *map; 173060089Seric char *lhs; 173160089Seric char *rhs; 173260089Seric { 173360089Seric register STAB *s; 173460089Seric 173560089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 173660089Seric s->s_alias = newstr(rhs); 173760089Seric } 173860089Seric 173960089Seric 174060089Seric /* 174160207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 174260207Seric ** 174360207Seric ** This is a wierd case -- it is only intended as a fallback for 174460207Seric ** aliases. For this reason, opens for write (only during a 174560207Seric ** "newaliases") always fails, and opens for read open the 174660207Seric ** actual underlying text file instead of the database. 174760089Seric */ 174860089Seric 174960089Seric bool 175060089Seric stab_map_open(map, mode) 175160089Seric register MAP *map; 175260089Seric int mode; 175360089Seric { 175463835Seric FILE *af; 175564284Seric struct stat st; 175663835Seric 175760537Seric if (tTd(38, 2)) 1758*68350Seric printf("stab_map_open(%s, %s)\n", 1759*68350Seric map->map_mname, map->map_file); 176060089Seric 176160089Seric if (mode != O_RDONLY) 176260207Seric { 176360207Seric errno = ENODEV; 176460089Seric return FALSE; 176560207Seric } 176660089Seric 176763835Seric af = fopen(map->map_file, "r"); 176863835Seric if (af == NULL) 176963835Seric return FALSE; 1770*68350Seric readaliases(map, af, FALSE, FALSE); 177164284Seric 177264284Seric if (fstat(fileno(af), &st) >= 0) 177364284Seric map->map_mtime = st.st_mtime; 177463835Seric fclose(af); 177563835Seric 177660089Seric return TRUE; 177760089Seric } 177860089Seric /* 177960089Seric ** Implicit Modules 178056822Seric ** 178160089Seric ** Tries several types. For back compatibility of aliases. 178256822Seric */ 178356822Seric 178460089Seric 178560089Seric /* 178660207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 178760089Seric */ 178860089Seric 178960089Seric char * 179060089Seric impl_map_lookup(map, name, av, pstat) 179160089Seric MAP *map; 179260089Seric char *name; 179356822Seric char **av; 179460089Seric int *pstat; 179556822Seric { 179660537Seric if (tTd(38, 20)) 1797*68350Seric printf("impl_map_lookup(%s, %s)\n", 1798*68350Seric map->map_mname, name); 179956822Seric 180060089Seric #ifdef NEWDB 180160207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 180260089Seric return db_map_lookup(map, name, av, pstat); 180360089Seric #endif 180460089Seric #ifdef NDBM 180560207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 180660089Seric return ndbm_map_lookup(map, name, av, pstat); 180760089Seric #endif 180860089Seric return stab_map_lookup(map, name, av, pstat); 180960089Seric } 181060089Seric 181160089Seric /* 181260207Seric ** IMPL_MAP_STORE -- store in open databases 181360089Seric */ 181460089Seric 181560089Seric void 181660089Seric impl_map_store(map, lhs, rhs) 181760089Seric MAP *map; 181860089Seric char *lhs; 181960089Seric char *rhs; 182060089Seric { 182160089Seric #ifdef NEWDB 182260207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 182360089Seric db_map_store(map, lhs, rhs); 182460089Seric #endif 182560089Seric #ifdef NDBM 182660207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 182760089Seric ndbm_map_store(map, lhs, rhs); 182860089Seric #endif 182960089Seric stab_map_store(map, lhs, rhs); 183060089Seric } 183160089Seric 183260089Seric /* 183360089Seric ** IMPL_MAP_OPEN -- implicit database open 183460089Seric */ 183560089Seric 183660089Seric bool 183760089Seric impl_map_open(map, mode) 183860089Seric MAP *map; 183960089Seric int mode; 184060089Seric { 184160089Seric struct stat stb; 184260089Seric 184360537Seric if (tTd(38, 2)) 1844*68350Seric printf("impl_map_open(%s, %s, %d)\n", 1845*68350Seric map->map_mname, map->map_file, mode); 184660089Seric 184760089Seric if (stat(map->map_file, &stb) < 0) 184856822Seric { 184960089Seric /* no alias file at all */ 185064718Seric if (tTd(38, 3)) 185164718Seric printf("no map file\n"); 185260089Seric return FALSE; 185356822Seric } 185456822Seric 185560089Seric #ifdef NEWDB 185660207Seric map->map_mflags |= MF_IMPL_HASH; 185760089Seric if (hash_map_open(map, mode)) 185856822Seric { 185964250Seric #if defined(NDBM) && defined(NIS) 186060561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 186160207Seric #endif 186260207Seric return TRUE; 186360089Seric } 186460207Seric else 186560207Seric map->map_mflags &= ~MF_IMPL_HASH; 186660089Seric #endif 186760089Seric #ifdef NDBM 186860207Seric map->map_mflags |= MF_IMPL_NDBM; 186960089Seric if (ndbm_map_open(map, mode)) 187060089Seric { 187160089Seric return TRUE; 187260089Seric } 187360207Seric else 187460207Seric map->map_mflags &= ~MF_IMPL_NDBM; 187560089Seric #endif 187656822Seric 187764650Seric #if defined(NEWDB) || defined(NDBM) 187860089Seric if (Verbose) 187960089Seric message("WARNING: cannot open alias database %s", map->map_file); 188064964Seric #else 188164964Seric if (mode != O_RDONLY) 188264964Seric usrerr("Cannot rebuild aliases: no database format defined"); 188360207Seric #endif 188460089Seric 188560207Seric return stab_map_open(map, mode); 188656822Seric } 188760089Seric 188860207Seric 188960089Seric /* 189060207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 189160089Seric */ 189260089Seric 189360089Seric void 189460207Seric impl_map_close(map) 189560089Seric MAP *map; 189660089Seric { 1897*68350Seric if (tTd(38, 20)) 1898*68350Seric printf("impl_map_close(%s, %s, %x)\n", 1899*68350Seric map->map_mname, map->map_file, map->map_mflags); 190060089Seric #ifdef NEWDB 190160207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 190260089Seric { 190360207Seric db_map_close(map); 190460207Seric map->map_mflags &= ~MF_IMPL_HASH; 190560089Seric } 190660089Seric #endif 190760089Seric 190860089Seric #ifdef NDBM 190960207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 191060089Seric { 191160207Seric ndbm_map_close(map); 191260207Seric map->map_mflags &= ~MF_IMPL_NDBM; 191360089Seric } 191460089Seric #endif 191560089Seric } 191660207Seric /* 1917*68350Seric ** User map class. 1918*68350Seric ** 1919*68350Seric ** Provides access to the system password file. 1920*68350Seric */ 1921*68350Seric 1922*68350Seric /* 1923*68350Seric ** USER_MAP_OPEN -- open user map 1924*68350Seric ** 1925*68350Seric ** Really just binds field names to field numbers. 1926*68350Seric */ 1927*68350Seric 1928*68350Seric bool 1929*68350Seric user_map_open(map, mode) 1930*68350Seric MAP *map; 1931*68350Seric int mode; 1932*68350Seric { 1933*68350Seric if (tTd(38, 2)) 1934*68350Seric printf("user_map_open(%s)\n", map->map_mname); 1935*68350Seric 1936*68350Seric if (mode != O_RDONLY) 1937*68350Seric { 1938*68350Seric /* issue a pseudo-error message */ 1939*68350Seric #ifdef ENOSYS 1940*68350Seric errno = ENOSYS; 1941*68350Seric #else 1942*68350Seric # ifdef EFTYPE 1943*68350Seric errno = EFTYPE; 1944*68350Seric # else 1945*68350Seric errno = ENXIO; 1946*68350Seric # endif 1947*68350Seric #endif 1948*68350Seric return FALSE; 1949*68350Seric } 1950*68350Seric if (map->map_valcolnm == NULL) 1951*68350Seric /* nothing */ ; 1952*68350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 1953*68350Seric map->map_valcolno = 1; 1954*68350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 1955*68350Seric map->map_valcolno = 2; 1956*68350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 1957*68350Seric map->map_valcolno = 3; 1958*68350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 1959*68350Seric map->map_valcolno = 4; 1960*68350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 1961*68350Seric map->map_valcolno = 5; 1962*68350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 1963*68350Seric map->map_valcolno = 6; 1964*68350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 1965*68350Seric map->map_valcolno = 7; 1966*68350Seric else 1967*68350Seric { 1968*68350Seric syserr("User map %s: unknown column name %s", 1969*68350Seric map->map_mname, map->map_valcolnm); 1970*68350Seric return FALSE; 1971*68350Seric } 1972*68350Seric return TRUE; 1973*68350Seric } 1974*68350Seric 1975*68350Seric 1976*68350Seric /* 1977*68350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 1978*68350Seric */ 1979*68350Seric 1980*68350Seric #include <pwd.h> 1981*68350Seric 1982*68350Seric char * 1983*68350Seric user_map_lookup(map, key, av, statp) 1984*68350Seric MAP *map; 1985*68350Seric char *key; 1986*68350Seric char **av; 1987*68350Seric int *statp; 1988*68350Seric { 1989*68350Seric struct passwd *pw; 1990*68350Seric 1991*68350Seric if (tTd(38, 20)) 1992*68350Seric printf("user_map_lookup(%s, %s)\n", 1993*68350Seric map->map_mname, key); 1994*68350Seric 1995*68350Seric pw = getpwnam(key); 1996*68350Seric if (pw == NULL) 1997*68350Seric return NULL; 1998*68350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 1999*68350Seric return map_rewrite(map, key, strlen(key), NULL); 2000*68350Seric else 2001*68350Seric { 2002*68350Seric char *rwval; 2003*68350Seric char buf[30]; 2004*68350Seric 2005*68350Seric switch (map->map_valcolno) 2006*68350Seric { 2007*68350Seric case 0: 2008*68350Seric case 1: 2009*68350Seric rwval = pw->pw_name; 2010*68350Seric break; 2011*68350Seric 2012*68350Seric case 2: 2013*68350Seric rwval = pw->pw_passwd; 2014*68350Seric break; 2015*68350Seric 2016*68350Seric case 3: 2017*68350Seric sprintf(buf, "%d", pw->pw_uid); 2018*68350Seric rwval = buf; 2019*68350Seric break; 2020*68350Seric 2021*68350Seric case 4: 2022*68350Seric sprintf(buf, "%d", pw->pw_gid); 2023*68350Seric rwval = buf; 2024*68350Seric break; 2025*68350Seric 2026*68350Seric case 5: 2027*68350Seric rwval = pw->pw_gecos; 2028*68350Seric break; 2029*68350Seric 2030*68350Seric case 6: 2031*68350Seric rwval = pw->pw_dir; 2032*68350Seric break; 2033*68350Seric 2034*68350Seric case 7: 2035*68350Seric rwval = pw->pw_shell; 2036*68350Seric break; 2037*68350Seric } 2038*68350Seric return map_rewrite(map, rwval, strlen(rwval), av); 2039*68350Seric } 2040*68350Seric } 2041*68350Seric /* 2042*68350Seric ** BESTMX -- find the best MX for a name 2043*68350Seric ** 2044*68350Seric ** This is really a hack, but I don't see any obvious way 2045*68350Seric ** to generalize it at the moment. 2046*68350Seric */ 2047*68350Seric 2048*68350Seric #if NAMED_BIND 2049*68350Seric 2050*68350Seric char * 2051*68350Seric bestmx_map_lookup(map, name, av, statp) 2052*68350Seric MAP *map; 2053*68350Seric char *name; 2054*68350Seric char **av; 2055*68350Seric int *statp; 2056*68350Seric { 2057*68350Seric int nmx; 2058*68350Seric auto int rcode; 2059*68350Seric char *mxhosts[MAXMXHOSTS + 1]; 2060*68350Seric 2061*68350Seric nmx = getmxrr(name, mxhosts, FALSE, &rcode); 2062*68350Seric if (nmx <= 0) 2063*68350Seric return NULL; 2064*68350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 2065*68350Seric return map_rewrite(map, name, strlen(name), NULL); 2066*68350Seric else 2067*68350Seric return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 2068*68350Seric } 2069*68350Seric 2070*68350Seric #endif 2071*68350Seric /* 2072*68350Seric ** Sequenced map type. 2073*68350Seric ** 2074*68350Seric ** Tries each map in order until something matches, much like 2075*68350Seric ** implicit. Stores go to the first map in the list that can 2076*68350Seric ** support storing. 2077*68350Seric ** 2078*68350Seric ** This is slightly unusual in that there are two interfaces. 2079*68350Seric ** The "sequence" interface lets you stack maps arbitrarily. 2080*68350Seric ** The "switch" interface builds a sequence map by looking 2081*68350Seric ** at a system-dependent configuration file such as 2082*68350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 2083*68350Seric ** 2084*68350Seric ** We don't need an explicit open, since all maps are 2085*68350Seric ** opened during startup, including underlying maps. 2086*68350Seric */ 2087*68350Seric 2088*68350Seric /* 2089*68350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 2090*68350Seric */ 2091*68350Seric 2092*68350Seric bool 2093*68350Seric seq_map_parse(map, ap) 2094*68350Seric MAP *map; 2095*68350Seric char *ap; 2096*68350Seric { 2097*68350Seric int maxmap; 2098*68350Seric 2099*68350Seric if (tTd(38, 2)) 2100*68350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 2101*68350Seric maxmap = 0; 2102*68350Seric while (*ap != '\0') 2103*68350Seric { 2104*68350Seric register char *p; 2105*68350Seric STAB *s; 2106*68350Seric 2107*68350Seric /* find beginning of map name */ 2108*68350Seric while (isascii(*ap) && isspace(*ap)) 2109*68350Seric ap++; 2110*68350Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 2111*68350Seric continue; 2112*68350Seric if (*p != '\0') 2113*68350Seric *p++ = '\0'; 2114*68350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 2115*68350Seric p++; 2116*68350Seric if (*ap == '\0') 2117*68350Seric { 2118*68350Seric ap = p; 2119*68350Seric continue; 2120*68350Seric } 2121*68350Seric s = stab(ap, ST_MAP, ST_FIND); 2122*68350Seric if (s == NULL) 2123*68350Seric { 2124*68350Seric syserr("Sequence map %s: unknown member map %s", 2125*68350Seric map->map_mname, ap); 2126*68350Seric } 2127*68350Seric else if (maxmap == MAXMAPSTACK) 2128*68350Seric { 2129*68350Seric syserr("Sequence map %s: too many member maps (%d max)", 2130*68350Seric map->map_mname, MAXMAPSTACK); 2131*68350Seric maxmap++; 2132*68350Seric } 2133*68350Seric else if (maxmap < MAXMAPSTACK) 2134*68350Seric { 2135*68350Seric map->map_stack[maxmap++] = &s->s_map; 2136*68350Seric } 2137*68350Seric ap = p; 2138*68350Seric } 2139*68350Seric return TRUE; 2140*68350Seric } 2141*68350Seric 2142*68350Seric 2143*68350Seric /* 2144*68350Seric ** SWITCH_MAP_OPEN -- open a switched map 2145*68350Seric ** 2146*68350Seric ** This looks at the system-dependent configuration and builds 2147*68350Seric ** a sequence map that does the same thing. 2148*68350Seric ** 2149*68350Seric ** Every system must define a switch_map_find routine in conf.c 2150*68350Seric ** that will return the list of service types associated with a 2151*68350Seric ** given service class. 2152*68350Seric */ 2153*68350Seric 2154*68350Seric bool 2155*68350Seric switch_map_open(map, mode) 2156*68350Seric MAP *map; 2157*68350Seric int mode; 2158*68350Seric { 2159*68350Seric int mapno; 2160*68350Seric int nmaps; 2161*68350Seric char *maptype[MAXMAPSTACK]; 2162*68350Seric 2163*68350Seric if (tTd(38, 2)) 2164*68350Seric printf("switch_map_open(%s, %s, %d)\n", 2165*68350Seric map->map_mname, map->map_file, mode); 2166*68350Seric 2167*68350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 2168*68350Seric if (tTd(38, 19)) 2169*68350Seric { 2170*68350Seric printf("\tswitch_map_find => %d\n", nmaps); 2171*68350Seric for (mapno = 0; mapno < nmaps; mapno++) 2172*68350Seric printf("\t\t%s\n", maptype[mapno]); 2173*68350Seric } 2174*68350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 2175*68350Seric return FALSE; 2176*68350Seric 2177*68350Seric for (mapno = 0; mapno < nmaps; mapno++) 2178*68350Seric { 2179*68350Seric register STAB *s; 2180*68350Seric char nbuf[MAXNAME + 1]; 2181*68350Seric 2182*68350Seric if (maptype[mapno] == NULL) 2183*68350Seric continue; 2184*68350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 2185*68350Seric s = stab(nbuf, ST_MAP, ST_FIND); 2186*68350Seric if (s == NULL) 2187*68350Seric { 2188*68350Seric syserr("Switch map %s: unknown member map %s", 2189*68350Seric map->map_mname, nbuf); 2190*68350Seric } 2191*68350Seric else 2192*68350Seric { 2193*68350Seric map->map_stack[mapno] = &s->s_map; 2194*68350Seric if (tTd(38, 4)) 2195*68350Seric printf("\tmap_stack[%d] = %s:%s\n", 2196*68350Seric mapno, s->s_map.map_class->map_cname, 2197*68350Seric nbuf); 2198*68350Seric } 2199*68350Seric } 2200*68350Seric return TRUE; 2201*68350Seric } 2202*68350Seric 2203*68350Seric 2204*68350Seric /* 2205*68350Seric ** SEQ_MAP_CLOSE -- close all underlying maps 2206*68350Seric */ 2207*68350Seric 2208*68350Seric seq_map_close(map) 2209*68350Seric MAP *map; 2210*68350Seric { 2211*68350Seric int mapno; 2212*68350Seric 2213*68350Seric if (tTd(38, 20)) 2214*68350Seric printf("seq_map_close(%s)\n", map->map_mname); 2215*68350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 2216*68350Seric { 2217*68350Seric MAP *mm = map->map_stack[mapno]; 2218*68350Seric 2219*68350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 2220*68350Seric continue; 2221*68350Seric mm->map_class->map_close(mm); 2222*68350Seric } 2223*68350Seric } 2224*68350Seric 2225*68350Seric 2226*68350Seric /* 2227*68350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 2228*68350Seric */ 2229*68350Seric 2230*68350Seric char * 2231*68350Seric seq_map_lookup(map, key, args, pstat) 2232*68350Seric MAP *map; 2233*68350Seric char *key; 2234*68350Seric char **args; 2235*68350Seric int *pstat; 2236*68350Seric { 2237*68350Seric int mapno; 2238*68350Seric int mapbit = 0x01; 2239*68350Seric 2240*68350Seric if (tTd(38, 20)) 2241*68350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 2242*68350Seric 2243*68350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 2244*68350Seric { 2245*68350Seric MAP *mm = map->map_stack[mapno]; 2246*68350Seric int stat = 0; 2247*68350Seric char *rv; 2248*68350Seric 2249*68350Seric if (mm == NULL) 2250*68350Seric continue; 2251*68350Seric if (!bitset(MF_OPEN, mm->map_mflags)) 2252*68350Seric { 2253*68350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 2254*68350Seric { 2255*68350Seric *pstat = EX_UNAVAILABLE; 2256*68350Seric return NULL; 2257*68350Seric } 2258*68350Seric continue; 2259*68350Seric } 2260*68350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 2261*68350Seric if (rv != NULL) 2262*68350Seric return rv; 2263*68350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 2264*68350Seric return NULL; 2265*68350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 2266*68350Seric { 2267*68350Seric *pstat = stat; 2268*68350Seric return NULL; 2269*68350Seric } 2270*68350Seric } 2271*68350Seric return NULL; 2272*68350Seric } 2273*68350Seric 2274*68350Seric 2275*68350Seric /* 2276*68350Seric ** SEQ_MAP_STORE -- sequenced map store 2277*68350Seric */ 2278*68350Seric 2279*68350Seric void 2280*68350Seric seq_map_store(map, key, val) 2281*68350Seric MAP *map; 2282*68350Seric char *key; 2283*68350Seric char *val; 2284*68350Seric { 2285*68350Seric int mapno; 2286*68350Seric 2287*68350Seric if (tTd(38, 12)) 2288*68350Seric printf("seq_map_store(%s, %s, %s)\n", 2289*68350Seric map->map_mname, key, val); 2290*68350Seric 2291*68350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 2292*68350Seric { 2293*68350Seric MAP *mm = map->map_stack[mapno]; 2294*68350Seric 2295*68350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 2296*68350Seric continue; 2297*68350Seric 2298*68350Seric mm->map_class->map_store(mm, key, val); 2299*68350Seric return; 2300*68350Seric } 2301*68350Seric syserr("seq_map_store(%s, %s, %s): no writable map", 2302*68350Seric map->map_mname, key, val); 2303*68350Seric } 2304*68350Seric /* 230560207Seric ** NULL stubs 230660089Seric */ 230760089Seric 230860207Seric bool 230960207Seric null_map_open(map, mode) 231060089Seric MAP *map; 231160207Seric int mode; 231260089Seric { 231360207Seric return TRUE; 231460089Seric } 231560089Seric 231660207Seric void 231760207Seric null_map_close(map) 231860207Seric MAP *map; 231960089Seric { 232060207Seric return; 232160207Seric } 232260089Seric 232360207Seric void 232460207Seric null_map_store(map, key, val) 232560207Seric MAP *map; 232660207Seric char *key; 232760207Seric char *val; 232860089Seric { 232960207Seric return; 233060089Seric } 2331*68350Seric 2332*68350Seric 2333*68350Seric /* 2334*68350Seric ** BOGUS stubs 2335*68350Seric */ 2336*68350Seric 2337*68350Seric char * 2338*68350Seric bogus_map_lookup(map, key, args, pstat) 2339*68350Seric MAP *map; 2340*68350Seric char *key; 2341*68350Seric char **args; 2342*68350Seric int *pstat; 2343*68350Seric { 2344*68350Seric *pstat = EX_TEMPFAIL; 2345*68350Seric return NULL; 2346*68350Seric } 2347*68350Seric 2348*68350Seric MAPCLASS BogusMapClass = 2349*68350Seric { 2350*68350Seric "bogus-map", NULL, 0, 2351*68350Seric NULL, bogus_map_lookup, null_map_store, 2352*68350Seric null_map_open, null_map_close, 2353*68350Seric }; 2354