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*67895Seric static char sccsid[] = "@(#)map.c 8.35 (Berkeley) 11/08/94"; 1156822Seric #endif /* not lint */ 1256822Seric 1356822Seric #include "sendmail.h" 1456822Seric 1560089Seric #ifdef NDBM 1656822Seric #include <ndbm.h> 1756822Seric #endif 1860089Seric #ifdef NEWDB 1956822Seric #include <db.h> 2056822Seric #endif 2160089Seric #ifdef NIS 2257208Seric #include <rpcsvc/ypclnt.h> 2357208Seric #endif 2456822Seric 2556822Seric /* 2660089Seric ** MAP.C -- implementations for various map classes. 2756822Seric ** 2860089Seric ** Each map class implements a series of functions: 2960089Seric ** 3060089Seric ** bool map_parse(MAP *map, char *args) 3160089Seric ** Parse the arguments from the config file. Return TRUE 3260089Seric ** if they were ok, FALSE otherwise. Fill in map with the 3360089Seric ** values. 3460089Seric ** 3560222Seric ** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 3660222Seric ** Look up the key in the given map. If found, do any 3760222Seric ** rewriting the map wants (including "args" if desired) 3860089Seric ** and return the value. Set *pstat to the appropriate status 3960222Seric ** on error and return NULL. Args will be NULL if called 4060222Seric ** from the alias routines, although this should probably 4160222Seric ** not be relied upon. It is suggested you call map_rewrite 4260222Seric ** to return the results -- it takes care of null termination 4360222Seric ** and uses a dynamically expanded buffer as needed. 4460089Seric ** 4560089Seric ** void map_store(MAP *map, char *key, char *value) 4660089Seric ** Store the key:value pair in the map. 4760089Seric ** 4860089Seric ** bool map_open(MAP *map, int mode) 4960222Seric ** Open the map for the indicated mode. Mode should 5060222Seric ** be either O_RDONLY or O_RDWR. Return TRUE if it 5160222Seric ** was opened successfully, FALSE otherwise. If the open 5260222Seric ** failed an the MF_OPTIONAL flag is not set, it should 5360222Seric ** also print an error. If the MF_ALIAS bit is set 5460222Seric ** and this map class understands the @:@ convention, it 5560222Seric ** should call aliaswait() before returning. 5660089Seric ** 5760089Seric ** void map_close(MAP *map) 5860089Seric ** Close the map. 5960089Seric */ 6060089Seric 6160089Seric #define DBMMODE 0644 6264718Seric 6364718Seric extern bool aliaswait __P((MAP *, char *, int)); 6460089Seric /* 6560089Seric ** MAP_PARSEARGS -- parse config line arguments for database lookup 6660089Seric ** 6760089Seric ** This is a generic version of the map_parse method. 6860089Seric ** 6956822Seric ** Parameters: 7060089Seric ** map -- the map being initialized. 7160089Seric ** ap -- a pointer to the args on the config line. 7256822Seric ** 7356822Seric ** Returns: 7460089Seric ** TRUE -- if everything parsed OK. 7556822Seric ** FALSE -- otherwise. 7656822Seric ** 7756822Seric ** Side Effects: 7860089Seric ** null terminates the filename; stores it in map 7956822Seric */ 8056822Seric 8156822Seric bool 8260089Seric map_parseargs(map, ap) 8356822Seric MAP *map; 8460089Seric char *ap; 8556822Seric { 8660089Seric register char *p = ap; 8756822Seric 8863753Seric map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; 8960089Seric for (;;) 9060089Seric { 9160089Seric while (isascii(*p) && isspace(*p)) 9260089Seric p++; 9360089Seric if (*p != '-') 9460089Seric break; 9560089Seric switch (*++p) 9660089Seric { 9760089Seric case 'N': 9860207Seric map->map_mflags |= MF_INCLNULL; 9963753Seric map->map_mflags &= ~MF_TRY0NULL; 10060089Seric break; 10160089Seric 10263753Seric case 'O': 10363753Seric map->map_mflags &= ~MF_TRY1NULL; 10463753Seric break; 10563753Seric 10660089Seric case 'o': 10760207Seric map->map_mflags |= MF_OPTIONAL; 10860089Seric break; 10960089Seric 11060089Seric case 'f': 11160207Seric map->map_mflags |= MF_NOFOLDCASE; 11260089Seric break; 11360089Seric 11460089Seric case 'm': 11560207Seric map->map_mflags |= MF_MATCHONLY; 11660089Seric break; 11760089Seric 11860089Seric case 'a': 11960089Seric map->map_app = ++p; 12060089Seric break; 12167726Seric 12267726Seric case 'k': 12367726Seric while (isascii(*++p) && isspace(*p)) 12467726Seric continue; 12567726Seric map->map_keycolnm = p; 12667726Seric break; 12767726Seric 12867726Seric case 'v': 12967726Seric while (isascii(*++p) && isspace(*p)) 13067726Seric continue; 13167726Seric map->map_valcolnm = p; 13267726Seric break; 13367726Seric 13467726Seric case 'z': 13567726Seric if (*++p != '\\') 13667726Seric map->map_coldelim = *p; 13767726Seric else 13867726Seric { 13967726Seric switch (*++p) 14067726Seric { 14167726Seric case 'n': 14267726Seric map->map_coldelim = '\n'; 14367726Seric break; 14467726Seric 14567726Seric case 't': 14667726Seric map->map_coldelim = '\t'; 14767726Seric break; 14867726Seric 14967726Seric default: 15067726Seric map->map_coldelim = '\\'; 15167726Seric } 15267726Seric } 15367726Seric break; 15460089Seric } 15560089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 15660089Seric p++; 15760089Seric if (*p != '\0') 15860089Seric *p++ = '\0'; 15960089Seric } 16060089Seric if (map->map_app != NULL) 16160089Seric map->map_app = newstr(map->map_app); 16267726Seric if (map->map_keycolnm != NULL) 16367726Seric map->map_keycolnm = newstr(map->map_keycolnm); 16467726Seric if (map->map_valcolnm != NULL) 16567726Seric map->map_valcolnm = newstr(map->map_valcolnm); 16660089Seric 16760089Seric if (*p != '\0') 16860089Seric { 16960089Seric map->map_file = p; 17060089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 17160089Seric p++; 17260089Seric if (*p != '\0') 17360089Seric *p++ = '\0'; 17460089Seric map->map_file = newstr(map->map_file); 17560089Seric } 17660089Seric 17760089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 17860089Seric p++; 17960089Seric if (*p != '\0') 18060089Seric map->map_rebuild = newstr(p); 18160089Seric 18256822Seric if (map->map_file == NULL) 18357208Seric { 18460089Seric syserr("No file name for %s map %s", 18560089Seric map->map_class->map_cname, map->map_mname); 18656822Seric return FALSE; 18757208Seric } 18860089Seric return TRUE; 18960089Seric } 19060089Seric /* 19160089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 19260089Seric ** 19360089Seric ** It also adds the map_app string. It can be used as a utility 19460089Seric ** in the map_lookup method. 19560089Seric ** 19660089Seric ** Parameters: 19760089Seric ** map -- the map that causes this. 19860089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 19960089Seric ** slen -- the length of s. 20060089Seric ** av -- arguments to interpolate into buf. 20160089Seric ** 20260089Seric ** Returns: 203*67895Seric ** Pointer to rewritten result. This is static data that 204*67895Seric ** should be copied if it is to be saved! 20560089Seric ** 20660089Seric ** Side Effects: 20760089Seric ** none. 20860089Seric */ 20960089Seric 21060089Seric char * 21160089Seric map_rewrite(map, s, slen, av) 21260089Seric register MAP *map; 21360089Seric register char *s; 21460089Seric int slen; 21560089Seric char **av; 21660089Seric { 21760089Seric register char *bp; 21860089Seric register char c; 21960089Seric char **avp; 22060089Seric register char *ap; 22160089Seric int i; 22260089Seric int len; 223*67895Seric static int buflen = -1; 224*67895Seric static char *buf = NULL; 22560089Seric 22660537Seric if (tTd(39, 1)) 22760089Seric { 22860256Seric printf("map_rewrite(%.*s), av =", slen, s); 22960256Seric if (av == NULL) 23060256Seric printf(" (nullv)"); 23160256Seric else 23260256Seric { 23360256Seric for (avp = av; *avp != NULL; avp++) 23460256Seric printf("\n\t%s", *avp); 23560256Seric } 23660256Seric printf("\n"); 23760089Seric } 23860089Seric 23960089Seric /* count expected size of output (can safely overestimate) */ 24060089Seric i = len = slen; 24160089Seric if (av != NULL) 24260089Seric { 24360089Seric bp = s; 24460089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 24560089Seric { 24660089Seric if (c != '%') 24760089Seric continue; 24860089Seric if (--i < 0) 24960089Seric break; 25060089Seric c = *bp++; 25160089Seric if (!(isascii(c) && isdigit(c))) 25260089Seric continue; 25363937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 25460089Seric continue; 25560089Seric if (*avp == NULL) 25660089Seric continue; 25760089Seric len += strlen(*avp); 25860089Seric } 25960089Seric } 26060089Seric if (map->map_app != NULL) 26160089Seric len += strlen(map->map_app); 262*67895Seric if (buflen < ++len) 26360089Seric { 26460089Seric /* need to malloc additional space */ 265*67895Seric buflen = len; 266*67895Seric if (buf != NULL) 267*67895Seric free(buf); 268*67895Seric buf = xalloc(buflen); 26960089Seric } 27060089Seric 271*67895Seric bp = buf; 27260089Seric if (av == NULL) 27360089Seric { 27460089Seric bcopy(s, bp, slen); 27560089Seric bp += slen; 27660089Seric } 27760089Seric else 27860089Seric { 27960089Seric while (--slen >= 0 && (c = *s++) != '\0') 28060089Seric { 28160089Seric if (c != '%') 28260089Seric { 28360089Seric pushc: 28460089Seric *bp++ = c; 28560089Seric continue; 28660089Seric } 28760089Seric if (--slen < 0 || (c = *s++) == '\0') 28860089Seric c = '%'; 28960089Seric if (c == '%') 29060089Seric goto pushc; 29160089Seric if (!(isascii(c) && isdigit(c))) 29260089Seric { 29360089Seric *bp++ = '%'; 29460089Seric goto pushc; 29560089Seric } 29663937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 29760089Seric continue; 29860089Seric if (*avp == NULL) 29960089Seric continue; 30060089Seric 30160089Seric /* transliterate argument into output string */ 30260089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 30360089Seric *bp++ = c; 30460089Seric } 30560089Seric } 30660089Seric if (map->map_app != NULL) 30760089Seric strcpy(bp, map->map_app); 30860089Seric else 30960089Seric *bp = '\0'; 31060537Seric if (tTd(39, 1)) 311*67895Seric printf("map_rewrite => %s\n", buf); 312*67895Seric return buf; 31360089Seric } 31460089Seric /* 31560537Seric ** INITMAPS -- initialize for aliasing 31660537Seric ** 31760537Seric ** Parameters: 31860537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 31960537Seric ** e -- current envelope. 32060537Seric ** 32160537Seric ** Returns: 32260537Seric ** none. 32360537Seric ** 32460537Seric ** Side Effects: 32560537Seric ** initializes aliases: 32660537Seric ** if NDBM: opens the database. 32760537Seric ** if ~NDBM: reads the aliases into the symbol table. 32860537Seric */ 32960537Seric 33060537Seric initmaps(rebuild, e) 33160537Seric bool rebuild; 33260537Seric register ENVELOPE *e; 33360537Seric { 33460537Seric extern void map_init(); 33560537Seric 33664671Seric #ifdef XDEBUG 33764671Seric checkfd012("entering initmaps"); 33864671Seric #endif 33960537Seric CurEnv = e; 34065085Seric if (rebuild) 34165085Seric { 34265085Seric stabapply(map_init, 1); 34365085Seric stabapply(map_init, 2); 34465085Seric } 34565085Seric else 34665085Seric { 34765085Seric stabapply(map_init, 0); 34865085Seric } 34964671Seric #ifdef XDEBUG 35064671Seric checkfd012("exiting initmaps"); 35164671Seric #endif 35260537Seric } 35360537Seric 35460537Seric void 35560537Seric map_init(s, rebuild) 35660537Seric register STAB *s; 35760537Seric int rebuild; 35860537Seric { 35960537Seric register MAP *map; 36060537Seric 36160537Seric /* has to be a map */ 36260537Seric if (s->s_type != ST_MAP) 36360537Seric return; 36460537Seric 36560537Seric map = &s->s_map; 36660537Seric if (!bitset(MF_VALID, map->map_mflags)) 36760537Seric return; 36860537Seric 36960537Seric if (tTd(38, 2)) 37067726Seric printf("map_init(%s:%s, %s, %d)\n", 37164690Seric map->map_class->map_cname == NULL ? "NULL" : 37264690Seric map->map_class->map_cname, 37367726Seric map->map_mname == NULL ? "NULL" : map->map_mname, 37465085Seric map->map_file == NULL ? "NULL" : map->map_file, 37565085Seric rebuild); 37660537Seric 37765085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && 37865085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) 37965085Seric { 38065085Seric if (tTd(38, 3)) 38165085Seric printf("\twrong pass\n"); 38265085Seric return; 38365085Seric } 38465085Seric 38560537Seric /* if already open, close it (for nested open) */ 38660537Seric if (bitset(MF_OPEN, map->map_mflags)) 38760537Seric { 38860537Seric map->map_class->map_close(map); 38960537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 39060537Seric } 39160537Seric 39265085Seric if (rebuild == 2) 39360537Seric { 39465085Seric rebuildaliases(map, FALSE); 39560537Seric } 39660537Seric else 39760537Seric { 39860537Seric if (map->map_class->map_open(map, O_RDONLY)) 39960537Seric { 40060537Seric if (tTd(38, 4)) 40167726Seric printf("\t%s:%s %s: valid\n", 40264690Seric map->map_class->map_cname == NULL ? "NULL" : 40364690Seric map->map_class->map_cname, 40467726Seric map->map_mname == NULL ? "NULL" : 40567726Seric map->map_mname, 40664690Seric map->map_file == NULL ? "NULL" : 40764690Seric map->map_file); 40860537Seric map->map_mflags |= MF_OPEN; 40960537Seric } 41060537Seric else if (tTd(38, 4)) 41167726Seric printf("\t%s:%s %s: invalid: %s\n", 41264690Seric map->map_class->map_cname == NULL ? "NULL" : 41364690Seric map->map_class->map_cname, 41467726Seric map->map_mname == NULL ? "NULL" : 41567726Seric map->map_mname, 41664690Seric map->map_file == NULL ? "NULL" : 41764690Seric map->map_file, 41860537Seric errstring(errno)); 41960537Seric } 42060537Seric } 42160537Seric /* 42260089Seric ** NDBM modules 42360089Seric */ 42460089Seric 42560089Seric #ifdef NDBM 42660089Seric 42760089Seric /* 42860089Seric ** DBM_MAP_OPEN -- DBM-style map open 42960089Seric */ 43060089Seric 43160089Seric bool 43260089Seric ndbm_map_open(map, mode) 43360089Seric MAP *map; 43460089Seric int mode; 43560089Seric { 43664284Seric register DBM *dbm; 43764284Seric struct stat st; 43860089Seric 43960537Seric if (tTd(38, 2)) 44067726Seric printf("ndbm_map_open(%s, %s, %d)\n", 44167726Seric map->map_mname, map->map_file, mode); 44260089Seric 44360207Seric if (mode == O_RDWR) 44460207Seric mode |= O_CREAT|O_TRUNC; 44560207Seric 44660089Seric /* open the database */ 44760089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 44856822Seric if (dbm == NULL) 44956822Seric { 45064718Seric #ifdef MAYBENEXTRELEASE 45164718Seric if (aliaswait(map, ".pag", FALSE)) 45264718Seric return TRUE; 45364718Seric #endif 45460207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 45556836Seric syserr("Cannot open DBM database %s", map->map_file); 45656822Seric return FALSE; 45756822Seric } 45860089Seric map->map_db1 = (void *) dbm; 45964964Seric if (mode == O_RDONLY) 46064964Seric { 46164964Seric if (bitset(MF_ALIAS, map->map_mflags) && 46264964Seric !aliaswait(map, ".pag", TRUE)) 46364718Seric return FALSE; 46464964Seric } 46564964Seric else 46664964Seric { 46764964Seric int fd; 46864964Seric 46964964Seric /* exclusive lock for duration of rebuild */ 47064964Seric fd = dbm_dirfno((DBM *) map->map_db1); 47164964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 47264964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 47364964Seric map->map_mflags |= MF_LOCKED; 47464964Seric } 47564718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 47664284Seric map->map_mtime = st.st_mtime; 47756822Seric return TRUE; 47856822Seric } 47960089Seric 48060089Seric 48160089Seric /* 48256822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 48356822Seric */ 48456822Seric 48556822Seric char * 48660089Seric ndbm_map_lookup(map, name, av, statp) 48756822Seric MAP *map; 48860089Seric char *name; 48956822Seric char **av; 49059084Seric int *statp; 49156822Seric { 49256822Seric datum key, val; 49364373Seric int fd; 49460089Seric char keybuf[MAXNAME + 1]; 49556822Seric 49660537Seric if (tTd(38, 20)) 49767726Seric printf("ndbm_map_lookup(%s, %s)\n", 49867726Seric map->map_mname, name); 49960089Seric 50060089Seric key.dptr = name; 50160089Seric key.dsize = strlen(name); 50260207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 50357014Seric { 50460089Seric if (key.dsize > sizeof keybuf - 1) 50560089Seric key.dsize = sizeof keybuf - 1; 50660089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 50760089Seric makelower(keybuf); 50860089Seric key.dptr = keybuf; 50957014Seric } 51064373Seric fd = dbm_dirfno((DBM *) map->map_db1); 51164388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 51264373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 51363753Seric val.dptr = NULL; 51463753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 51563753Seric { 51663753Seric val = dbm_fetch((DBM *) map->map_db1, key); 51763753Seric if (val.dptr != NULL) 51863753Seric map->map_mflags &= ~MF_TRY1NULL; 51963753Seric } 52063753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 52163753Seric { 52256822Seric key.dsize++; 52363753Seric val = dbm_fetch((DBM *) map->map_db1, key); 52463753Seric if (val.dptr != NULL) 52563753Seric map->map_mflags &= ~MF_TRY0NULL; 52663753Seric } 52764388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 52864373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 52956822Seric if (val.dptr == NULL) 53056822Seric return NULL; 53160207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 53263753Seric return map_rewrite(map, name, strlen(name), NULL); 53363753Seric else 53463753Seric return map_rewrite(map, val.dptr, val.dsize, av); 53556822Seric } 53656822Seric 53756822Seric 53856822Seric /* 53960089Seric ** DBM_MAP_STORE -- store a datum in the database 54056822Seric */ 54156822Seric 54260089Seric void 54360089Seric ndbm_map_store(map, lhs, rhs) 54460089Seric register MAP *map; 54560089Seric char *lhs; 54660089Seric char *rhs; 54760089Seric { 54860089Seric datum key; 54960089Seric datum data; 55060089Seric int stat; 55160089Seric 55260537Seric if (tTd(38, 12)) 55367726Seric printf("ndbm_map_store(%s, %s, %s)\n", 55467726Seric map->map_mname, lhs, rhs); 55560089Seric 55660089Seric key.dsize = strlen(lhs); 55760089Seric key.dptr = lhs; 55860089Seric 55960089Seric data.dsize = strlen(rhs); 56060089Seric data.dptr = rhs; 56160089Seric 56260207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 56360089Seric { 56460089Seric key.dsize++; 56560089Seric data.dsize++; 56660089Seric } 56760089Seric 56860089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 56960089Seric if (stat > 0) 57060089Seric { 57160089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 57260089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 57360089Seric } 57460089Seric if (stat != 0) 57560089Seric syserr("readaliases: dbm put (%s)", lhs); 57660089Seric } 57760089Seric 57860089Seric 57960089Seric /* 58060207Seric ** NDBM_MAP_CLOSE -- close the database 58160089Seric */ 58260089Seric 58360089Seric void 58460089Seric ndbm_map_close(map) 58560089Seric register MAP *map; 58660089Seric { 58766773Seric if (tTd(38, 9)) 58867726Seric printf("ndbm_map_close(%s, %s, %x)\n", 58967726Seric map->map_mname, map->map_file, map->map_mflags); 59066773Seric 59160207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 59260089Seric { 59364250Seric #ifdef NIS 59464075Seric bool inclnull; 59560089Seric char buf[200]; 59660089Seric 59764075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 59864075Seric map->map_mflags &= ~MF_INCLNULL; 59964075Seric 60060089Seric (void) sprintf(buf, "%010ld", curtime()); 60160089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 60260089Seric 60364941Seric (void) gethostname(buf, sizeof buf); 60460089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 60564075Seric 60664075Seric if (inclnull) 60764075Seric map->map_mflags |= MF_INCLNULL; 60860089Seric #endif 60960089Seric 61060089Seric /* write out the distinguished alias */ 61160089Seric ndbm_map_store(map, "@", "@"); 61260089Seric } 61360089Seric dbm_close((DBM *) map->map_db1); 61460089Seric } 61560089Seric 61660089Seric #endif 61760089Seric /* 61860582Seric ** NEWDB (Hash and BTree) Modules 61960089Seric */ 62060089Seric 62160089Seric #ifdef NEWDB 62260089Seric 62360089Seric /* 62460582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 62560582Seric ** 62660582Seric ** These do rather bizarre locking. If you can lock on open, 62760582Seric ** do that to avoid the condition of opening a database that 62860582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 62960582Seric ** there will be a race condition. If opening for read-only, 63060582Seric ** we immediately release the lock to avoid freezing things up. 63160582Seric ** We really ought to hold the lock, but guarantee that we won't 63260582Seric ** be pokey about it. That's hard to do. 63360089Seric */ 63460089Seric 63556822Seric bool 63660089Seric bt_map_open(map, mode) 63756822Seric MAP *map; 63860089Seric int mode; 63956822Seric { 64056822Seric DB *db; 64160228Seric int i; 64260582Seric int omode; 64364373Seric int fd; 64464284Seric struct stat st; 64560089Seric char buf[MAXNAME]; 64656822Seric 64760537Seric if (tTd(38, 2)) 64867726Seric printf("bt_map_open(%s, %s, %d)\n", 64967726Seric map->map_mname, map->map_file, mode); 65060089Seric 65160582Seric omode = mode; 65260582Seric if (omode == O_RDWR) 65360582Seric { 65460582Seric omode |= O_CREAT|O_TRUNC; 65565830Seric #if defined(O_EXLOCK) && HASFLOCK 65660582Seric omode |= O_EXLOCK; 65766843Seric # if !OLD_NEWDB 65860582Seric } 65960582Seric else 66060582Seric { 66160582Seric omode |= O_SHLOCK; 66260582Seric # endif 66360582Seric #endif 66460582Seric } 66560207Seric 66660228Seric (void) strcpy(buf, map->map_file); 66760228Seric i = strlen(buf); 66860228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 66960228Seric (void) strcat(buf, ".db"); 67060582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 67156822Seric if (db == NULL) 67256822Seric { 67364718Seric #ifdef MAYBENEXTRELEASE 67464718Seric if (aliaswait(map, ".db", FALSE)) 67564718Seric return TRUE; 67664718Seric #endif 67760207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 67856836Seric syserr("Cannot open BTREE database %s", map->map_file); 67956822Seric return FALSE; 68056822Seric } 68167173Seric #if !OLD_NEWDB 68264373Seric fd = db->fd(db); 68367187Seric # if HASFLOCK 68467187Seric # if !defined(O_EXLOCK) 68564373Seric if (mode == O_RDWR && fd >= 0) 68664388Seric { 68764388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 68864388Seric map->map_mflags |= MF_LOCKED; 68964388Seric } 69067187Seric # else 69164373Seric if (mode == O_RDONLY && fd >= 0) 69264373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 69364388Seric else 69464388Seric map->map_mflags |= MF_LOCKED; 69567187Seric # endif 69660582Seric # endif 69760582Seric #endif 69860585Seric 69960585Seric /* try to make sure that at least the database header is on disk */ 70060585Seric if (mode == O_RDWR) 70166843Seric #if OLD_NEWDB 70264373Seric (void) db->sync(db); 70364373Seric #else 70460585Seric (void) db->sync(db, 0); 70560585Seric 70664373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 70764284Seric map->map_mtime = st.st_mtime; 70864284Seric #endif 70964284Seric 71060089Seric map->map_db2 = (void *) db; 71160207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 71264718Seric if (!aliaswait(map, ".db", TRUE)) 71364718Seric return FALSE; 71456822Seric return TRUE; 71556822Seric } 71656822Seric 71756822Seric 71856822Seric /* 71956822Seric ** HASH_MAP_INIT -- HASH-style map initialization 72056822Seric */ 72156822Seric 72256822Seric bool 72360089Seric hash_map_open(map, mode) 72456822Seric MAP *map; 72560089Seric int mode; 72656822Seric { 72756822Seric DB *db; 72860228Seric int i; 72960582Seric int omode; 73064373Seric int fd; 73164284Seric struct stat st; 73260089Seric char buf[MAXNAME]; 73356822Seric 73460537Seric if (tTd(38, 2)) 73567726Seric printf("hash_map_open(%s, %s, %d)\n", 73667726Seric map->map_mname, map->map_file, mode); 73760089Seric 73860582Seric omode = mode; 73960582Seric if (omode == O_RDWR) 74060582Seric { 74160582Seric omode |= O_CREAT|O_TRUNC; 74265830Seric #if defined(O_EXLOCK) && HASFLOCK 74360582Seric omode |= O_EXLOCK; 74466843Seric # if !OLD_NEWDB 74560582Seric } 74660582Seric else 74760582Seric { 74860582Seric omode |= O_SHLOCK; 74960582Seric # endif 75060582Seric #endif 75160582Seric } 75260207Seric 75360228Seric (void) strcpy(buf, map->map_file); 75460228Seric i = strlen(buf); 75560228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 75660228Seric (void) strcat(buf, ".db"); 75760582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 75856822Seric if (db == NULL) 75956822Seric { 76064718Seric #ifdef MAYBENEXTRELEASE 76164718Seric if (aliaswait(map, ".db", FALSE)) 76264718Seric return TRUE; 76364718Seric #endif 76460207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 76556836Seric syserr("Cannot open HASH database %s", map->map_file); 76656822Seric return FALSE; 76756822Seric } 76867173Seric #if !OLD_NEWDB 76964373Seric fd = db->fd(db); 77067187Seric # if HASFLOCK 77167187Seric # if !defined(O_EXLOCK) 77264373Seric if (mode == O_RDWR && fd >= 0) 77364388Seric { 77464388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 77564388Seric map->map_mflags |= MF_LOCKED; 77664388Seric } 77767187Seric # else 77864373Seric if (mode == O_RDONLY && fd >= 0) 77964373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 78064388Seric else 78164388Seric map->map_mflags |= MF_LOCKED; 78267187Seric # endif 78360582Seric # endif 78460582Seric #endif 78560585Seric 78660585Seric /* try to make sure that at least the database header is on disk */ 78760585Seric if (mode == O_RDWR) 78866843Seric #if OLD_NEWDB 78964373Seric (void) db->sync(db); 79064373Seric #else 79160585Seric (void) db->sync(db, 0); 79260585Seric 79364373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 79464284Seric map->map_mtime = st.st_mtime; 79564284Seric #endif 79664284Seric 79760089Seric map->map_db2 = (void *) db; 79860207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 79964718Seric if (!aliaswait(map, ".db", TRUE)) 80064718Seric return FALSE; 80156822Seric return TRUE; 80256822Seric } 80356822Seric 80456822Seric 80556822Seric /* 80656822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 80756822Seric */ 80856822Seric 80956822Seric char * 81060089Seric db_map_lookup(map, name, av, statp) 81156822Seric MAP *map; 81260089Seric char *name; 81356822Seric char **av; 81459084Seric int *statp; 81556822Seric { 81656822Seric DBT key, val; 81760422Seric register DB *db = (DB *) map->map_db2; 81860422Seric int st; 81960422Seric int saveerrno; 82064373Seric int fd; 82160089Seric char keybuf[MAXNAME + 1]; 82256822Seric 82360537Seric if (tTd(38, 20)) 82467726Seric printf("db_map_lookup(%s, %s)\n", 82567726Seric map->map_mname, name); 82660089Seric 82760089Seric key.size = strlen(name); 82860089Seric if (key.size > sizeof keybuf - 1) 82960089Seric key.size = sizeof keybuf - 1; 83060089Seric key.data = keybuf; 83160089Seric bcopy(name, keybuf, key.size + 1); 83260207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 83360089Seric makelower(keybuf); 83466843Seric #if !OLD_NEWDB 83564388Seric fd = db->fd(db); 83664388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 83764388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 83860422Seric #endif 83963753Seric st = 1; 84063753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 84163753Seric { 84263753Seric st = db->get(db, &key, &val, 0); 84363753Seric if (st == 0) 84463753Seric map->map_mflags &= ~MF_TRY1NULL; 84563753Seric } 84663753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 84763753Seric { 84863753Seric key.size++; 84963753Seric st = db->get(db, &key, &val, 0); 85063753Seric if (st == 0) 85163753Seric map->map_mflags &= ~MF_TRY0NULL; 85263753Seric } 85360422Seric saveerrno = errno; 85466843Seric #if !OLD_NEWDB 85564388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 85664373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 85760422Seric #endif 85860422Seric if (st != 0) 85960422Seric { 86060422Seric errno = saveerrno; 86160422Seric if (st < 0) 86260422Seric syserr("db_map_lookup: get (%s)", name); 86356822Seric return NULL; 86460422Seric } 86560207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 86663753Seric return map_rewrite(map, name, strlen(name), NULL); 86763753Seric else 86863753Seric return map_rewrite(map, val.data, val.size, av); 86956822Seric } 87056822Seric 87160089Seric 87260089Seric /* 87360089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 87456822Seric */ 87556822Seric 87660089Seric void 87760089Seric db_map_store(map, lhs, rhs) 87860089Seric register MAP *map; 87960089Seric char *lhs; 88060089Seric char *rhs; 88156822Seric { 88260089Seric int stat; 88360089Seric DBT key; 88460089Seric DBT data; 88560089Seric register DB *db = map->map_db2; 88656822Seric 88760537Seric if (tTd(38, 20)) 88867726Seric printf("db_map_store(%s, %s, %s)\n", 88967726Seric map->map_mname, lhs, rhs); 89060089Seric 89160089Seric key.size = strlen(lhs); 89260089Seric key.data = lhs; 89360089Seric 89460089Seric data.size = strlen(rhs); 89560089Seric data.data = rhs; 89660089Seric 89760207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 89856822Seric { 89960089Seric key.size++; 90060089Seric data.size++; 90160089Seric } 90256836Seric 90360089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 90460089Seric if (stat > 0) 90560089Seric { 90660089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 90760089Seric stat = db->put(db, &key, &data, 0); 90860089Seric } 90960089Seric if (stat != 0) 91060089Seric syserr("readaliases: db put (%s)", lhs); 91160089Seric } 91256836Seric 91356847Seric 91460089Seric /* 91560089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 91660089Seric */ 91760089Seric 91860089Seric void 91960089Seric db_map_close(map) 92060089Seric MAP *map; 92160089Seric { 92260089Seric register DB *db = map->map_db2; 92360089Seric 92460537Seric if (tTd(38, 9)) 92567726Seric printf("db_map_close(%s, %s, %x)\n", 92667726Seric map->map_mname, map->map_file, map->map_mflags); 92760089Seric 92860207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 92958804Seric { 93060089Seric /* write out the distinguished alias */ 93160089Seric db_map_store(map, "@", "@"); 93258804Seric } 93358963Seric 93460089Seric if (db->close(db) != 0) 93560089Seric syserr("readaliases: db close failure"); 93656822Seric } 93757208Seric 93860089Seric #endif 93960089Seric /* 94060089Seric ** NIS Modules 94160089Seric */ 94260089Seric 94360089Seric # ifdef NIS 94460089Seric 94564369Seric # ifndef YPERR_BUSY 94664369Seric # define YPERR_BUSY 16 94764369Seric # endif 94864369Seric 94957208Seric /* 95060089Seric ** NIS_MAP_OPEN -- open DBM map 95157208Seric */ 95257208Seric 95357208Seric bool 95460089Seric nis_map_open(map, mode) 95557208Seric MAP *map; 95660089Seric int mode; 95757208Seric { 95857216Seric int yperr; 95960215Seric register char *p; 96060215Seric auto char *vp; 96160215Seric auto int vsize; 96257216Seric char *master; 96357216Seric 96460537Seric if (tTd(38, 2)) 96567726Seric printf("nis_map_open(%s, %s)\n", 96667726Seric map->map_mname, map->map_file); 96760089Seric 96860207Seric if (mode != O_RDONLY) 96960207Seric { 97064650Seric /* issue a pseudo-error message */ 97164650Seric #ifdef ENOSYS 97264650Seric errno = ENOSYS; 97364650Seric #else 97464650Seric # ifdef EFTYPE 97564650Seric errno = EFTYPE; 97664650Seric # else 97764650Seric errno = ENXIO; 97864650Seric # endif 97964650Seric #endif 98060207Seric return FALSE; 98160207Seric } 98260207Seric 98360089Seric p = strchr(map->map_file, '@'); 98460089Seric if (p != NULL) 98560089Seric { 98660089Seric *p++ = '\0'; 98760089Seric if (*p != '\0') 98860089Seric map->map_domain = p; 98960089Seric } 99060215Seric 99160089Seric if (*map->map_file == '\0') 99260089Seric map->map_file = "mail.aliases"; 99360089Seric 99466157Seric if (map->map_domain == NULL) 99566157Seric { 99666157Seric yperr = yp_get_default_domain(&map->map_domain); 99766157Seric if (yperr != 0) 99866157Seric { 99966744Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 100066744Seric syserr("NIS map %s specified, but NIS not running\n", 100166744Seric map->map_file); 100266157Seric return FALSE; 100366157Seric } 100466157Seric } 100566157Seric 100660215Seric /* check to see if this map actually exists */ 100760089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 100860089Seric &vp, &vsize); 100960537Seric if (tTd(38, 10)) 101060089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 101160089Seric map->map_domain, map->map_file, yperr_string(yperr)); 101260089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 101360089Seric return TRUE; 101460215Seric 101560215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 101660215Seric syserr("Cannot bind to domain %s: %s", map->map_domain, 101760215Seric yperr_string(yperr)); 101860215Seric 101960089Seric return FALSE; 102060089Seric } 102160089Seric 102260089Seric 102360089Seric /* 102457208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 102557208Seric */ 102657208Seric 102757208Seric char * 102860089Seric nis_map_lookup(map, name, av, statp) 102957208Seric MAP *map; 103060089Seric char *name; 103157208Seric char **av; 103259084Seric int *statp; 103357208Seric { 103457208Seric char *vp; 103557642Seric auto int vsize; 103659274Seric int buflen; 103760215Seric int yperr; 103860089Seric char keybuf[MAXNAME + 1]; 103957208Seric 104060537Seric if (tTd(38, 20)) 104167726Seric printf("nis_map_lookup(%s, %s)\n", 104267726Seric map->map_mname, name); 104360089Seric 104460089Seric buflen = strlen(name); 104560089Seric if (buflen > sizeof keybuf - 1) 104660089Seric buflen = sizeof keybuf - 1; 104760089Seric bcopy(name, keybuf, buflen + 1); 104860207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 104960089Seric makelower(keybuf); 105063753Seric yperr = YPERR_KEY; 105163753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 105263753Seric { 105363753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 105463753Seric &vp, &vsize); 105563753Seric if (yperr == 0) 105663753Seric map->map_mflags &= ~MF_TRY1NULL; 105763753Seric } 105863753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 105963753Seric { 106059274Seric buflen++; 106163753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 106263753Seric &vp, &vsize); 106363753Seric if (yperr == 0) 106463753Seric map->map_mflags &= ~MF_TRY0NULL; 106563753Seric } 106660089Seric if (yperr != 0) 106760089Seric { 106860089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 106960215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 107057208Seric return NULL; 107160089Seric } 107260207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 107363753Seric return map_rewrite(map, name, strlen(name), NULL); 107463753Seric else 107563753Seric return map_rewrite(map, vp, vsize, av); 107657208Seric } 107757208Seric 107867726Seric #endif 107957208Seric /* 108067848Seric ** NISPLUS Modules 108167848Seric ** 108267848Seric ** This code donated by Sun Microsystems. 108367848Seric */ 108467848Seric 108567848Seric #ifdef NISPLUS 108667848Seric 108767848Seric #undef NIS /* symbol conflict in nis.h */ 108867848Seric #include <rpcsvc/nis.h> 108967848Seric #include <rpcsvc/nislib.h> 109067848Seric 109167848Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 109267848Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 109367848Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 109467848Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 109567848Seric 109667848Seric /* 109767848Seric ** NISPLUS_MAP_OPEN -- open nisplus table 109867848Seric */ 109967848Seric 110067848Seric bool 110167848Seric nisplus_map_open(map, mode) 110267848Seric MAP *map; 110367848Seric int mode; 110467848Seric { 110567848Seric register char *p; 110667848Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 110767848Seric nis_result *res = NULL; 110867848Seric u_int objs_len; 110967848Seric nis_object *obj_ptr; 111067848Seric int retry_cnt, max_col, i; 111167848Seric 111267848Seric if (tTd(38, 2)) 111367848Seric printf("nisplus_map_open(%s, %s, %d)\n", 111467848Seric map->map_mname, map->map_file, mode); 111567848Seric 111667848Seric if (mode != O_RDONLY) 111767848Seric { 111867848Seric errno = ENODEV; 111967848Seric return FALSE; 112067848Seric } 112167848Seric 112267848Seric if (*map->map_file == '\0') 112367848Seric map->map_file = "mail_aliases.org_dir"; 112467848Seric 112567848Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 112667848Seric { 112767848Seric /* set default NISPLUS Domain to $m */ 112867848Seric extern char *nisplus_default_domain(); 112967848Seric 113067848Seric map->map_domain = newstr(nisplus_default_domain()); 113167848Seric if (tTd(38, 2)) 113267848Seric printf("nisplus_map_open(%s): using domain %s\n", 113367848Seric map->map_file, map->map_domain); 113467848Seric } 113567848Seric if (!PARTIAL_NAME(map->map_file)) 113667848Seric map->map_domain = newstr(""); 113767848Seric 113867848Seric /* check to see if this map actually exists */ 113967848Seric if (PARTIAL_NAME(map->map_file)) 114067848Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 114167848Seric else 114267848Seric strcpy(qbuf, map->map_file); 114367848Seric 114467848Seric retry_cnt = 0; 114567848Seric while (res == NULL || res->status != NIS_SUCCESS) 114667848Seric { 114767848Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 114867848Seric switch (res->status) 114967848Seric { 115067848Seric case NIS_SUCCESS: 115167848Seric case NIS_TRYAGAIN: 115267848Seric case NIS_RPCERROR: 115367848Seric case NIS_NAMEUNREACHABLE: 115467848Seric break; 115567848Seric 115667848Seric default: /* all other nisplus errors */ 115767848Seric #if 0 115867848Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 115967848Seric syserr("Cannot find table %s.%s: %s", 116067848Seric map->map_file, map->map_domain, 116167848Seric nis_sperrno(res->status)); 116267848Seric #endif 116367848Seric errno = EBADR; 116467848Seric return FALSE; 116567848Seric } 116667848Seric sleep(2); /* try not to overwhelm hosed server */ 116767848Seric if (retry_cnt++ > 4) 116867848Seric { 116967848Seric errno = EBADR; 117067848Seric return FALSE; 117167848Seric } 117267848Seric } 117367848Seric 117467848Seric if (NIS_RES_NUMOBJ(res) != 1 || 117567848Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 117667848Seric { 117767848Seric if (tTd(38, 10)) 117867848Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 117967848Seric #if 0 118067848Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 118167848Seric syserr("%s.%s: %s is not a table", 118267848Seric map->map_file, map->map_domain, 118367848Seric nis_sperrno(res->status)); 118467848Seric #endif 118567848Seric errno = EBADR; 118667848Seric return FALSE; 118767848Seric } 118867848Seric /* default key column is column 0 */ 118967848Seric if (map->map_keycolnm == NULL) 119067848Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 119167848Seric 119267848Seric max_col = COL_MAX(res); 119367848Seric 119467848Seric /* verify the key column exist */ 119567848Seric for (i=0; i< max_col; i++) 119667848Seric { 119767848Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 119867848Seric break; 119967848Seric } 120067848Seric if (i == max_col) 120167848Seric { 120267848Seric if (tTd(38, 2)) 120367848Seric printf("nisplus_map_open(%s): can not find key column %s\n", 120467848Seric map->map_file, map->map_keycolnm); 120567848Seric errno = EBADR; 120667848Seric return FALSE; 120767848Seric } 120867848Seric 120967848Seric /* default value column is the last column */ 121067848Seric if (map->map_valcolnm == NULL) 121167848Seric { 121267848Seric map->map_valcolno = max_col - 1; 121367848Seric return TRUE; 121467848Seric } 121567848Seric 121667848Seric for (i=0; i< max_col; i++) 121767848Seric { 121867848Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 121967848Seric { 122067848Seric map->map_valcolno = i; 122167848Seric return TRUE; 122267848Seric } 122367848Seric } 122467848Seric 122567848Seric if (tTd(38, 2)) 122667848Seric printf("nisplus_map_open(%s): can not find column %s\n", 122767848Seric map->map_file, map->map_keycolnm); 122867848Seric errno = EBADR; 122967848Seric return FALSE; 123067848Seric } 123167848Seric 123267848Seric 123367848Seric /* 123467848Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 123567848Seric */ 123667848Seric 123767848Seric char * 123867848Seric nisplus_map_lookup(map, name, av, statp) 123967848Seric MAP *map; 124067848Seric char *name; 124167848Seric char **av; 124267848Seric int *statp; 124367848Seric { 124467848Seric char *vp; 124567848Seric auto int vsize; 124667848Seric int buflen; 124767848Seric char search_key[MAXNAME + 1]; 124867848Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 124967848Seric nis_result *result; 125067848Seric 125167848Seric if (tTd(38, 20)) 125267848Seric printf("nisplus_map_lookup(%s, %s)\n", 125367848Seric map->map_mname, name); 125467848Seric 125567848Seric if (!bitset(MF_OPEN, map->map_mflags)) 125667848Seric { 125767848Seric if (nisplus_map_open(map, O_RDONLY)) 125867848Seric map->map_mflags |= MF_OPEN; 125967848Seric else 126067848Seric { 126167848Seric *statp = EX_UNAVAILABLE; 126267848Seric return NULL; 126367848Seric } 126467848Seric } 126567848Seric 126667848Seric buflen = strlen(name); 126767848Seric if (buflen > sizeof search_key - 1) 126867848Seric buflen = sizeof search_key - 1; 126967848Seric bcopy(name, search_key, buflen + 1); 127067848Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 127167848Seric makelower(search_key); 127267848Seric 127367848Seric /* construct the query */ 127467848Seric if (PARTIAL_NAME(map->map_file)) 127567848Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 127667848Seric search_key, map->map_file, map->map_domain); 127767848Seric else 127867848Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 127967848Seric search_key, map->map_file); 128067848Seric 128167848Seric if (tTd(38, 20)) 128267848Seric printf("qbuf=%s\n", qbuf); 128367848Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 128467848Seric if (result->status == NIS_SUCCESS) 128567848Seric { 128667848Seric int count; 128767848Seric char *str; 128867848Seric 128967848Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 129067848Seric { 129167848Seric if (LogLevel > 10) 129267848Seric syslog(LOG_WARNING, 129367848Seric "%s:Lookup error, expected 1 entry, got (%d)", 129467848Seric map->map_file, count); 129567848Seric 129667848Seric /* ignore second entry */ 129767848Seric if (tTd(38, 20)) 129867848Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 129967848Seric name, count); 130067848Seric } 130167848Seric 130267848Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 130367848Seric /* set the length of the result */ 130467848Seric if (vp == NULL) 130567848Seric vp = ""; 130667848Seric vsize = strlen(vp); 130767848Seric if (tTd(38, 20)) 130867848Seric printf("nisplus_map_lookup(%s), found %s\n", 130967848Seric name, vp); 131067848Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 131167848Seric str = map_rewrite(map, name, strlen(name), NULL); 131267848Seric else 131367848Seric str = map_rewrite(map, vp, vsize, av); 131467848Seric nis_freeresult(result); 131567848Seric #ifdef MAP_EXIT_STAT 131667848Seric *statp = EX_OK; 131767848Seric #endif 131867848Seric return str; 131967848Seric } 132067848Seric else 132167848Seric { 132267848Seric #ifdef MAP_EXIT_STAT 132367848Seric if (result->status == NIS_NOTFOUND) 132467848Seric *statp = EX_NOTFOUND; 132567848Seric else if (result->status == NIS_TRYAGAIN) 132667848Seric *statp = EX_TEMPFAIL; 132767848Seric else 132867848Seric { 132967848Seric *statp = EX_UNAVAILABLE; 133067848Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 133167848Seric } 133267848Seric #else 133367848Seric if ((result->status != NIS_NOTFOUND) && 133467848Seric (result->status != NIS_TRYAGAIN)) 133567848Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 133667848Seric #endif 133767848Seric } 133867848Seric if (tTd(38, 20)) 133967848Seric printf("nisplus_map_lookup(%s), failed\n", name); 134067848Seric nis_freeresult(result); 134167848Seric return NULL; 134267848Seric } 134367848Seric 134467848Seric 134567848Seric char * 134667848Seric nisplus_default_domain() 134767848Seric { 134867848Seric static char default_domain[MAXNAME] = ""; 134967848Seric nis_result *res = NULL; 135067848Seric char *p; 135167848Seric 135267848Seric if (default_domain[0] != '\0') 135367848Seric return(default_domain); 135467848Seric 135567848Seric if (VendorCode == VENDOR_SUN && ConfigLevel < 2) 135667848Seric { 135767848Seric /* for old config, user nis+ local directory */ 135867848Seric /* have to be backward compatible with bugs too :-( */ 135967848Seric p = nis_local_directory(); 136067848Seric strcpy(default_domain, p); 136167848Seric return default_domain; 136267848Seric } 136367848Seric 136467848Seric if ((p = macvalue('m', CurEnv)) == NULL) 136567848Seric { 136667848Seric p = nis_local_directory(); 136767848Seric strcpy(default_domain, p); 136867848Seric return default_domain; 136967848Seric } 137067848Seric 137167848Seric strcpy(default_domain, p); 137267848Seric if (PARTIAL_NAME(default_domain)) 137367848Seric strcat(default_domain, "."); 137467848Seric 137567848Seric res = nis_lookup(default_domain, FOLLOW_LINKS); 137667848Seric if (res->status == NIS_NOTFOUND) 137767848Seric { 137867848Seric p = nis_local_directory(); 137967848Seric strcpy(default_domain, p); 138067848Seric } 138167848Seric return(default_domain); 138267848Seric } 138367848Seric 138467848Seric #endif /* NISPLUS */ 138567848Seric /* 138667832Seric ** HESIOD Modules 138767832Seric ** 138867832Seric ** Only works for aliases (for now). 138967832Seric */ 139067832Seric 139167832Seric #ifdef HESIOD 139267832Seric 139367832Seric char * 139467832Seric hes_map_lookup(map, name, av, statp) 139567832Seric MAP *map; 139667832Seric char *name; 139767832Seric char **av; 139867832Seric int *statp; 139967832Seric { 140067832Seric struct hes_postoffice *pobox; 140167832Seric char keybuf[MAXNAME + 1]; 140267832Seric 140367832Seric if (tTd(38, 20)) 140467832Seric printf("hes_map_lookup(%s)\n", name); 140567832Seric 140667832Seric pobox = hes_getmailhost(name); 140767832Seric if (pobox == NULL) 140867832Seric return NULL; 140967832Seric 141067832Seric /* We only know how to deal with the SMTP types right now */ 141167832Seric if (strcmp(pobox->po_type, "SMTP") != 0 && 141267832Seric strcmp(pobox->po_type, "ESMTP") != 0) 141367832Seric return NULL; 141467832Seric 141567832Seric /* if just checking for a match, we are done */ 141667832Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 141767832Seric return map_rewrite(map, name, strlen(name), NULL); 141867832Seric 141967832Seric /* Do the rewriting with new values */ 142067832Seric if (strlen(pobox->po_name) + strlen(pobox->po_host) + 1 > sizeof keybuf) 142167848Seric { 142267848Seric *statp = EX_DATAERR; 142367832Seric return NULL; 142467848Seric } 142567832Seric (void) sprintf(keybuf, "%s@%s", pobox->po_name, pobox->po_host); 142667832Seric return map_rewrite(map, keybuf, strlen(keybuf), av); 142767832Seric } 142867832Seric 142967832Seric #endif 143067832Seric /* 143167842Seric ** NeXT NETINFO Modules 143267842Seric */ 143367842Seric 143467842Seric #ifdef NETINFO 143567842Seric 143667842Seric #define NETINFO_DEFAULT_DIR "/aliases" 143767842Seric #define NETINFO_DEFAULT_PROPERTY "members" 143867842Seric 143967842Seric 144067842Seric /* 144167842Seric ** NI_MAP_OPEN -- open NetInfo Aliases 144267842Seric */ 144367842Seric 144467848Seric bool 144567842Seric ni_map_open(map, mode) 144667842Seric MAP *map; 144767842Seric int mode; 144867842Seric { 144967842Seric char *p; 145067842Seric 145167842Seric if (tTd(38, 20)) 145267842Seric printf("ni_map_open: %s\n", map->map_file); 145367842Seric 145467842Seric p = strchr(map->map_file, '@'); 145567842Seric if (p != NULL) 145667842Seric { 145767842Seric *p++ = '\0'; 145867842Seric if (*p != '\0') 145967842Seric map->map_domain = p; 146067842Seric } 146167842Seric if (*map->map_file == '\0') 146267842Seric map->map_file = NETINFO_DEFAULT_DIR; 146367842Seric 146467842Seric if (map->map_domain == NULL) 146567842Seric map->map_domain = NETINFO_DEFAULT_PROPERTY; 146667842Seric 146767857Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 146867857Seric map->map_coldelim = ','; 146967842Seric 147067842Seric return TRUE; 147167842Seric } 147267842Seric 147367842Seric 147467842Seric /* 147567842Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 147667842Seric */ 147767842Seric 147867842Seric char * 147967842Seric ni_map_lookup(map, name, av, statp) 148067842Seric MAP *map; 148167842Seric char *name; 148267842Seric char **av; 148367842Seric int *statp; 148467842Seric { 148567842Seric char *res; 148667842Seric char *propval; 148767842Seric extern char *ni_propval(); 148867842Seric 148967842Seric if (tTd(38, 20)) 149067848Seric printf("ni_map_lookup(%s, %s)\n", 149167842Seric map->map_mname, name); 149267842Seric 149367842Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 149467842Seric map->map_valcolnm, map->map_coldelim); 149567842Seric 149667848Seric if (propval == NULL) 149767842Seric return NULL; 149867842Seric 149967842Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 150067842Seric res = map_rewrite(map, name, strlen(name), NULL); 150167842Seric else 150267842Seric res = map_rewrite(map, propval, strlen(propval), av); 150367842Seric free(propval); 150467842Seric return res; 150567842Seric } 150667842Seric 150767842Seric #endif 150867842Seric /* 150967848Seric ** TEXT (unindexed text file) Modules 151067848Seric ** 151167848Seric ** This code donated by Sun Microsystems. 151267848Seric */ 151367848Seric 151467848Seric 151567848Seric /* 151667848Seric ** TEXT_MAP_OPEN -- open text table 151767848Seric */ 151867848Seric 151967848Seric bool 152067848Seric text_map_open(map, mode) 152167848Seric MAP *map; 152267848Seric int mode; 152367848Seric { 152467848Seric struct stat sbuf; 152567848Seric 152667848Seric if (tTd(38, 2)) 152767848Seric printf("text_map_open(%s, %s, %d)\n", 152867848Seric map->map_mname, map->map_file, mode); 152967848Seric 153067848Seric if (mode != O_RDONLY) 153167848Seric { 153267848Seric errno = ENODEV; 153367848Seric return FALSE; 153467848Seric } 153567848Seric 153667848Seric if (*map->map_file == '\0') 153767848Seric { 153867848Seric if (tTd(38, 2)) 153967848Seric printf("text_map_open: file name required\n"); 154067848Seric return FALSE; 154167848Seric } 154267848Seric 154367848Seric if (map->map_file[0] != '/') 154467848Seric { 154567848Seric if (tTd(38, 2)) 154667848Seric printf("text_map_open(%s): file name must be fully qualified\n", 154767848Seric map->map_file); 154867848Seric return FALSE; 154967848Seric } 155067848Seric /* check to see if this map actually accessable */ 155167848Seric if (access(map->map_file, R_OK) <0) 155267848Seric return FALSE; 155367848Seric 155467848Seric /* check to see if this map actually exist */ 155567848Seric if (stat(map->map_file, &sbuf) <0) 155667848Seric { 155767848Seric if (tTd(38, 2)) 155867848Seric printf("text_map_open(%s): can not stat %s\n", 155967848Seric map->map_file, map->map_file); 156067848Seric return FALSE; 156167848Seric } 156267848Seric 156367848Seric if (!S_ISREG(sbuf.st_mode)) 156467848Seric { 156567848Seric if (tTd(38, 2)) 156667848Seric printf("text_map_open(%s): %s is not a file\n", 156767848Seric map->map_file, map->map_file); 156867848Seric return FALSE; 156967848Seric } 157067848Seric 157167848Seric if (map->map_keycolnm == NULL) 157267848Seric map->map_keycolno = 0; 157367848Seric else 157467848Seric { 157567848Seric if (!isdigit(*map->map_keycolnm)) 157667848Seric { 157767848Seric if (tTd(38, 2)) 157867848Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 157967848Seric map->map_file, map->map_keycolnm); 158067848Seric return FALSE; 158167848Seric } 158267848Seric map->map_keycolno = atoi(map->map_keycolnm); 158367848Seric } 158467848Seric 158567848Seric if (map->map_valcolnm == NULL) 158667848Seric map->map_valcolno = 0; 158767848Seric else 158867848Seric { 158967848Seric if (!isdigit(*map->map_valcolnm)) 159067848Seric { 159167848Seric if (tTd(38, 2)) 159267848Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 159367848Seric map->map_file, map->map_valcolnm); 159467848Seric return FALSE; 159567848Seric } 159667848Seric map->map_valcolno = atoi(map->map_valcolnm); 159767848Seric } 159867848Seric 159967848Seric if (map->map_coldelim == '\0') 160067848Seric map->map_coldelim = ':'; 160167848Seric 160267848Seric if (tTd(38, 2)) 160367848Seric { 160467848Seric printf("text_map_open(%s): delimiter = %c\n", 160567848Seric map->map_file, map->map_coldelim); 160667848Seric } 160767848Seric 160867848Seric return TRUE; 160967848Seric } 161067848Seric 161167848Seric 161267848Seric /* 161367848Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 161467848Seric */ 161567848Seric 161667848Seric char * 161767848Seric text_map_lookup(map, name, av, statp) 161867848Seric MAP *map; 161967848Seric char *name; 162067848Seric char **av; 162167848Seric int *statp; 162267848Seric { 162367848Seric char *vp; 162467848Seric auto int vsize; 162567848Seric int buflen; 162667848Seric char search_key[MAXNAME + 1]; 162767848Seric char linebuf[MAXLINE]; 162867848Seric FILE *f; 162967848Seric char buf[MAXNAME+1]; 163067848Seric char delim; 163167848Seric int key_idx; 163267848Seric bool found_it; 163367848Seric extern char *get_column(); 163467848Seric 163567848Seric 163667848Seric found_it = FALSE; 163767848Seric if (tTd(38, 20)) 163867848Seric printf("text_map_lookup(%s)\n", name); 163967848Seric 164067848Seric buflen = strlen(name); 164167848Seric if (buflen > sizeof search_key - 1) 164267848Seric buflen = sizeof search_key - 1; 164367848Seric bcopy(name, search_key, buflen + 1); 164467848Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 164567848Seric makelower(search_key); 164667848Seric 164767848Seric f = fopen(map->map_file, "r"); 164867848Seric if (f == NULL) 164967848Seric { 165067848Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 165167848Seric *statp = EX_UNAVAILABLE; 165267848Seric return NULL; 165367848Seric } 165467848Seric key_idx = map->map_keycolno; 165567848Seric delim = map->map_coldelim; 165667848Seric while (fgets(linebuf, MAXLINE, f)) 165767848Seric { 165867848Seric char *lf; 165967848Seric if (linebuf[0] == '#') 166067848Seric continue; /* skip comment line */ 166167848Seric if (lf = strchr(linebuf, '\n')) 166267848Seric *lf = '\0'; 166367848Seric if (!strcasecmp(search_key, 166467848Seric get_column(linebuf, key_idx, delim, buf))) 166567848Seric { 166667848Seric found_it = TRUE; 166767848Seric break; 166867848Seric } 166967848Seric } 167067848Seric fclose(f); 167167848Seric if (!found_it) 167267848Seric { 167367848Seric #ifdef MAP_EXIT_STAT 167467848Seric *statp = EX_NOTFOUND; 167567848Seric #endif 167667848Seric return(NULL); 167767848Seric } 167867848Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 167967848Seric vsize = strlen(vp); 168067848Seric #ifdef MAP_EXIT_STAT 168167848Seric *statp = EX_OK; 168267848Seric #endif 168367848Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 168467848Seric return map_rewrite(map, name, strlen(name), NULL); 168567848Seric else 168667848Seric return map_rewrite(map, vp, vsize, av); 168767848Seric } 168867848Seric /* 168960089Seric ** STAB (Symbol Table) Modules 169060089Seric */ 169160089Seric 169260089Seric 169360089Seric /* 169460207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 169560089Seric */ 169660089Seric 169760089Seric char * 169861707Seric stab_map_lookup(map, name, av, pstat) 169960089Seric register MAP *map; 170060089Seric char *name; 170161707Seric char **av; 170261707Seric int *pstat; 170360089Seric { 170460089Seric register STAB *s; 170560089Seric 170660537Seric if (tTd(38, 20)) 170767726Seric printf("stab_lookup(%s, %s)\n", 170867726Seric map->map_mname, name); 170960089Seric 171060089Seric s = stab(name, ST_ALIAS, ST_FIND); 171160089Seric if (s != NULL) 171260089Seric return (s->s_alias); 171360089Seric return (NULL); 171460089Seric } 171560089Seric 171660089Seric 171760089Seric /* 171860207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 171960089Seric */ 172060089Seric 172160089Seric void 172260089Seric stab_map_store(map, lhs, rhs) 172360089Seric register MAP *map; 172460089Seric char *lhs; 172560089Seric char *rhs; 172660089Seric { 172760089Seric register STAB *s; 172860089Seric 172960089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 173060089Seric s->s_alias = newstr(rhs); 173160089Seric } 173260089Seric 173360089Seric 173460089Seric /* 173560207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 173660207Seric ** 173760207Seric ** This is a wierd case -- it is only intended as a fallback for 173860207Seric ** aliases. For this reason, opens for write (only during a 173960207Seric ** "newaliases") always fails, and opens for read open the 174060207Seric ** actual underlying text file instead of the database. 174160089Seric */ 174260089Seric 174360089Seric bool 174460089Seric stab_map_open(map, mode) 174560089Seric register MAP *map; 174660089Seric int mode; 174760089Seric { 174863835Seric FILE *af; 174964284Seric struct stat st; 175063835Seric 175160537Seric if (tTd(38, 2)) 175267726Seric printf("stab_map_open(%s, %s)\n", 175367726Seric map->map_mname, map->map_file); 175460089Seric 175560089Seric if (mode != O_RDONLY) 175660207Seric { 175760207Seric errno = ENODEV; 175860089Seric return FALSE; 175960207Seric } 176060089Seric 176163835Seric af = fopen(map->map_file, "r"); 176263835Seric if (af == NULL) 176363835Seric return FALSE; 176467263Seric readaliases(map, af, FALSE, FALSE); 176564284Seric 176664284Seric if (fstat(fileno(af), &st) >= 0) 176764284Seric map->map_mtime = st.st_mtime; 176863835Seric fclose(af); 176963835Seric 177060089Seric return TRUE; 177160089Seric } 177260089Seric /* 177360089Seric ** Implicit Modules 177456822Seric ** 177560089Seric ** Tries several types. For back compatibility of aliases. 177656822Seric */ 177756822Seric 177860089Seric 177960089Seric /* 178060207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 178160089Seric */ 178260089Seric 178360089Seric char * 178460089Seric impl_map_lookup(map, name, av, pstat) 178560089Seric MAP *map; 178660089Seric char *name; 178756822Seric char **av; 178860089Seric int *pstat; 178956822Seric { 179060537Seric if (tTd(38, 20)) 179167726Seric printf("impl_map_lookup(%s, %s)\n", 179267726Seric map->map_mname, name); 179356822Seric 179460089Seric #ifdef NEWDB 179560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 179660089Seric return db_map_lookup(map, name, av, pstat); 179760089Seric #endif 179860089Seric #ifdef NDBM 179960207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 180060089Seric return ndbm_map_lookup(map, name, av, pstat); 180160089Seric #endif 180260089Seric return stab_map_lookup(map, name, av, pstat); 180360089Seric } 180460089Seric 180560089Seric /* 180660207Seric ** IMPL_MAP_STORE -- store in open databases 180760089Seric */ 180860089Seric 180960089Seric void 181060089Seric impl_map_store(map, lhs, rhs) 181160089Seric MAP *map; 181260089Seric char *lhs; 181360089Seric char *rhs; 181460089Seric { 181560089Seric #ifdef NEWDB 181660207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 181760089Seric db_map_store(map, lhs, rhs); 181860089Seric #endif 181960089Seric #ifdef NDBM 182060207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 182160089Seric ndbm_map_store(map, lhs, rhs); 182260089Seric #endif 182360089Seric stab_map_store(map, lhs, rhs); 182460089Seric } 182560089Seric 182660089Seric /* 182760089Seric ** IMPL_MAP_OPEN -- implicit database open 182860089Seric */ 182960089Seric 183060089Seric bool 183160089Seric impl_map_open(map, mode) 183260089Seric MAP *map; 183360089Seric int mode; 183460089Seric { 183560089Seric struct stat stb; 183660089Seric 183760537Seric if (tTd(38, 2)) 183867726Seric printf("impl_map_open(%s, %s, %d)\n", 183967726Seric map->map_mname, map->map_file, mode); 184060089Seric 184160089Seric if (stat(map->map_file, &stb) < 0) 184256822Seric { 184360089Seric /* no alias file at all */ 184464718Seric if (tTd(38, 3)) 184564718Seric printf("no map file\n"); 184660089Seric return FALSE; 184756822Seric } 184856822Seric 184960089Seric #ifdef NEWDB 185060207Seric map->map_mflags |= MF_IMPL_HASH; 185160089Seric if (hash_map_open(map, mode)) 185256822Seric { 185364250Seric #if defined(NDBM) && defined(NIS) 185460561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 185560207Seric #endif 185660207Seric return TRUE; 185760089Seric } 185860207Seric else 185960207Seric map->map_mflags &= ~MF_IMPL_HASH; 186060089Seric #endif 186160089Seric #ifdef NDBM 186260207Seric map->map_mflags |= MF_IMPL_NDBM; 186360089Seric if (ndbm_map_open(map, mode)) 186460089Seric { 186560089Seric return TRUE; 186660089Seric } 186760207Seric else 186860207Seric map->map_mflags &= ~MF_IMPL_NDBM; 186960089Seric #endif 187056822Seric 187164650Seric #if defined(NEWDB) || defined(NDBM) 187260089Seric if (Verbose) 187360089Seric message("WARNING: cannot open alias database %s", map->map_file); 187464964Seric #else 187564964Seric if (mode != O_RDONLY) 187664964Seric usrerr("Cannot rebuild aliases: no database format defined"); 187760207Seric #endif 187860089Seric 187960207Seric return stab_map_open(map, mode); 188056822Seric } 188160089Seric 188260207Seric 188360089Seric /* 188460207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 188560089Seric */ 188660089Seric 188760089Seric void 188860207Seric impl_map_close(map) 188960089Seric MAP *map; 189060089Seric { 189160089Seric #ifdef NEWDB 189260207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 189360089Seric { 189460207Seric db_map_close(map); 189560207Seric map->map_mflags &= ~MF_IMPL_HASH; 189660089Seric } 189760089Seric #endif 189860089Seric 189960089Seric #ifdef NDBM 190060207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 190160089Seric { 190260207Seric ndbm_map_close(map); 190360207Seric map->map_mflags &= ~MF_IMPL_NDBM; 190460089Seric } 190560089Seric #endif 190660089Seric } 190760207Seric /* 190867726Seric ** User map class. 190967726Seric ** 191067726Seric ** Provides access to the system password file. 191167726Seric */ 191267726Seric 191367726Seric /* 191467726Seric ** USER_MAP_OPEN -- open user map 191567726Seric ** 191667726Seric ** Really just binds field names to field numbers. 191767726Seric */ 191867726Seric 191967726Seric bool 192067726Seric user_map_open(map, mode) 192167726Seric MAP *map; 192267726Seric int mode; 192367726Seric { 192467726Seric if (tTd(38, 2)) 192567726Seric printf("user_map_open(%s)\n", map->map_mname); 192667726Seric 192767726Seric if (mode != O_RDONLY) 192867726Seric { 192967726Seric /* issue a pseudo-error message */ 193067726Seric #ifdef ENOSYS 193167726Seric errno = ENOSYS; 193267726Seric #else 193367726Seric # ifdef EFTYPE 193467726Seric errno = EFTYPE; 193567726Seric # else 193667726Seric errno = ENXIO; 193767726Seric # endif 193867726Seric #endif 193967726Seric return FALSE; 194067726Seric } 194167726Seric if (map->map_valcolnm == NULL) 194267726Seric /* nothing */ ; 194367726Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 194467726Seric map->map_valcolno = 1; 194567726Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 194667726Seric map->map_valcolno = 2; 194767726Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 194867726Seric map->map_valcolno = 3; 194967726Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 195067726Seric map->map_valcolno = 4; 195167726Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 195267726Seric map->map_valcolno = 5; 195367726Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 195467726Seric map->map_valcolno = 6; 195567726Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 195667726Seric map->map_valcolno = 7; 195767726Seric else 195867726Seric { 195967726Seric syserr("User map %s: unknown column name %s", 196067726Seric map->map_mname, map->map_valcolnm); 196167726Seric return FALSE; 196267726Seric } 196367726Seric return TRUE; 196467726Seric } 196567726Seric 196667726Seric 196767726Seric /* 196867726Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 196967726Seric */ 197067726Seric 197167726Seric #include <pwd.h> 197267726Seric 197367726Seric char * 197467726Seric user_map_lookup(map, key, av, statp) 197567726Seric MAP *map; 197667726Seric char *key; 197767726Seric char **av; 197867726Seric int *statp; 197967726Seric { 198067726Seric struct passwd *pw; 198167726Seric 198267726Seric if (tTd(38, 20)) 198367726Seric printf("user_map_lookup(%s, %s)\n", 198467726Seric map->map_mname, key); 198567726Seric 198667726Seric pw = getpwnam(key); 198767726Seric if (pw == NULL) 198867726Seric return NULL; 198967726Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 199067726Seric return map_rewrite(map, key, strlen(key), NULL); 199167726Seric else 199267726Seric { 199367726Seric char *rwval; 199467726Seric char buf[30]; 199567726Seric 199667726Seric switch (map->map_valcolno) 199767726Seric { 199867726Seric case 0: 199967726Seric case 1: 200067848Seric rwval = pw->pw_name; 200167726Seric break; 200267726Seric 200367726Seric case 2: 200467726Seric rwval = pw->pw_passwd; 200567726Seric break; 200667726Seric 200767726Seric case 3: 200867726Seric sprintf(buf, "%d", pw->pw_uid); 200967726Seric rwval = buf; 201067726Seric break; 201167726Seric 201267726Seric case 4: 201367726Seric sprintf(buf, "%d", pw->pw_gid); 201467726Seric rwval = buf; 201567726Seric break; 201667726Seric 201767726Seric case 5: 201867726Seric rwval = pw->pw_gecos; 201967726Seric break; 202067726Seric 202167726Seric case 6: 202267726Seric rwval = pw->pw_dir; 202367726Seric break; 202467726Seric 202567726Seric case 7: 202667726Seric rwval = pw->pw_shell; 202767726Seric break; 202867726Seric } 202967726Seric return map_rewrite(map, rwval, strlen(rwval), av); 203067726Seric } 203167726Seric } 203267726Seric /* 203367726Seric ** Sequenced map type. 203467726Seric ** 203567726Seric ** Tries each map in order until something matches, much like 203667726Seric ** implicit. Stores go to the first map in the list that can 203767726Seric ** support storing. 203867848Seric ** 203967848Seric ** This is slightly unusual in that there are two interfaces. 204067848Seric ** The "sequence" interface lets you stack maps arbitrarily. 204167848Seric ** The "switch" interface builds a sequence map by looking 204267848Seric ** at a system-dependent configuration file such as 204367848Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 204467848Seric ** 204567848Seric ** We don't need an explicit open, since all maps are 204667848Seric ** opened during startup, including underlying maps. 204767726Seric */ 204867726Seric 204967726Seric /* 205067726Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 205167726Seric */ 205267726Seric 205367726Seric bool 205467726Seric seq_map_parse(map, ap) 205567726Seric MAP *map; 205667726Seric char *ap; 205767726Seric { 205867726Seric int maxmap; 205967726Seric 206067726Seric if (tTd(38, 2)) 206167726Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 206267726Seric maxmap = 0; 206367726Seric while (*ap != '\0') 206467726Seric { 206567726Seric register char *p; 206667726Seric STAB *s; 206767726Seric 206867726Seric /* find beginning of map name */ 206967726Seric while (isascii(*ap) && isspace(*ap)) 207067726Seric ap++; 207167726Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 207267726Seric continue; 207367726Seric if (*p != '\0') 207467726Seric *p++ = '\0'; 207567726Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 207667726Seric p++; 207767726Seric if (*ap == '\0') 207867726Seric { 207967726Seric ap = p; 208067726Seric continue; 208167726Seric } 208267726Seric s = stab(ap, ST_MAP, ST_FIND); 208367726Seric if (s == NULL) 208467726Seric { 208567726Seric syserr("Sequence map %s: unknown member map %s", 208667726Seric map->map_mname, ap); 208767726Seric } 208867726Seric else if (maxmap == MAXMAPSTACK) 208967726Seric { 209067726Seric syserr("Sequence map %s: too many member maps (%d max)", 209167726Seric map->map_mname, MAXMAPSTACK); 209267726Seric maxmap++; 209367726Seric } 209467726Seric else if (maxmap < MAXMAPSTACK) 209567726Seric { 209667726Seric map->map_stack[maxmap++] = &s->s_map; 209767726Seric } 209867726Seric ap = p; 209967726Seric } 210067726Seric return TRUE; 210167726Seric } 210267726Seric 210367726Seric 210467726Seric /* 210567848Seric ** SWITCH_MAP_OPEN -- open a switched map 210667848Seric ** 210767848Seric ** This looks at the system-dependent configuration and builds 210867848Seric ** a sequence map that does the same thing. 210967848Seric ** 211067848Seric ** Every system must define a switch_map_find routine in conf.c 211167848Seric ** that will return the list of service types associated with a 211267848Seric ** given service class. 211367848Seric */ 211467848Seric 211567848Seric bool 211667848Seric switch_map_open(map, mode) 211767848Seric MAP *map; 211867848Seric int mode; 211967848Seric { 212067848Seric int mapno; 212167848Seric int nmaps; 212267848Seric char *maptype[MAXMAPSTACK]; 212367848Seric 212467848Seric if (tTd(38, 2)) 212567848Seric printf("switch_map_open(%s, %s, %d)\n", 212667848Seric map->map_mname, map->map_file, mode); 212767848Seric 212867850Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 212967848Seric if (tTd(38, 19)) 213067848Seric { 213167848Seric printf("\tswitch_map_find => %d\n", nmaps); 213267848Seric for (mapno = 0; mapno < nmaps; mapno++) 213367848Seric printf("\t\t%s\n", maptype[mapno]); 213467848Seric } 213567848Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 213667848Seric return FALSE; 213767848Seric 213867848Seric for (mapno = 0; mapno < nmaps; mapno++) 213967848Seric { 214067848Seric register STAB *s; 214167848Seric char nbuf[MAXNAME + 1]; 214267848Seric 214367848Seric if (maptype[mapno] == NULL) 214467848Seric continue; 214567848Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 214667848Seric s = stab(nbuf, ST_MAP, ST_FIND); 214767848Seric if (s == NULL) 214867848Seric { 214967848Seric syserr("Switch map %s: unknown member map %s", 215067848Seric map->map_mname, nbuf); 215167848Seric } 215267848Seric else 215367848Seric { 215467848Seric map->map_stack[mapno] = &s->s_map; 215567848Seric if (tTd(38, 4)) 215667848Seric printf("\tmap_stack[%d] = %s:%s\n", 215767848Seric mapno, s->s_map.map_class->map_cname, 215867848Seric nbuf); 215967848Seric } 216067848Seric } 216167848Seric return TRUE; 216267848Seric } 216367848Seric 216467848Seric 216567848Seric /* 216667848Seric ** SEQ_MAP_CLOSE -- close all underlying maps 216767848Seric */ 216867848Seric 216967848Seric seq_map_close(map) 217067848Seric MAP *map; 217167848Seric { 217267848Seric int mapno; 217367848Seric 217467848Seric if (tTd(38, 20)) 217567848Seric printf("seq_map_close(%s)\n", map->map_mname); 217667848Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 217767848Seric { 217867848Seric MAP *mm = map->map_stack[mapno]; 217967848Seric 218067848Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 218167848Seric continue; 218267848Seric mm->map_class->map_close(mm); 218367848Seric } 218467848Seric } 218567848Seric 218667848Seric 218767848Seric /* 218867726Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 218967726Seric */ 219067726Seric 219167726Seric char * 219267726Seric seq_map_lookup(map, key, args, pstat) 219367726Seric MAP *map; 219467726Seric char *key; 219567726Seric char **args; 219667726Seric int *pstat; 219767726Seric { 219867726Seric int mapno; 219967726Seric int mapbit = 0x01; 220067726Seric 220167726Seric if (tTd(38, 20)) 220267726Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 220367726Seric 220467726Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 220567726Seric { 220667726Seric MAP *mm = map->map_stack[mapno]; 220767726Seric int stat = 0; 220867726Seric char *rv; 220967726Seric 221067726Seric if (mm == NULL) 221167726Seric continue; 221267726Seric if (!bitset(MF_OPEN, mm->map_mflags)) 221367726Seric { 221467726Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 221567848Seric { 221667848Seric *pstat = EX_UNAVAILABLE; 221767726Seric return NULL; 221867848Seric } 221967726Seric continue; 222067726Seric } 222167726Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 222267726Seric if (rv != NULL) 222367726Seric return rv; 222467726Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 222567726Seric return NULL; 222667726Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 222767726Seric { 222867726Seric *pstat = stat; 222967726Seric return NULL; 223067726Seric } 223167726Seric } 223267726Seric return NULL; 223367726Seric } 223467726Seric 223567726Seric 223667726Seric /* 223767726Seric ** SEQ_MAP_STORE -- sequenced map store 223867726Seric */ 223967726Seric 224067726Seric void 224167726Seric seq_map_store(map, key, val) 224267726Seric MAP *map; 224367726Seric char *key; 224467726Seric char *val; 224567726Seric { 224667726Seric int mapno; 224767726Seric 224867726Seric if (tTd(38, 12)) 224967726Seric printf("seq_map_store(%s, %s, %s)\n", 225067726Seric map->map_mname, key, val); 225167726Seric 225267726Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 225367726Seric { 225467726Seric MAP *mm = map->map_stack[mapno]; 225567726Seric 225667726Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 225767726Seric continue; 225867726Seric 225967726Seric mm->map_class->map_store(mm, key, val); 226067726Seric return; 226167726Seric } 226267726Seric syserr("seq_map_store(%s, %s, %s): no writable map", 226367726Seric map->map_mname, key, val); 226467726Seric } 226567726Seric /* 226660207Seric ** NULL stubs 226760089Seric */ 226860089Seric 226960207Seric bool 227060207Seric null_map_open(map, mode) 227160089Seric MAP *map; 227260207Seric int mode; 227360089Seric { 227460207Seric return TRUE; 227560089Seric } 227660089Seric 227760207Seric void 227860207Seric null_map_close(map) 227960207Seric MAP *map; 228060089Seric { 228160207Seric return; 228260207Seric } 228360089Seric 228460207Seric void 228560207Seric null_map_store(map, key, val) 228660207Seric MAP *map; 228760207Seric char *key; 228860207Seric char *val; 228960089Seric { 229060207Seric return; 229160089Seric } 2292