156822Seric /* 268839Seric * Copyright (c) 1992, 1995 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*68879Seric static char sccsid[] = "@(#)map.c 8.57 (Berkeley) 04/24/95"; 1156822Seric #endif /* not lint */ 1256822Seric 1356822Seric #include "sendmail.h" 1456822Seric 1560089Seric #ifdef NDBM 1668509Seric # include <ndbm.h> 1756822Seric #endif 1860089Seric #ifdef NEWDB 1968509Seric # include <db.h> 2056822Seric #endif 2160089Seric #ifdef NIS 2268524Seric struct dom_binding { int dummy; }; /* needed on IRIX */ 2368509Seric # include <rpcsvc/ypclnt.h> 2457208Seric #endif 2556822Seric 2656822Seric /* 2760089Seric ** MAP.C -- implementations for various map classes. 2856822Seric ** 2960089Seric ** Each map class implements a series of functions: 3060089Seric ** 3160089Seric ** bool map_parse(MAP *map, char *args) 3260089Seric ** Parse the arguments from the config file. Return TRUE 3360089Seric ** if they were ok, FALSE otherwise. Fill in map with the 3460089Seric ** values. 3560089Seric ** 3660222Seric ** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 3760222Seric ** Look up the key in the given map. If found, do any 3860222Seric ** rewriting the map wants (including "args" if desired) 3960089Seric ** and return the value. Set *pstat to the appropriate status 4060222Seric ** on error and return NULL. Args will be NULL if called 4160222Seric ** from the alias routines, although this should probably 4260222Seric ** not be relied upon. It is suggested you call map_rewrite 4360222Seric ** to return the results -- it takes care of null termination 4460222Seric ** and uses a dynamically expanded buffer as needed. 4560089Seric ** 4660089Seric ** void map_store(MAP *map, char *key, char *value) 4760089Seric ** Store the key:value pair in the map. 4860089Seric ** 4960089Seric ** bool map_open(MAP *map, int mode) 5060222Seric ** Open the map for the indicated mode. Mode should 5160222Seric ** be either O_RDONLY or O_RDWR. Return TRUE if it 5260222Seric ** was opened successfully, FALSE otherwise. If the open 5360222Seric ** failed an the MF_OPTIONAL flag is not set, it should 5460222Seric ** also print an error. If the MF_ALIAS bit is set 5560222Seric ** and this map class understands the @:@ convention, it 5660222Seric ** should call aliaswait() before returning. 5760089Seric ** 5860089Seric ** void map_close(MAP *map) 5960089Seric ** Close the map. 6060089Seric */ 6160089Seric 6260089Seric #define DBMMODE 0644 6364718Seric 6464718Seric extern bool aliaswait __P((MAP *, char *, int)); 6560089Seric /* 6660089Seric ** MAP_PARSEARGS -- parse config line arguments for database lookup 6760089Seric ** 6860089Seric ** This is a generic version of the map_parse method. 6960089Seric ** 7056822Seric ** Parameters: 7160089Seric ** map -- the map being initialized. 7260089Seric ** ap -- a pointer to the args on the config line. 7356822Seric ** 7456822Seric ** Returns: 7560089Seric ** TRUE -- if everything parsed OK. 7656822Seric ** FALSE -- otherwise. 7756822Seric ** 7856822Seric ** Side Effects: 7960089Seric ** null terminates the filename; stores it in map 8056822Seric */ 8156822Seric 8256822Seric bool 8360089Seric map_parseargs(map, ap) 8456822Seric MAP *map; 8560089Seric char *ap; 8656822Seric { 8760089Seric register char *p = ap; 8856822Seric 8963753Seric map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; 9060089Seric for (;;) 9160089Seric { 9260089Seric while (isascii(*p) && isspace(*p)) 9360089Seric p++; 9460089Seric if (*p != '-') 9560089Seric break; 9660089Seric switch (*++p) 9760089Seric { 9860089Seric case 'N': 9960207Seric map->map_mflags |= MF_INCLNULL; 10063753Seric map->map_mflags &= ~MF_TRY0NULL; 10160089Seric break; 10260089Seric 10363753Seric case 'O': 10463753Seric map->map_mflags &= ~MF_TRY1NULL; 10563753Seric break; 10663753Seric 10760089Seric case 'o': 10860207Seric map->map_mflags |= MF_OPTIONAL; 10960089Seric break; 11060089Seric 11160089Seric case 'f': 11260207Seric map->map_mflags |= MF_NOFOLDCASE; 11360089Seric break; 11460089Seric 11560089Seric case 'm': 11660207Seric map->map_mflags |= MF_MATCHONLY; 11760089Seric break; 11860089Seric 11968497Seric case 'A': 12068497Seric map->map_mflags |= MF_APPEND; 12168497Seric break; 12268497Seric 12360089Seric case 'a': 12460089Seric map->map_app = ++p; 12560089Seric break; 12668350Seric 12768350Seric case 'k': 12868350Seric while (isascii(*++p) && isspace(*p)) 12968350Seric continue; 13068350Seric map->map_keycolnm = p; 13168350Seric break; 13268350Seric 13368350Seric case 'v': 13468350Seric while (isascii(*++p) && isspace(*p)) 13568350Seric continue; 13668350Seric map->map_valcolnm = p; 13768350Seric break; 13868350Seric 13968350Seric case 'z': 14068350Seric if (*++p != '\\') 14168350Seric map->map_coldelim = *p; 14268350Seric else 14368350Seric { 14468350Seric switch (*++p) 14568350Seric { 14668350Seric case 'n': 14768350Seric map->map_coldelim = '\n'; 14868350Seric break; 14968350Seric 15068350Seric case 't': 15168350Seric map->map_coldelim = '\t'; 15268350Seric break; 15368350Seric 15468350Seric default: 15568350Seric map->map_coldelim = '\\'; 15668350Seric } 15768350Seric } 15868350Seric break; 15968497Seric #ifdef RESERVED_FOR_SUN 16068497Seric case 'd': 16168497Seric map->map_mflags |= MF_DOMAIN_WIDE; 16268497Seric break; 16368497Seric 16468497Seric case 's': 16568497Seric /* info type */ 16668497Seric break; 16768497Seric #endif 16860089Seric } 16960089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 17060089Seric p++; 17160089Seric if (*p != '\0') 17260089Seric *p++ = '\0'; 17360089Seric } 17460089Seric if (map->map_app != NULL) 17560089Seric map->map_app = newstr(map->map_app); 17668350Seric if (map->map_keycolnm != NULL) 17768350Seric map->map_keycolnm = newstr(map->map_keycolnm); 17868350Seric if (map->map_valcolnm != NULL) 17968350Seric map->map_valcolnm = newstr(map->map_valcolnm); 18060089Seric 18160089Seric if (*p != '\0') 18260089Seric { 18360089Seric map->map_file = p; 18460089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 18560089Seric p++; 18660089Seric if (*p != '\0') 18760089Seric *p++ = '\0'; 18860089Seric map->map_file = newstr(map->map_file); 18960089Seric } 19060089Seric 19160089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 19260089Seric p++; 19360089Seric if (*p != '\0') 19460089Seric map->map_rebuild = newstr(p); 19560089Seric 19668350Seric if (map->map_file == NULL && 19768350Seric !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 19857208Seric { 19960089Seric syserr("No file name for %s map %s", 20060089Seric map->map_class->map_cname, map->map_mname); 20156822Seric return FALSE; 20257208Seric } 20360089Seric return TRUE; 20460089Seric } 20560089Seric /* 20660089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 20760089Seric ** 20860089Seric ** It also adds the map_app string. It can be used as a utility 20960089Seric ** in the map_lookup method. 21060089Seric ** 21160089Seric ** Parameters: 21260089Seric ** map -- the map that causes this. 21360089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 21460089Seric ** slen -- the length of s. 21560089Seric ** av -- arguments to interpolate into buf. 21660089Seric ** 21760089Seric ** Returns: 21867895Seric ** Pointer to rewritten result. This is static data that 21967895Seric ** should be copied if it is to be saved! 22060089Seric ** 22160089Seric ** Side Effects: 22260089Seric ** none. 22360089Seric */ 22460089Seric 22560089Seric char * 22660089Seric map_rewrite(map, s, slen, av) 22760089Seric register MAP *map; 22860089Seric register char *s; 22960089Seric int slen; 23060089Seric char **av; 23160089Seric { 23260089Seric register char *bp; 23360089Seric register char c; 23460089Seric char **avp; 23560089Seric register char *ap; 23660089Seric int i; 23760089Seric int len; 23867895Seric static int buflen = -1; 23967895Seric static char *buf = NULL; 24060089Seric 24160537Seric if (tTd(39, 1)) 24260089Seric { 24360256Seric printf("map_rewrite(%.*s), av =", slen, s); 24460256Seric if (av == NULL) 24560256Seric printf(" (nullv)"); 24660256Seric else 24760256Seric { 24860256Seric for (avp = av; *avp != NULL; avp++) 24960256Seric printf("\n\t%s", *avp); 25060256Seric } 25160256Seric printf("\n"); 25260089Seric } 25360089Seric 25460089Seric /* count expected size of output (can safely overestimate) */ 25560089Seric i = len = slen; 25660089Seric if (av != NULL) 25760089Seric { 25860089Seric bp = s; 25960089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 26060089Seric { 26160089Seric if (c != '%') 26260089Seric continue; 26360089Seric if (--i < 0) 26460089Seric break; 26560089Seric c = *bp++; 26660089Seric if (!(isascii(c) && isdigit(c))) 26760089Seric continue; 26863937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 26960089Seric continue; 27060089Seric if (*avp == NULL) 27160089Seric continue; 27260089Seric len += strlen(*avp); 27360089Seric } 27460089Seric } 27560089Seric if (map->map_app != NULL) 27660089Seric len += strlen(map->map_app); 27767895Seric if (buflen < ++len) 27860089Seric { 27960089Seric /* need to malloc additional space */ 28067895Seric buflen = len; 28167895Seric if (buf != NULL) 28267895Seric free(buf); 28367895Seric buf = xalloc(buflen); 28460089Seric } 28560089Seric 28667895Seric bp = buf; 28760089Seric if (av == NULL) 28860089Seric { 28960089Seric bcopy(s, bp, slen); 29060089Seric bp += slen; 29160089Seric } 29260089Seric else 29360089Seric { 29460089Seric while (--slen >= 0 && (c = *s++) != '\0') 29560089Seric { 29660089Seric if (c != '%') 29760089Seric { 29860089Seric pushc: 29960089Seric *bp++ = c; 30060089Seric continue; 30160089Seric } 30260089Seric if (--slen < 0 || (c = *s++) == '\0') 30360089Seric c = '%'; 30460089Seric if (c == '%') 30560089Seric goto pushc; 30660089Seric if (!(isascii(c) && isdigit(c))) 30760089Seric { 30860089Seric *bp++ = '%'; 30960089Seric goto pushc; 31060089Seric } 31163937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 31260089Seric continue; 31360089Seric if (*avp == NULL) 31460089Seric continue; 31560089Seric 31660089Seric /* transliterate argument into output string */ 31760089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 31860089Seric *bp++ = c; 31960089Seric } 32060089Seric } 32160089Seric if (map->map_app != NULL) 32260089Seric strcpy(bp, map->map_app); 32360089Seric else 32460089Seric *bp = '\0'; 32560537Seric if (tTd(39, 1)) 32667895Seric printf("map_rewrite => %s\n", buf); 32767895Seric return buf; 32860089Seric } 32960089Seric /* 33060537Seric ** INITMAPS -- initialize for aliasing 33160537Seric ** 33260537Seric ** Parameters: 33360537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 33460537Seric ** e -- current envelope. 33560537Seric ** 33660537Seric ** Returns: 33760537Seric ** none. 33860537Seric ** 33960537Seric ** Side Effects: 34060537Seric ** initializes aliases: 34160537Seric ** if NDBM: opens the database. 34260537Seric ** if ~NDBM: reads the aliases into the symbol table. 34360537Seric */ 34460537Seric 34560537Seric initmaps(rebuild, e) 34660537Seric bool rebuild; 34760537Seric register ENVELOPE *e; 34860537Seric { 34960537Seric extern void map_init(); 35060537Seric 35164671Seric #ifdef XDEBUG 35264671Seric checkfd012("entering initmaps"); 35364671Seric #endif 35460537Seric CurEnv = e; 35565085Seric if (rebuild) 35665085Seric { 35765085Seric stabapply(map_init, 1); 35865085Seric stabapply(map_init, 2); 35965085Seric } 36065085Seric else 36165085Seric { 36265085Seric stabapply(map_init, 0); 36365085Seric } 36464671Seric #ifdef XDEBUG 36564671Seric checkfd012("exiting initmaps"); 36664671Seric #endif 36760537Seric } 36860537Seric 36960537Seric void 37060537Seric map_init(s, rebuild) 37160537Seric register STAB *s; 37260537Seric int rebuild; 37360537Seric { 37460537Seric register MAP *map; 37560537Seric 37660537Seric /* has to be a map */ 37760537Seric if (s->s_type != ST_MAP) 37860537Seric return; 37960537Seric 38060537Seric map = &s->s_map; 38160537Seric if (!bitset(MF_VALID, map->map_mflags)) 38260537Seric return; 38360537Seric 38460537Seric if (tTd(38, 2)) 38568350Seric printf("map_init(%s:%s, %s, %d)\n", 38664690Seric map->map_class->map_cname == NULL ? "NULL" : 38764690Seric map->map_class->map_cname, 38868350Seric map->map_mname == NULL ? "NULL" : map->map_mname, 38965085Seric map->map_file == NULL ? "NULL" : map->map_file, 39065085Seric rebuild); 39160537Seric 39265085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && 39365085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) 39465085Seric { 39565085Seric if (tTd(38, 3)) 39665085Seric printf("\twrong pass\n"); 39765085Seric return; 39865085Seric } 39965085Seric 40060537Seric /* if already open, close it (for nested open) */ 40160537Seric if (bitset(MF_OPEN, map->map_mflags)) 40260537Seric { 40360537Seric map->map_class->map_close(map); 40460537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 40560537Seric } 40660537Seric 40765085Seric if (rebuild == 2) 40860537Seric { 40965085Seric rebuildaliases(map, FALSE); 41060537Seric } 41160537Seric else 41260537Seric { 41360537Seric if (map->map_class->map_open(map, O_RDONLY)) 41460537Seric { 41560537Seric if (tTd(38, 4)) 41668350Seric printf("\t%s:%s %s: valid\n", 41764690Seric map->map_class->map_cname == NULL ? "NULL" : 41864690Seric map->map_class->map_cname, 41968350Seric map->map_mname == NULL ? "NULL" : 42068350Seric map->map_mname, 42164690Seric map->map_file == NULL ? "NULL" : 42264690Seric map->map_file); 42360537Seric map->map_mflags |= MF_OPEN; 42460537Seric } 42568350Seric else 42668350Seric { 42768350Seric if (tTd(38, 4)) 42868350Seric printf("\t%s:%s %s: invalid: %s\n", 42968350Seric map->map_class->map_cname == NULL ? "NULL" : 43068350Seric map->map_class->map_cname, 43168350Seric map->map_mname == NULL ? "NULL" : 43268350Seric map->map_mname, 43368350Seric map->map_file == NULL ? "NULL" : 43468350Seric map->map_file, 43568350Seric errstring(errno)); 43668350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 43768350Seric { 43868350Seric extern MAPCLASS BogusMapClass; 43968350Seric 44068350Seric map->map_class = &BogusMapClass; 44168350Seric map->map_mflags |= MF_OPEN; 44268350Seric } 44368350Seric } 44460537Seric } 44560537Seric } 44660537Seric /* 44760089Seric ** NDBM modules 44860089Seric */ 44960089Seric 45060089Seric #ifdef NDBM 45160089Seric 45260089Seric /* 45360089Seric ** DBM_MAP_OPEN -- DBM-style map open 45460089Seric */ 45560089Seric 45660089Seric bool 45760089Seric ndbm_map_open(map, mode) 45860089Seric MAP *map; 45960089Seric int mode; 46060089Seric { 46164284Seric register DBM *dbm; 46264284Seric struct stat st; 46360089Seric 46460537Seric if (tTd(38, 2)) 46568350Seric printf("ndbm_map_open(%s, %s, %d)\n", 46668350Seric map->map_mname, map->map_file, mode); 46760089Seric 46860207Seric if (mode == O_RDWR) 46960207Seric mode |= O_CREAT|O_TRUNC; 47060207Seric 47160089Seric /* open the database */ 47260089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 47356822Seric if (dbm == NULL) 47456822Seric { 47564718Seric if (aliaswait(map, ".pag", FALSE)) 47664718Seric return TRUE; 47760207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 47856836Seric syserr("Cannot open DBM database %s", map->map_file); 47956822Seric return FALSE; 48056822Seric } 48160089Seric map->map_db1 = (void *) dbm; 48264964Seric if (mode == O_RDONLY) 48364964Seric { 48464964Seric if (bitset(MF_ALIAS, map->map_mflags) && 48564964Seric !aliaswait(map, ".pag", TRUE)) 48664718Seric return FALSE; 48764964Seric } 48864964Seric else 48964964Seric { 49064964Seric int fd; 49164964Seric 49264964Seric /* exclusive lock for duration of rebuild */ 49364964Seric fd = dbm_dirfno((DBM *) map->map_db1); 49464964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 49564964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 49664964Seric map->map_mflags |= MF_LOCKED; 49764964Seric } 49864718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 49964284Seric map->map_mtime = st.st_mtime; 50056822Seric return TRUE; 50156822Seric } 50260089Seric 50360089Seric 50460089Seric /* 50556822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 50656822Seric */ 50756822Seric 50856822Seric char * 50960089Seric ndbm_map_lookup(map, name, av, statp) 51056822Seric MAP *map; 51160089Seric char *name; 51256822Seric char **av; 51359084Seric int *statp; 51456822Seric { 51556822Seric datum key, val; 51664373Seric int fd; 51760089Seric char keybuf[MAXNAME + 1]; 51856822Seric 51960537Seric if (tTd(38, 20)) 52068350Seric printf("ndbm_map_lookup(%s, %s)\n", 52168350Seric map->map_mname, name); 52260089Seric 52360089Seric key.dptr = name; 52460089Seric key.dsize = strlen(name); 52560207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 52657014Seric { 52760089Seric if (key.dsize > sizeof keybuf - 1) 52860089Seric key.dsize = sizeof keybuf - 1; 52960089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 53060089Seric makelower(keybuf); 53160089Seric key.dptr = keybuf; 53257014Seric } 53364373Seric fd = dbm_dirfno((DBM *) map->map_db1); 53464388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 53564373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 53663753Seric val.dptr = NULL; 53763753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 53863753Seric { 53963753Seric val = dbm_fetch((DBM *) map->map_db1, key); 54063753Seric if (val.dptr != NULL) 54163753Seric map->map_mflags &= ~MF_TRY1NULL; 54263753Seric } 54363753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 54463753Seric { 54556822Seric key.dsize++; 54663753Seric val = dbm_fetch((DBM *) map->map_db1, key); 54763753Seric if (val.dptr != NULL) 54863753Seric map->map_mflags &= ~MF_TRY0NULL; 54963753Seric } 55064388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 55164373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 55256822Seric if (val.dptr == NULL) 55356822Seric return NULL; 55460207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 55563753Seric return map_rewrite(map, name, strlen(name), NULL); 55663753Seric else 55763753Seric return map_rewrite(map, val.dptr, val.dsize, av); 55856822Seric } 55956822Seric 56056822Seric 56156822Seric /* 56260089Seric ** DBM_MAP_STORE -- store a datum in the database 56356822Seric */ 56456822Seric 56560089Seric void 56660089Seric ndbm_map_store(map, lhs, rhs) 56760089Seric register MAP *map; 56860089Seric char *lhs; 56960089Seric char *rhs; 57060089Seric { 57160089Seric datum key; 57260089Seric datum data; 57360089Seric int stat; 57460089Seric 57560537Seric if (tTd(38, 12)) 57668350Seric printf("ndbm_map_store(%s, %s, %s)\n", 57768350Seric map->map_mname, lhs, rhs); 57860089Seric 57960089Seric key.dsize = strlen(lhs); 58060089Seric key.dptr = lhs; 58160089Seric 58260089Seric data.dsize = strlen(rhs); 58360089Seric data.dptr = rhs; 58460089Seric 58560207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 58660089Seric { 58760089Seric key.dsize++; 58860089Seric data.dsize++; 58960089Seric } 59060089Seric 59160089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 59260089Seric if (stat > 0) 59360089Seric { 59468497Seric if (!bitset(MF_APPEND, map->map_mflags)) 59568497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 59668497Seric else 59768497Seric { 59868497Seric static char *buf = NULL; 59968497Seric static int bufsiz = 0; 600*68879Seric auto int xstat; 60168497Seric datum old; 60268497Seric 603*68879Seric old.dptr = ndbm_map_lookup(map, key.dptr, NULL, &xstat); 60468497Seric if (old.dptr != NULL && *old.dptr != '\0') 60568497Seric { 60668497Seric old.dsize = strlen(old.dptr); 60768497Seric if (data.dsize + old.dsize + 2 > bufsiz) 60868497Seric { 60968497Seric if (buf != NULL) 61068497Seric (void) free(buf); 61168497Seric bufsiz = data.dsize + old.dsize + 2; 61268497Seric buf = xalloc(bufsiz); 61368497Seric } 61468497Seric sprintf(buf, "%s,%s", data.dptr, old.dptr); 61568497Seric data.dsize = data.dsize + old.dsize + 1; 61668497Seric data.dptr = buf; 61768497Seric if (tTd(38, 9)) 61868497Seric printf("ndbm_map_store append=%s\n", data.dptr); 61968497Seric } 62068497Seric } 62160089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 62260089Seric } 62360089Seric if (stat != 0) 62460089Seric syserr("readaliases: dbm put (%s)", lhs); 62560089Seric } 62660089Seric 62760089Seric 62860089Seric /* 62960207Seric ** NDBM_MAP_CLOSE -- close the database 63060089Seric */ 63160089Seric 63260089Seric void 63360089Seric ndbm_map_close(map) 63460089Seric register MAP *map; 63560089Seric { 63666773Seric if (tTd(38, 9)) 63768350Seric printf("ndbm_map_close(%s, %s, %x)\n", 63868350Seric map->map_mname, map->map_file, map->map_mflags); 63966773Seric 64060207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 64160089Seric { 64264250Seric #ifdef NIS 64364075Seric bool inclnull; 64460089Seric char buf[200]; 64560089Seric 64664075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 64764075Seric map->map_mflags &= ~MF_INCLNULL; 64864075Seric 64960089Seric (void) sprintf(buf, "%010ld", curtime()); 65060089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 65160089Seric 65264941Seric (void) gethostname(buf, sizeof buf); 65360089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 65464075Seric 65564075Seric if (inclnull) 65664075Seric map->map_mflags |= MF_INCLNULL; 65760089Seric #endif 65860089Seric 65960089Seric /* write out the distinguished alias */ 66060089Seric ndbm_map_store(map, "@", "@"); 66160089Seric } 66260089Seric dbm_close((DBM *) map->map_db1); 66360089Seric } 66460089Seric 66560089Seric #endif 66660089Seric /* 66760582Seric ** NEWDB (Hash and BTree) Modules 66860089Seric */ 66960089Seric 67060089Seric #ifdef NEWDB 67160089Seric 67260089Seric /* 67360582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 67460582Seric ** 67560582Seric ** These do rather bizarre locking. If you can lock on open, 67660582Seric ** do that to avoid the condition of opening a database that 67760582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 67860582Seric ** there will be a race condition. If opening for read-only, 67960582Seric ** we immediately release the lock to avoid freezing things up. 68060582Seric ** We really ought to hold the lock, but guarantee that we won't 68160582Seric ** be pokey about it. That's hard to do. 68260089Seric */ 68360089Seric 68456822Seric bool 68560089Seric bt_map_open(map, mode) 68656822Seric MAP *map; 68760089Seric int mode; 68856822Seric { 68956822Seric DB *db; 69060228Seric int i; 69160582Seric int omode; 69264373Seric int fd; 69364284Seric struct stat st; 69468528Seric char buf[MAXNAME + 1]; 69556822Seric 69660537Seric if (tTd(38, 2)) 69768350Seric printf("bt_map_open(%s, %s, %d)\n", 69868350Seric map->map_mname, map->map_file, mode); 69960089Seric 70060582Seric omode = mode; 70160582Seric if (omode == O_RDWR) 70260582Seric { 70360582Seric omode |= O_CREAT|O_TRUNC; 70465830Seric #if defined(O_EXLOCK) && HASFLOCK 70560582Seric omode |= O_EXLOCK; 70666843Seric # if !OLD_NEWDB 70760582Seric } 70860582Seric else 70960582Seric { 71060582Seric omode |= O_SHLOCK; 71160582Seric # endif 71260582Seric #endif 71360582Seric } 71460207Seric 71560228Seric (void) strcpy(buf, map->map_file); 71660228Seric i = strlen(buf); 71760228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 71860228Seric (void) strcat(buf, ".db"); 71960582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 72056822Seric if (db == NULL) 72156822Seric { 72264718Seric #ifdef MAYBENEXTRELEASE 72364718Seric if (aliaswait(map, ".db", FALSE)) 72464718Seric return TRUE; 72564718Seric #endif 72660207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 72756836Seric syserr("Cannot open BTREE database %s", map->map_file); 72856822Seric return FALSE; 72956822Seric } 73068350Seric #if !OLD_NEWDB 73164373Seric fd = db->fd(db); 73268778Seric # if defined(O_EXLOCK) && HASFLOCK 73368778Seric if (fd >= 0) 73468778Seric { 73568778Seric if (mode == O_RDONLY) 73668778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 73768778Seric else 73868778Seric map->map_mflags |= MF_LOCKED; 73968778Seric } 74068778Seric # else 74164373Seric if (mode == O_RDWR && fd >= 0) 74264388Seric { 74364388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 74464388Seric map->map_mflags |= MF_LOCKED; 74564388Seric } 74660582Seric # endif 74760582Seric #endif 74860585Seric 74960585Seric /* try to make sure that at least the database header is on disk */ 75060585Seric if (mode == O_RDWR) 75166843Seric #if OLD_NEWDB 75264373Seric (void) db->sync(db); 75364373Seric #else 75460585Seric (void) db->sync(db, 0); 75560585Seric 75664373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 75764284Seric map->map_mtime = st.st_mtime; 75864284Seric #endif 75964284Seric 76060089Seric map->map_db2 = (void *) db; 76160207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 76264718Seric if (!aliaswait(map, ".db", TRUE)) 76364718Seric return FALSE; 76456822Seric return TRUE; 76556822Seric } 76656822Seric 76756822Seric 76856822Seric /* 76956822Seric ** HASH_MAP_INIT -- HASH-style map initialization 77056822Seric */ 77156822Seric 77256822Seric bool 77360089Seric hash_map_open(map, mode) 77456822Seric MAP *map; 77560089Seric int mode; 77656822Seric { 77756822Seric DB *db; 77860228Seric int i; 77960582Seric int omode; 78064373Seric int fd; 78164284Seric struct stat st; 78268528Seric char buf[MAXNAME + 1]; 78356822Seric 78460537Seric if (tTd(38, 2)) 78568350Seric printf("hash_map_open(%s, %s, %d)\n", 78668350Seric map->map_mname, map->map_file, mode); 78760089Seric 78860582Seric omode = mode; 78960582Seric if (omode == O_RDWR) 79060582Seric { 79160582Seric omode |= O_CREAT|O_TRUNC; 79265830Seric #if defined(O_EXLOCK) && HASFLOCK 79360582Seric omode |= O_EXLOCK; 79466843Seric # if !OLD_NEWDB 79560582Seric } 79660582Seric else 79760582Seric { 79860582Seric omode |= O_SHLOCK; 79960582Seric # endif 80060582Seric #endif 80160582Seric } 80260207Seric 80360228Seric (void) strcpy(buf, map->map_file); 80460228Seric i = strlen(buf); 80560228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 80660228Seric (void) strcat(buf, ".db"); 80760582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 80856822Seric if (db == NULL) 80956822Seric { 81064718Seric #ifdef MAYBENEXTRELEASE 81164718Seric if (aliaswait(map, ".db", FALSE)) 81264718Seric return TRUE; 81364718Seric #endif 81460207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 81556836Seric syserr("Cannot open HASH database %s", map->map_file); 81656822Seric return FALSE; 81756822Seric } 81868350Seric #if !OLD_NEWDB 81964373Seric fd = db->fd(db); 82068778Seric # if defined(O_EXLOCK) && HASFLOCK 82168778Seric if (fd >= 0) 82268778Seric { 82368778Seric if (mode == O_RDONLY) 82468778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 82568778Seric else 82668778Seric map->map_mflags |= MF_LOCKED; 82768778Seric } 82868778Seric # else 82964373Seric if (mode == O_RDWR && fd >= 0) 83064388Seric { 83164388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 83264388Seric map->map_mflags |= MF_LOCKED; 83364388Seric } 83460582Seric # endif 83560582Seric #endif 83660585Seric 83760585Seric /* try to make sure that at least the database header is on disk */ 83860585Seric if (mode == O_RDWR) 83966843Seric #if OLD_NEWDB 84064373Seric (void) db->sync(db); 84164373Seric #else 84260585Seric (void) db->sync(db, 0); 84360585Seric 84464373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 84564284Seric map->map_mtime = st.st_mtime; 84664284Seric #endif 84764284Seric 84860089Seric map->map_db2 = (void *) db; 84960207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 85064718Seric if (!aliaswait(map, ".db", TRUE)) 85164718Seric return FALSE; 85256822Seric return TRUE; 85356822Seric } 85456822Seric 85556822Seric 85656822Seric /* 85756822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 85856822Seric */ 85956822Seric 86056822Seric char * 86160089Seric db_map_lookup(map, name, av, statp) 86256822Seric MAP *map; 86360089Seric char *name; 86456822Seric char **av; 86559084Seric int *statp; 86656822Seric { 86756822Seric DBT key, val; 86860422Seric register DB *db = (DB *) map->map_db2; 86960422Seric int st; 87060422Seric int saveerrno; 87164373Seric int fd; 87260089Seric char keybuf[MAXNAME + 1]; 87356822Seric 87460537Seric if (tTd(38, 20)) 87568350Seric printf("db_map_lookup(%s, %s)\n", 87668350Seric map->map_mname, name); 87760089Seric 87860089Seric key.size = strlen(name); 87960089Seric if (key.size > sizeof keybuf - 1) 88060089Seric key.size = sizeof keybuf - 1; 88160089Seric key.data = keybuf; 88260089Seric bcopy(name, keybuf, key.size + 1); 88360207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 88460089Seric makelower(keybuf); 88566843Seric #if !OLD_NEWDB 88664388Seric fd = db->fd(db); 88764388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 88864388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 88960422Seric #endif 89063753Seric st = 1; 89163753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 89263753Seric { 89363753Seric st = db->get(db, &key, &val, 0); 89463753Seric if (st == 0) 89563753Seric map->map_mflags &= ~MF_TRY1NULL; 89663753Seric } 89763753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 89863753Seric { 89963753Seric key.size++; 90063753Seric st = db->get(db, &key, &val, 0); 90163753Seric if (st == 0) 90263753Seric map->map_mflags &= ~MF_TRY0NULL; 90363753Seric } 90460422Seric saveerrno = errno; 90566843Seric #if !OLD_NEWDB 90664388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 90764373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 90860422Seric #endif 90960422Seric if (st != 0) 91060422Seric { 91160422Seric errno = saveerrno; 91260422Seric if (st < 0) 91360422Seric syserr("db_map_lookup: get (%s)", name); 91456822Seric return NULL; 91560422Seric } 91660207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 91763753Seric return map_rewrite(map, name, strlen(name), NULL); 91863753Seric else 91963753Seric return map_rewrite(map, val.data, val.size, av); 92056822Seric } 92156822Seric 92260089Seric 92360089Seric /* 92460089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 92556822Seric */ 92656822Seric 92760089Seric void 92860089Seric db_map_store(map, lhs, rhs) 92960089Seric register MAP *map; 93060089Seric char *lhs; 93160089Seric char *rhs; 93256822Seric { 93360089Seric int stat; 93460089Seric DBT key; 93560089Seric DBT data; 93660089Seric register DB *db = map->map_db2; 93756822Seric 93860537Seric if (tTd(38, 20)) 93968350Seric printf("db_map_store(%s, %s, %s)\n", 94068350Seric map->map_mname, lhs, rhs); 94160089Seric 94260089Seric key.size = strlen(lhs); 94360089Seric key.data = lhs; 94460089Seric 94560089Seric data.size = strlen(rhs); 94660089Seric data.data = rhs; 94760089Seric 94860207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 94956822Seric { 95060089Seric key.size++; 95160089Seric data.size++; 95260089Seric } 95356836Seric 95460089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 95560089Seric if (stat > 0) 95660089Seric { 95768497Seric if (!bitset(MF_APPEND, map->map_mflags)) 95868497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 95968497Seric else 96068497Seric { 96168497Seric static char *buf = NULL; 96268497Seric static int bufsiz = 0; 96368497Seric DBT old; 96468497Seric 96568497Seric old.data = db_map_lookup(map, key.data, NULL, &stat); 96668497Seric if (old.data != NULL) 96768497Seric { 96868497Seric old.size = strlen(old.data); 96968497Seric if (data.size + old.size + 2 > bufsiz) 97068497Seric { 97168497Seric if (buf != NULL) 97268497Seric (void) free(buf); 97368497Seric bufsiz = data.size + old.size + 2; 97468497Seric buf = xalloc(bufsiz); 97568497Seric } 97668497Seric sprintf(buf, "%s,%s", data.data, old.data); 97768497Seric data.size = data.size + old.size + 1; 97868497Seric data.data = buf; 97968497Seric if (tTd(38, 9)) 98068497Seric printf("db_map_store append=%s\n", data.data); 98168497Seric } 98268497Seric } 98360089Seric stat = db->put(db, &key, &data, 0); 98460089Seric } 98560089Seric if (stat != 0) 98660089Seric syserr("readaliases: db put (%s)", lhs); 98760089Seric } 98856836Seric 98956847Seric 99060089Seric /* 99160089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 99260089Seric */ 99360089Seric 99460089Seric void 99560089Seric db_map_close(map) 99660089Seric MAP *map; 99760089Seric { 99860089Seric register DB *db = map->map_db2; 99960089Seric 100060537Seric if (tTd(38, 9)) 100168350Seric printf("db_map_close(%s, %s, %x)\n", 100268350Seric map->map_mname, map->map_file, map->map_mflags); 100360089Seric 100460207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 100558804Seric { 100660089Seric /* write out the distinguished alias */ 100760089Seric db_map_store(map, "@", "@"); 100858804Seric } 100958963Seric 101060089Seric if (db->close(db) != 0) 101160089Seric syserr("readaliases: db close failure"); 101256822Seric } 101357208Seric 101460089Seric #endif 101560089Seric /* 101660089Seric ** NIS Modules 101760089Seric */ 101860089Seric 101960089Seric # ifdef NIS 102060089Seric 102164369Seric # ifndef YPERR_BUSY 102264369Seric # define YPERR_BUSY 16 102364369Seric # endif 102464369Seric 102557208Seric /* 102660089Seric ** NIS_MAP_OPEN -- open DBM map 102757208Seric */ 102857208Seric 102957208Seric bool 103060089Seric nis_map_open(map, mode) 103157208Seric MAP *map; 103260089Seric int mode; 103357208Seric { 103457216Seric int yperr; 103560215Seric register char *p; 103660215Seric auto char *vp; 103760215Seric auto int vsize; 103857216Seric char *master; 103957216Seric 104060537Seric if (tTd(38, 2)) 104168350Seric printf("nis_map_open(%s, %s)\n", 104268350Seric map->map_mname, map->map_file); 104360089Seric 104460207Seric if (mode != O_RDONLY) 104560207Seric { 104664650Seric /* issue a pseudo-error message */ 104764650Seric #ifdef ENOSYS 104864650Seric errno = ENOSYS; 104964650Seric #else 105064650Seric # ifdef EFTYPE 105164650Seric errno = EFTYPE; 105264650Seric # else 105364650Seric errno = ENXIO; 105464650Seric # endif 105564650Seric #endif 105660207Seric return FALSE; 105760207Seric } 105860207Seric 105960089Seric p = strchr(map->map_file, '@'); 106060089Seric if (p != NULL) 106160089Seric { 106260089Seric *p++ = '\0'; 106360089Seric if (*p != '\0') 106460089Seric map->map_domain = p; 106560089Seric } 106660215Seric 106760089Seric if (*map->map_file == '\0') 106860089Seric map->map_file = "mail.aliases"; 106960089Seric 107066157Seric if (map->map_domain == NULL) 107166157Seric { 107266157Seric yperr = yp_get_default_domain(&map->map_domain); 107366157Seric if (yperr != 0) 107466157Seric { 107566744Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 107668350Seric syserr("421 NIS map %s specified, but NIS not running\n", 107766744Seric map->map_file); 107866157Seric return FALSE; 107966157Seric } 108066157Seric } 108166157Seric 108260215Seric /* check to see if this map actually exists */ 108360089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 108460089Seric &vp, &vsize); 108560537Seric if (tTd(38, 10)) 108660089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 108760089Seric map->map_domain, map->map_file, yperr_string(yperr)); 108860089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 108968350Seric { 109068350Seric if (!bitset(MF_ALIAS, map->map_mflags) || 109168350Seric aliaswait(map, NULL, TRUE)) 109268350Seric return TRUE; 109368350Seric } 109460215Seric 109560215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 109668735Seric { 109768735Seric syserr("421 Cannot bind to map %s in domain %s: %s", 109868735Seric map->map_file, map->map_domain, yperr_string(yperr)); 109968735Seric } 110060215Seric 110160089Seric return FALSE; 110260089Seric } 110360089Seric 110460089Seric 110560089Seric /* 110657208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 110757208Seric */ 110857208Seric 110957208Seric char * 111060089Seric nis_map_lookup(map, name, av, statp) 111157208Seric MAP *map; 111260089Seric char *name; 111357208Seric char **av; 111459084Seric int *statp; 111557208Seric { 111657208Seric char *vp; 111757642Seric auto int vsize; 111859274Seric int buflen; 111960215Seric int yperr; 112060089Seric char keybuf[MAXNAME + 1]; 112157208Seric 112260537Seric if (tTd(38, 20)) 112368350Seric printf("nis_map_lookup(%s, %s)\n", 112468350Seric map->map_mname, name); 112560089Seric 112660089Seric buflen = strlen(name); 112760089Seric if (buflen > sizeof keybuf - 1) 112860089Seric buflen = sizeof keybuf - 1; 112960089Seric bcopy(name, keybuf, buflen + 1); 113060207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 113160089Seric makelower(keybuf); 113263753Seric yperr = YPERR_KEY; 113363753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 113463753Seric { 113563753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 113663753Seric &vp, &vsize); 113763753Seric if (yperr == 0) 113863753Seric map->map_mflags &= ~MF_TRY1NULL; 113963753Seric } 114063753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 114163753Seric { 114259274Seric buflen++; 114363753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 114463753Seric &vp, &vsize); 114563753Seric if (yperr == 0) 114663753Seric map->map_mflags &= ~MF_TRY0NULL; 114763753Seric } 114860089Seric if (yperr != 0) 114960089Seric { 115060089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 115160215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 115257208Seric return NULL; 115360089Seric } 115460207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 115563753Seric return map_rewrite(map, name, strlen(name), NULL); 115663753Seric else 115763753Seric return map_rewrite(map, vp, vsize, av); 115857208Seric } 115957208Seric 116068350Seric #endif 116168350Seric /* 116268350Seric ** NISPLUS Modules 116368350Seric ** 116468350Seric ** This code donated by Sun Microsystems. 116568350Seric */ 116667848Seric 116768350Seric #ifdef NISPLUS 116868350Seric 116968350Seric #undef NIS /* symbol conflict in nis.h */ 117068350Seric #include <rpcsvc/nis.h> 117168350Seric #include <rpcsvc/nislib.h> 117268350Seric 117368350Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 117468350Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 117568350Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 117668350Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 117768350Seric 117867848Seric /* 117968350Seric ** NISPLUS_MAP_OPEN -- open nisplus table 118067848Seric */ 118167848Seric 118268350Seric bool 118368350Seric nisplus_map_open(map, mode) 118467848Seric MAP *map; 118568350Seric int mode; 118667848Seric { 118768350Seric register char *p; 118868350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 118968350Seric nis_result *res = NULL; 119068350Seric u_int objs_len; 119168350Seric nis_object *obj_ptr; 119268350Seric int retry_cnt, max_col, i; 119368350Seric 119468350Seric if (tTd(38, 2)) 119568350Seric printf("nisplus_map_open(%s, %s, %d)\n", 119668350Seric map->map_mname, map->map_file, mode); 119768350Seric 119868350Seric if (mode != O_RDONLY) 119968350Seric { 120068350Seric errno = ENODEV; 120168350Seric return FALSE; 120268350Seric } 120368350Seric 120468350Seric if (*map->map_file == '\0') 120568350Seric map->map_file = "mail_aliases.org_dir"; 120668350Seric 120768350Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 120868350Seric { 120968350Seric /* set default NISPLUS Domain to $m */ 121068350Seric extern char *nisplus_default_domain(); 121168350Seric 121268350Seric map->map_domain = newstr(nisplus_default_domain()); 121368350Seric if (tTd(38, 2)) 121468350Seric printf("nisplus_map_open(%s): using domain %s\n", 121568350Seric map->map_file, map->map_domain); 121668350Seric } 121768350Seric if (!PARTIAL_NAME(map->map_file)) 121868350Seric map->map_domain = newstr(""); 121968350Seric 122068350Seric /* check to see if this map actually exists */ 122168350Seric if (PARTIAL_NAME(map->map_file)) 122268350Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 122368350Seric else 122468350Seric strcpy(qbuf, map->map_file); 122568350Seric 122668350Seric retry_cnt = 0; 122768350Seric while (res == NULL || res->status != NIS_SUCCESS) 122868350Seric { 122968350Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 123068350Seric switch (res->status) 123168350Seric { 123268350Seric case NIS_SUCCESS: 123368350Seric case NIS_TRYAGAIN: 123468350Seric case NIS_RPCERROR: 123568350Seric case NIS_NAMEUNREACHABLE: 123668350Seric break; 123768350Seric 123868350Seric default: /* all other nisplus errors */ 123968350Seric #if 0 124068350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 124168350Seric syserr("421 Cannot find table %s.%s: %s", 124268350Seric map->map_file, map->map_domain, 124368350Seric nis_sperrno(res->status)); 124468350Seric #endif 124568350Seric errno = EBADR; 124668350Seric return FALSE; 124768350Seric } 124868350Seric sleep(2); /* try not to overwhelm hosed server */ 124968350Seric if (retry_cnt++ > 4) 125068350Seric { 125168350Seric errno = EBADR; 125268350Seric return FALSE; 125368350Seric } 125468350Seric } 125568350Seric 125668350Seric if (NIS_RES_NUMOBJ(res) != 1 || 125768350Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 125868350Seric { 125968350Seric if (tTd(38, 10)) 126068350Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 126168350Seric #if 0 126268350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 126368350Seric syserr("421 %s.%s: %s is not a table", 126468350Seric map->map_file, map->map_domain, 126568350Seric nis_sperrno(res->status)); 126668350Seric #endif 126768350Seric errno = EBADR; 126868350Seric return FALSE; 126968350Seric } 127068350Seric /* default key column is column 0 */ 127168350Seric if (map->map_keycolnm == NULL) 127268350Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 127368350Seric 127468350Seric max_col = COL_MAX(res); 127568350Seric 127668350Seric /* verify the key column exist */ 127768350Seric for (i=0; i< max_col; i++) 127868350Seric { 127968350Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 128068350Seric break; 128168350Seric } 128268350Seric if (i == max_col) 128368350Seric { 128468350Seric if (tTd(38, 2)) 128568350Seric printf("nisplus_map_open(%s): can not find key column %s\n", 128668350Seric map->map_file, map->map_keycolnm); 128768350Seric errno = EBADR; 128868350Seric return FALSE; 128968350Seric } 129068350Seric 129168350Seric /* default value column is the last column */ 129268350Seric if (map->map_valcolnm == NULL) 129368350Seric { 129468350Seric map->map_valcolno = max_col - 1; 129568350Seric return TRUE; 129668350Seric } 129768350Seric 129868350Seric for (i=0; i< max_col; i++) 129968350Seric { 130068350Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 130168350Seric { 130268350Seric map->map_valcolno = i; 130368350Seric return TRUE; 130468350Seric } 130568350Seric } 130668350Seric 130768350Seric if (tTd(38, 2)) 130868350Seric printf("nisplus_map_open(%s): can not find column %s\n", 130968350Seric map->map_file, map->map_keycolnm); 131068350Seric errno = EBADR; 131168350Seric return FALSE; 131267848Seric } 131367848Seric 131467848Seric 131567848Seric /* 131668350Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 131767848Seric */ 131867848Seric 131968350Seric char * 132068350Seric nisplus_map_lookup(map, name, av, statp) 132167848Seric MAP *map; 132268350Seric char *name; 132368350Seric char **av; 132468350Seric int *statp; 132567848Seric { 132668350Seric char *vp; 132768350Seric auto int vsize; 132868350Seric int buflen; 132968350Seric char search_key[MAXNAME + 1]; 133068350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 133168350Seric nis_result *result; 133268350Seric 133368350Seric if (tTd(38, 20)) 133468350Seric printf("nisplus_map_lookup(%s, %s)\n", 133568350Seric map->map_mname, name); 133668350Seric 133768350Seric if (!bitset(MF_OPEN, map->map_mflags)) 133868350Seric { 133968350Seric if (nisplus_map_open(map, O_RDONLY)) 134068350Seric map->map_mflags |= MF_OPEN; 134168350Seric else 134268350Seric { 134368350Seric *statp = EX_UNAVAILABLE; 134468350Seric return NULL; 134568350Seric } 134668350Seric } 134768350Seric 134868350Seric buflen = strlen(name); 134968350Seric if (buflen > sizeof search_key - 1) 135068350Seric buflen = sizeof search_key - 1; 135168350Seric bcopy(name, search_key, buflen + 1); 135268350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 135368350Seric makelower(search_key); 135468350Seric 135568350Seric /* construct the query */ 135668350Seric if (PARTIAL_NAME(map->map_file)) 135768350Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 135868350Seric search_key, map->map_file, map->map_domain); 135968350Seric else 136068350Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 136168350Seric search_key, map->map_file); 136268350Seric 136368350Seric if (tTd(38, 20)) 136468350Seric printf("qbuf=%s\n", qbuf); 136568350Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 136668350Seric if (result->status == NIS_SUCCESS) 136768350Seric { 136868350Seric int count; 136968350Seric char *str; 137068350Seric 137168350Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 137268350Seric { 137368350Seric if (LogLevel > 10) 137468350Seric syslog(LOG_WARNING, 137568350Seric "%s:Lookup error, expected 1 entry, got (%d)", 137668350Seric map->map_file, count); 137768350Seric 137868350Seric /* ignore second entry */ 137968350Seric if (tTd(38, 20)) 138068350Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 138168350Seric name, count); 138268350Seric } 138368350Seric 138468350Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 138568350Seric /* set the length of the result */ 138668350Seric if (vp == NULL) 138768350Seric vp = ""; 138868350Seric vsize = strlen(vp); 138968350Seric if (tTd(38, 20)) 139068350Seric printf("nisplus_map_lookup(%s), found %s\n", 139168350Seric name, vp); 139268350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 139368350Seric str = map_rewrite(map, name, strlen(name), NULL); 139468350Seric else 139568350Seric str = map_rewrite(map, vp, vsize, av); 139668350Seric nis_freeresult(result); 139768350Seric #ifdef MAP_EXIT_STAT 139868350Seric *statp = EX_OK; 139968350Seric #endif 140068350Seric return str; 140168350Seric } 140268350Seric else 140368350Seric { 140468350Seric #ifdef MAP_EXIT_STAT 140568350Seric if (result->status == NIS_NOTFOUND) 140668350Seric *statp = EX_NOTFOUND; 140768350Seric else if (result->status == NIS_TRYAGAIN) 140868350Seric *statp = EX_TEMPFAIL; 140968350Seric else 141068350Seric { 141168350Seric *statp = EX_UNAVAILABLE; 141268350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 141368350Seric } 141468350Seric #else 141568350Seric if ((result->status != NIS_NOTFOUND) && 141668350Seric (result->status != NIS_TRYAGAIN)) 141768350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 141868350Seric #endif 141968350Seric } 142068350Seric if (tTd(38, 20)) 142168350Seric printf("nisplus_map_lookup(%s), failed\n", name); 142268350Seric nis_freeresult(result); 142368350Seric return NULL; 142467848Seric } 142567848Seric 142668350Seric 142768350Seric char * 142868350Seric nisplus_default_domain() 142968350Seric { 143068528Seric static char default_domain[MAXNAME + 1] = ""; 143168350Seric char *p; 143268350Seric 143368350Seric if (default_domain[0] != '\0') 143468350Seric return(default_domain); 143568350Seric 143668458Seric p = nis_local_directory(); 143768350Seric strcpy(default_domain, p); 143868458Seric return default_domain; 143968350Seric } 144068350Seric 144168350Seric #endif /* NISPLUS */ 144267848Seric /* 144368350Seric ** HESIOD Modules 144468350Seric */ 144568350Seric 144668350Seric #ifdef HESIOD 144768350Seric 144868350Seric #include <hesiod.h> 144968350Seric 145068350Seric char * 145168350Seric hes_map_lookup(map, name, av, statp) 145268350Seric MAP *map; 145368350Seric char *name; 145468350Seric char **av; 145568350Seric int *statp; 145668350Seric { 145768350Seric char **hp; 145868350Seric char *retdata = NULL; 145968350Seric int i; 146068350Seric 146168350Seric if (tTd(38, 20)) 146268350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 146368350Seric 146468350Seric hp = hes_resolve(name, map->map_file); 146568350Seric if (hp == NULL) 146668350Seric return NULL; 146768350Seric 146868350Seric if (hp[0] != NULL) 146968350Seric { 147068350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 147168350Seric retdata = map_rewrite(map, name, strlen(name), NULL); 147268350Seric else 147368350Seric retdata = map_rewrite(map, hp[0], strlen(hp[0]), av); 147468350Seric } 147568350Seric 147668350Seric for (i = 0; hp[i] != NULL; i++) 147768350Seric free(hp[i]); 147868350Seric free(hp); 147968350Seric return retdata; 148068350Seric } 148168350Seric 148268350Seric #endif 148368350Seric /* 148468350Seric ** NeXT NETINFO Modules 148568350Seric */ 148668350Seric 148768350Seric #ifdef NETINFO 148868350Seric 148968350Seric #define NETINFO_DEFAULT_DIR "/aliases" 149068350Seric #define NETINFO_DEFAULT_PROPERTY "members" 149168350Seric 149268350Seric 149368350Seric /* 149468350Seric ** NI_MAP_OPEN -- open NetInfo Aliases 149568350Seric */ 149668350Seric 149768350Seric bool 149868350Seric ni_map_open(map, mode) 149968350Seric MAP *map; 150068350Seric int mode; 150168350Seric { 150268350Seric char *p; 150368350Seric 150468350Seric if (tTd(38, 20)) 150568350Seric printf("ni_map_open: %s\n", map->map_file); 150668350Seric 150768350Seric if (*map->map_file == '\0') 150868350Seric map->map_file = NETINFO_DEFAULT_DIR; 150968350Seric 151068350Seric if (map->map_valcolnm == NULL) 151168350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 151268350Seric 151368350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 151468350Seric map->map_coldelim = ','; 151568350Seric 151668350Seric return TRUE; 151768350Seric } 151868350Seric 151968350Seric 152068350Seric /* 152168350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 152268350Seric */ 152368350Seric 152468350Seric char * 152568350Seric ni_map_lookup(map, name, av, statp) 152668350Seric MAP *map; 152768350Seric char *name; 152868350Seric char **av; 152968350Seric int *statp; 153068350Seric { 153168350Seric char *res; 153268350Seric char *propval; 153368350Seric extern char *ni_propval(); 153468350Seric 153568350Seric if (tTd(38, 20)) 153668350Seric printf("ni_map_lookup(%s, %s)\n", 153768350Seric map->map_mname, name); 153868350Seric 153968350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 154068350Seric map->map_valcolnm, map->map_coldelim); 154168350Seric 154268350Seric if (propval == NULL) 154368350Seric return NULL; 154468350Seric 154568350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 154668350Seric res = map_rewrite(map, name, strlen(name), NULL); 154768350Seric else 154868350Seric res = map_rewrite(map, propval, strlen(propval), av); 154968350Seric free(propval); 155068350Seric return res; 155168350Seric } 155268350Seric 155368350Seric #endif 155468350Seric /* 155568350Seric ** TEXT (unindexed text file) Modules 155668350Seric ** 155768350Seric ** This code donated by Sun Microsystems. 155868350Seric */ 155968350Seric 156068350Seric 156168350Seric /* 156268350Seric ** TEXT_MAP_OPEN -- open text table 156368350Seric */ 156468350Seric 156568350Seric bool 156668350Seric text_map_open(map, mode) 156768350Seric MAP *map; 156868350Seric int mode; 156968350Seric { 157068350Seric struct stat sbuf; 157168350Seric 157268350Seric if (tTd(38, 2)) 157368350Seric printf("text_map_open(%s, %s, %d)\n", 157468350Seric map->map_mname, map->map_file, mode); 157568350Seric 157668350Seric if (mode != O_RDONLY) 157768350Seric { 157868350Seric errno = ENODEV; 157968350Seric return FALSE; 158068350Seric } 158168350Seric 158268350Seric if (*map->map_file == '\0') 158368350Seric { 158468350Seric if (tTd(38, 2)) 158568350Seric printf("text_map_open: file name required\n"); 158668350Seric return FALSE; 158768350Seric } 158868350Seric 158968350Seric if (map->map_file[0] != '/') 159068350Seric { 159168350Seric if (tTd(38, 2)) 159268350Seric printf("text_map_open(%s): file name must be fully qualified\n", 159368350Seric map->map_file); 159468350Seric return FALSE; 159568350Seric } 159668350Seric /* check to see if this map actually accessable */ 159768350Seric if (access(map->map_file, R_OK) <0) 159868350Seric return FALSE; 159968350Seric 160068350Seric /* check to see if this map actually exist */ 160168350Seric if (stat(map->map_file, &sbuf) <0) 160268350Seric { 160368350Seric if (tTd(38, 2)) 160468350Seric printf("text_map_open(%s): can not stat %s\n", 160568350Seric map->map_file, map->map_file); 160668350Seric return FALSE; 160768350Seric } 160868350Seric 160968350Seric if (!S_ISREG(sbuf.st_mode)) 161068350Seric { 161168350Seric if (tTd(38, 2)) 161268350Seric printf("text_map_open(%s): %s is not a file\n", 161368350Seric map->map_file, map->map_file); 161468350Seric return FALSE; 161568350Seric } 161668350Seric 161768350Seric if (map->map_keycolnm == NULL) 161868350Seric map->map_keycolno = 0; 161968350Seric else 162068350Seric { 162168350Seric if (!isdigit(*map->map_keycolnm)) 162268350Seric { 162368350Seric if (tTd(38, 2)) 162468350Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 162568350Seric map->map_file, map->map_keycolnm); 162668350Seric return FALSE; 162768350Seric } 162868350Seric map->map_keycolno = atoi(map->map_keycolnm); 162968350Seric } 163068350Seric 163168350Seric if (map->map_valcolnm == NULL) 163268350Seric map->map_valcolno = 0; 163368350Seric else 163468350Seric { 163568350Seric if (!isdigit(*map->map_valcolnm)) 163668350Seric { 163768350Seric if (tTd(38, 2)) 163868350Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 163968350Seric map->map_file, map->map_valcolnm); 164068350Seric return FALSE; 164168350Seric } 164268350Seric map->map_valcolno = atoi(map->map_valcolnm); 164368350Seric } 164468350Seric 164568350Seric if (tTd(38, 2)) 164668350Seric { 164768520Seric printf("text_map_open(%s): delimiter = ", 164868520Seric map->map_file); 164968520Seric if (map->map_coldelim == '\0') 165068520Seric printf("(white space)\n"); 165168520Seric else 165268520Seric printf("%c\n", map->map_coldelim); 165368350Seric } 165468350Seric 165568350Seric return TRUE; 165668350Seric } 165768350Seric 165868350Seric 165968350Seric /* 166068350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 166168350Seric */ 166268350Seric 166368350Seric char * 166468350Seric text_map_lookup(map, name, av, statp) 166568350Seric MAP *map; 166668350Seric char *name; 166768350Seric char **av; 166868350Seric int *statp; 166968350Seric { 167068350Seric char *vp; 167168350Seric auto int vsize; 167268350Seric int buflen; 167368350Seric char search_key[MAXNAME + 1]; 167468350Seric char linebuf[MAXLINE]; 167568350Seric FILE *f; 167668528Seric char buf[MAXNAME + 1]; 167768350Seric char delim; 167868350Seric int key_idx; 167968350Seric bool found_it; 168068350Seric extern char *get_column(); 168168350Seric 168268350Seric 168368350Seric found_it = FALSE; 168468350Seric if (tTd(38, 20)) 168568350Seric printf("text_map_lookup(%s)\n", name); 168668350Seric 168768350Seric buflen = strlen(name); 168868350Seric if (buflen > sizeof search_key - 1) 168968350Seric buflen = sizeof search_key - 1; 169068350Seric bcopy(name, search_key, buflen + 1); 169168350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 169268350Seric makelower(search_key); 169368350Seric 169468350Seric f = fopen(map->map_file, "r"); 169568350Seric if (f == NULL) 169668350Seric { 169768350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 169868350Seric *statp = EX_UNAVAILABLE; 169968350Seric return NULL; 170068350Seric } 170168350Seric key_idx = map->map_keycolno; 170268350Seric delim = map->map_coldelim; 170368350Seric while (fgets(linebuf, MAXLINE, f)) 170468350Seric { 170568350Seric char *lf; 170668350Seric if (linebuf[0] == '#') 170768350Seric continue; /* skip comment line */ 170868350Seric if (lf = strchr(linebuf, '\n')) 170968350Seric *lf = '\0'; 171068350Seric if (!strcasecmp(search_key, 171168350Seric get_column(linebuf, key_idx, delim, buf))) 171268350Seric { 171368350Seric found_it = TRUE; 171468350Seric break; 171568350Seric } 171668350Seric } 171768350Seric fclose(f); 171868350Seric if (!found_it) 171968350Seric { 172068350Seric #ifdef MAP_EXIT_STAT 172168350Seric *statp = EX_NOTFOUND; 172268350Seric #endif 172368350Seric return(NULL); 172468350Seric } 172568350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 172668350Seric vsize = strlen(vp); 172768350Seric #ifdef MAP_EXIT_STAT 172868350Seric *statp = EX_OK; 172968350Seric #endif 173068350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 173168350Seric return map_rewrite(map, name, strlen(name), NULL); 173268350Seric else 173368350Seric return map_rewrite(map, vp, vsize, av); 173468350Seric } 173568350Seric /* 173660089Seric ** STAB (Symbol Table) Modules 173760089Seric */ 173860089Seric 173960089Seric 174060089Seric /* 174160207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 174260089Seric */ 174360089Seric 174460089Seric char * 174561707Seric stab_map_lookup(map, name, av, pstat) 174660089Seric register MAP *map; 174760089Seric char *name; 174861707Seric char **av; 174961707Seric int *pstat; 175060089Seric { 175160089Seric register STAB *s; 175260089Seric 175360537Seric if (tTd(38, 20)) 175468350Seric printf("stab_lookup(%s, %s)\n", 175568350Seric map->map_mname, name); 175660089Seric 175760089Seric s = stab(name, ST_ALIAS, ST_FIND); 175860089Seric if (s != NULL) 175960089Seric return (s->s_alias); 176060089Seric return (NULL); 176160089Seric } 176260089Seric 176360089Seric 176460089Seric /* 176560207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 176660089Seric */ 176760089Seric 176860089Seric void 176960089Seric stab_map_store(map, lhs, rhs) 177060089Seric register MAP *map; 177160089Seric char *lhs; 177260089Seric char *rhs; 177360089Seric { 177460089Seric register STAB *s; 177560089Seric 177660089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 177760089Seric s->s_alias = newstr(rhs); 177860089Seric } 177960089Seric 178060089Seric 178160089Seric /* 178260207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 178360207Seric ** 178460207Seric ** This is a wierd case -- it is only intended as a fallback for 178560207Seric ** aliases. For this reason, opens for write (only during a 178660207Seric ** "newaliases") always fails, and opens for read open the 178760207Seric ** actual underlying text file instead of the database. 178860089Seric */ 178960089Seric 179060089Seric bool 179160089Seric stab_map_open(map, mode) 179260089Seric register MAP *map; 179360089Seric int mode; 179460089Seric { 179563835Seric FILE *af; 179664284Seric struct stat st; 179763835Seric 179860537Seric if (tTd(38, 2)) 179968350Seric printf("stab_map_open(%s, %s)\n", 180068350Seric map->map_mname, map->map_file); 180160089Seric 180260089Seric if (mode != O_RDONLY) 180360207Seric { 180460207Seric errno = ENODEV; 180560089Seric return FALSE; 180660207Seric } 180760089Seric 180863835Seric af = fopen(map->map_file, "r"); 180963835Seric if (af == NULL) 181063835Seric return FALSE; 181168350Seric readaliases(map, af, FALSE, FALSE); 181264284Seric 181364284Seric if (fstat(fileno(af), &st) >= 0) 181464284Seric map->map_mtime = st.st_mtime; 181563835Seric fclose(af); 181663835Seric 181760089Seric return TRUE; 181860089Seric } 181960089Seric /* 182060089Seric ** Implicit Modules 182156822Seric ** 182260089Seric ** Tries several types. For back compatibility of aliases. 182356822Seric */ 182456822Seric 182560089Seric 182660089Seric /* 182760207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 182860089Seric */ 182960089Seric 183060089Seric char * 183160089Seric impl_map_lookup(map, name, av, pstat) 183260089Seric MAP *map; 183360089Seric char *name; 183456822Seric char **av; 183560089Seric int *pstat; 183656822Seric { 183760537Seric if (tTd(38, 20)) 183868350Seric printf("impl_map_lookup(%s, %s)\n", 183968350Seric map->map_mname, name); 184056822Seric 184160089Seric #ifdef NEWDB 184260207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 184360089Seric return db_map_lookup(map, name, av, pstat); 184460089Seric #endif 184560089Seric #ifdef NDBM 184660207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 184760089Seric return ndbm_map_lookup(map, name, av, pstat); 184860089Seric #endif 184960089Seric return stab_map_lookup(map, name, av, pstat); 185060089Seric } 185160089Seric 185260089Seric /* 185360207Seric ** IMPL_MAP_STORE -- store in open databases 185460089Seric */ 185560089Seric 185660089Seric void 185760089Seric impl_map_store(map, lhs, rhs) 185860089Seric MAP *map; 185960089Seric char *lhs; 186060089Seric char *rhs; 186160089Seric { 186260089Seric #ifdef NEWDB 186360207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 186460089Seric db_map_store(map, lhs, rhs); 186560089Seric #endif 186660089Seric #ifdef NDBM 186760207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 186860089Seric ndbm_map_store(map, lhs, rhs); 186960089Seric #endif 187060089Seric stab_map_store(map, lhs, rhs); 187160089Seric } 187260089Seric 187360089Seric /* 187460089Seric ** IMPL_MAP_OPEN -- implicit database open 187560089Seric */ 187660089Seric 187760089Seric bool 187860089Seric impl_map_open(map, mode) 187960089Seric MAP *map; 188060089Seric int mode; 188160089Seric { 188260089Seric struct stat stb; 188360089Seric 188460537Seric if (tTd(38, 2)) 188568350Seric printf("impl_map_open(%s, %s, %d)\n", 188668350Seric map->map_mname, map->map_file, mode); 188760089Seric 188860089Seric if (stat(map->map_file, &stb) < 0) 188956822Seric { 189060089Seric /* no alias file at all */ 189164718Seric if (tTd(38, 3)) 189264718Seric printf("no map file\n"); 189360089Seric return FALSE; 189456822Seric } 189556822Seric 189660089Seric #ifdef NEWDB 189760207Seric map->map_mflags |= MF_IMPL_HASH; 189860089Seric if (hash_map_open(map, mode)) 189956822Seric { 190064250Seric #if defined(NDBM) && defined(NIS) 190160561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 190260207Seric #endif 190360207Seric return TRUE; 190460089Seric } 190560207Seric else 190660207Seric map->map_mflags &= ~MF_IMPL_HASH; 190760089Seric #endif 190860089Seric #ifdef NDBM 190960207Seric map->map_mflags |= MF_IMPL_NDBM; 191060089Seric if (ndbm_map_open(map, mode)) 191160089Seric { 191260089Seric return TRUE; 191360089Seric } 191460207Seric else 191560207Seric map->map_mflags &= ~MF_IMPL_NDBM; 191660089Seric #endif 191756822Seric 191864650Seric #if defined(NEWDB) || defined(NDBM) 191960089Seric if (Verbose) 192060089Seric message("WARNING: cannot open alias database %s", map->map_file); 192164964Seric #else 192264964Seric if (mode != O_RDONLY) 192364964Seric usrerr("Cannot rebuild aliases: no database format defined"); 192460207Seric #endif 192560089Seric 192660207Seric return stab_map_open(map, mode); 192756822Seric } 192860089Seric 192960207Seric 193060089Seric /* 193160207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 193260089Seric */ 193360089Seric 193460089Seric void 193560207Seric impl_map_close(map) 193660089Seric MAP *map; 193760089Seric { 193868350Seric if (tTd(38, 20)) 193968350Seric printf("impl_map_close(%s, %s, %x)\n", 194068350Seric map->map_mname, map->map_file, map->map_mflags); 194160089Seric #ifdef NEWDB 194260207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 194360089Seric { 194460207Seric db_map_close(map); 194560207Seric map->map_mflags &= ~MF_IMPL_HASH; 194660089Seric } 194760089Seric #endif 194860089Seric 194960089Seric #ifdef NDBM 195060207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 195160089Seric { 195260207Seric ndbm_map_close(map); 195360207Seric map->map_mflags &= ~MF_IMPL_NDBM; 195460089Seric } 195560089Seric #endif 195660089Seric } 195760207Seric /* 195868350Seric ** User map class. 195968350Seric ** 196068350Seric ** Provides access to the system password file. 196168350Seric */ 196268350Seric 196368350Seric /* 196468350Seric ** USER_MAP_OPEN -- open user map 196568350Seric ** 196668350Seric ** Really just binds field names to field numbers. 196768350Seric */ 196868350Seric 196968350Seric bool 197068350Seric user_map_open(map, mode) 197168350Seric MAP *map; 197268350Seric int mode; 197368350Seric { 197468350Seric if (tTd(38, 2)) 197568350Seric printf("user_map_open(%s)\n", map->map_mname); 197668350Seric 197768350Seric if (mode != O_RDONLY) 197868350Seric { 197968350Seric /* issue a pseudo-error message */ 198068350Seric #ifdef ENOSYS 198168350Seric errno = ENOSYS; 198268350Seric #else 198368350Seric # ifdef EFTYPE 198468350Seric errno = EFTYPE; 198568350Seric # else 198668350Seric errno = ENXIO; 198768350Seric # endif 198868350Seric #endif 198968350Seric return FALSE; 199068350Seric } 199168350Seric if (map->map_valcolnm == NULL) 199268350Seric /* nothing */ ; 199368350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 199468350Seric map->map_valcolno = 1; 199568350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 199668350Seric map->map_valcolno = 2; 199768350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 199868350Seric map->map_valcolno = 3; 199968350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 200068350Seric map->map_valcolno = 4; 200168350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 200268350Seric map->map_valcolno = 5; 200368350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 200468350Seric map->map_valcolno = 6; 200568350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 200668350Seric map->map_valcolno = 7; 200768350Seric else 200868350Seric { 200968350Seric syserr("User map %s: unknown column name %s", 201068350Seric map->map_mname, map->map_valcolnm); 201168350Seric return FALSE; 201268350Seric } 201368350Seric return TRUE; 201468350Seric } 201568350Seric 201668350Seric 201768350Seric /* 201868350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 201968350Seric */ 202068350Seric 202168350Seric char * 202268350Seric user_map_lookup(map, key, av, statp) 202368350Seric MAP *map; 202468350Seric char *key; 202568350Seric char **av; 202668350Seric int *statp; 202768350Seric { 202868350Seric struct passwd *pw; 202968350Seric 203068350Seric if (tTd(38, 20)) 203168350Seric printf("user_map_lookup(%s, %s)\n", 203268350Seric map->map_mname, key); 203368350Seric 203468693Seric pw = sm_getpwnam(key); 203568350Seric if (pw == NULL) 203668350Seric return NULL; 203768350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 203868350Seric return map_rewrite(map, key, strlen(key), NULL); 203968350Seric else 204068350Seric { 204168433Seric char *rwval = NULL; 204268350Seric char buf[30]; 204368350Seric 204468350Seric switch (map->map_valcolno) 204568350Seric { 204668350Seric case 0: 204768350Seric case 1: 204868350Seric rwval = pw->pw_name; 204968350Seric break; 205068350Seric 205168350Seric case 2: 205268350Seric rwval = pw->pw_passwd; 205368350Seric break; 205468350Seric 205568350Seric case 3: 205668350Seric sprintf(buf, "%d", pw->pw_uid); 205768350Seric rwval = buf; 205868350Seric break; 205968350Seric 206068350Seric case 4: 206168350Seric sprintf(buf, "%d", pw->pw_gid); 206268350Seric rwval = buf; 206368350Seric break; 206468350Seric 206568350Seric case 5: 206668350Seric rwval = pw->pw_gecos; 206768350Seric break; 206868350Seric 206968350Seric case 6: 207068350Seric rwval = pw->pw_dir; 207168350Seric break; 207268350Seric 207368350Seric case 7: 207468350Seric rwval = pw->pw_shell; 207568350Seric break; 207668350Seric } 207768350Seric return map_rewrite(map, rwval, strlen(rwval), av); 207868350Seric } 207968350Seric } 208068350Seric /* 208168350Seric ** BESTMX -- find the best MX for a name 208268350Seric ** 208368350Seric ** This is really a hack, but I don't see any obvious way 208468350Seric ** to generalize it at the moment. 208568350Seric */ 208668350Seric 208768350Seric #if NAMED_BIND 208868350Seric 208968350Seric char * 209068350Seric bestmx_map_lookup(map, name, av, statp) 209168350Seric MAP *map; 209268350Seric char *name; 209368350Seric char **av; 209468350Seric int *statp; 209568350Seric { 209668350Seric int nmx; 209768350Seric auto int rcode; 209868350Seric char *mxhosts[MAXMXHOSTS + 1]; 209968350Seric 210068350Seric nmx = getmxrr(name, mxhosts, FALSE, &rcode); 210168350Seric if (nmx <= 0) 210268350Seric return NULL; 210368350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 210468350Seric return map_rewrite(map, name, strlen(name), NULL); 210568350Seric else 210668350Seric return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 210768350Seric } 210868350Seric 210968350Seric #endif 211068350Seric /* 211168350Seric ** Sequenced map type. 211268350Seric ** 211368350Seric ** Tries each map in order until something matches, much like 211468350Seric ** implicit. Stores go to the first map in the list that can 211568350Seric ** support storing. 211668350Seric ** 211768350Seric ** This is slightly unusual in that there are two interfaces. 211868350Seric ** The "sequence" interface lets you stack maps arbitrarily. 211968350Seric ** The "switch" interface builds a sequence map by looking 212068350Seric ** at a system-dependent configuration file such as 212168350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 212268350Seric ** 212368350Seric ** We don't need an explicit open, since all maps are 212468350Seric ** opened during startup, including underlying maps. 212568350Seric */ 212668350Seric 212768350Seric /* 212868350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 212968350Seric */ 213068350Seric 213168350Seric bool 213268350Seric seq_map_parse(map, ap) 213368350Seric MAP *map; 213468350Seric char *ap; 213568350Seric { 213668350Seric int maxmap; 213768350Seric 213868350Seric if (tTd(38, 2)) 213968350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 214068350Seric maxmap = 0; 214168350Seric while (*ap != '\0') 214268350Seric { 214368350Seric register char *p; 214468350Seric STAB *s; 214568350Seric 214668350Seric /* find beginning of map name */ 214768350Seric while (isascii(*ap) && isspace(*ap)) 214868350Seric ap++; 214968350Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 215068350Seric continue; 215168350Seric if (*p != '\0') 215268350Seric *p++ = '\0'; 215368350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 215468350Seric p++; 215568350Seric if (*ap == '\0') 215668350Seric { 215768350Seric ap = p; 215868350Seric continue; 215968350Seric } 216068350Seric s = stab(ap, ST_MAP, ST_FIND); 216168350Seric if (s == NULL) 216268350Seric { 216368350Seric syserr("Sequence map %s: unknown member map %s", 216468350Seric map->map_mname, ap); 216568350Seric } 216668350Seric else if (maxmap == MAXMAPSTACK) 216768350Seric { 216868350Seric syserr("Sequence map %s: too many member maps (%d max)", 216968350Seric map->map_mname, MAXMAPSTACK); 217068350Seric maxmap++; 217168350Seric } 217268350Seric else if (maxmap < MAXMAPSTACK) 217368350Seric { 217468350Seric map->map_stack[maxmap++] = &s->s_map; 217568350Seric } 217668350Seric ap = p; 217768350Seric } 217868350Seric return TRUE; 217968350Seric } 218068350Seric 218168350Seric 218268350Seric /* 218368350Seric ** SWITCH_MAP_OPEN -- open a switched map 218468350Seric ** 218568350Seric ** This looks at the system-dependent configuration and builds 218668350Seric ** a sequence map that does the same thing. 218768350Seric ** 218868350Seric ** Every system must define a switch_map_find routine in conf.c 218968350Seric ** that will return the list of service types associated with a 219068350Seric ** given service class. 219168350Seric */ 219268350Seric 219368350Seric bool 219468350Seric switch_map_open(map, mode) 219568350Seric MAP *map; 219668350Seric int mode; 219768350Seric { 219868350Seric int mapno; 219968350Seric int nmaps; 220068350Seric char *maptype[MAXMAPSTACK]; 220168350Seric 220268350Seric if (tTd(38, 2)) 220368350Seric printf("switch_map_open(%s, %s, %d)\n", 220468350Seric map->map_mname, map->map_file, mode); 220568350Seric 220668350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 220768350Seric if (tTd(38, 19)) 220868350Seric { 220968350Seric printf("\tswitch_map_find => %d\n", nmaps); 221068350Seric for (mapno = 0; mapno < nmaps; mapno++) 221168350Seric printf("\t\t%s\n", maptype[mapno]); 221268350Seric } 221368350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 221468350Seric return FALSE; 221568350Seric 221668350Seric for (mapno = 0; mapno < nmaps; mapno++) 221768350Seric { 221868350Seric register STAB *s; 221968350Seric char nbuf[MAXNAME + 1]; 222068350Seric 222168350Seric if (maptype[mapno] == NULL) 222268350Seric continue; 222368350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 222468350Seric s = stab(nbuf, ST_MAP, ST_FIND); 222568350Seric if (s == NULL) 222668350Seric { 222768350Seric syserr("Switch map %s: unknown member map %s", 222868350Seric map->map_mname, nbuf); 222968350Seric } 223068350Seric else 223168350Seric { 223268350Seric map->map_stack[mapno] = &s->s_map; 223368350Seric if (tTd(38, 4)) 223468350Seric printf("\tmap_stack[%d] = %s:%s\n", 223568350Seric mapno, s->s_map.map_class->map_cname, 223668350Seric nbuf); 223768350Seric } 223868350Seric } 223968350Seric return TRUE; 224068350Seric } 224168350Seric 224268350Seric 224368350Seric /* 224468350Seric ** SEQ_MAP_CLOSE -- close all underlying maps 224568350Seric */ 224668350Seric 224768350Seric seq_map_close(map) 224868350Seric MAP *map; 224968350Seric { 225068350Seric int mapno; 225168350Seric 225268350Seric if (tTd(38, 20)) 225368350Seric printf("seq_map_close(%s)\n", map->map_mname); 225468350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 225568350Seric { 225668350Seric MAP *mm = map->map_stack[mapno]; 225768350Seric 225868350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 225968350Seric continue; 226068350Seric mm->map_class->map_close(mm); 226168798Seric mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 226268350Seric } 226368350Seric } 226468350Seric 226568350Seric 226668350Seric /* 226768350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 226868350Seric */ 226968350Seric 227068350Seric char * 227168350Seric seq_map_lookup(map, key, args, pstat) 227268350Seric MAP *map; 227368350Seric char *key; 227468350Seric char **args; 227568350Seric int *pstat; 227668350Seric { 227768350Seric int mapno; 227868350Seric int mapbit = 0x01; 227968350Seric 228068350Seric if (tTd(38, 20)) 228168350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 228268350Seric 228368350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 228468350Seric { 228568350Seric MAP *mm = map->map_stack[mapno]; 228668350Seric int stat = 0; 228768350Seric char *rv; 228868350Seric 228968350Seric if (mm == NULL) 229068350Seric continue; 229168350Seric if (!bitset(MF_OPEN, mm->map_mflags)) 229268350Seric { 229368350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 229468350Seric { 229568350Seric *pstat = EX_UNAVAILABLE; 229668350Seric return NULL; 229768350Seric } 229868350Seric continue; 229968350Seric } 230068350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 230168350Seric if (rv != NULL) 230268350Seric return rv; 230368350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 230468350Seric return NULL; 230568350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 230668350Seric { 230768350Seric *pstat = stat; 230868350Seric return NULL; 230968350Seric } 231068350Seric } 231168350Seric return NULL; 231268350Seric } 231368350Seric 231468350Seric 231568350Seric /* 231668350Seric ** SEQ_MAP_STORE -- sequenced map store 231768350Seric */ 231868350Seric 231968350Seric void 232068350Seric seq_map_store(map, key, val) 232168350Seric MAP *map; 232268350Seric char *key; 232368350Seric char *val; 232468350Seric { 232568350Seric int mapno; 232668350Seric 232768350Seric if (tTd(38, 12)) 232868350Seric printf("seq_map_store(%s, %s, %s)\n", 232968350Seric map->map_mname, key, val); 233068350Seric 233168350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 233268350Seric { 233368350Seric MAP *mm = map->map_stack[mapno]; 233468350Seric 233568350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 233668350Seric continue; 233768350Seric 233868350Seric mm->map_class->map_store(mm, key, val); 233968350Seric return; 234068350Seric } 234168350Seric syserr("seq_map_store(%s, %s, %s): no writable map", 234268350Seric map->map_mname, key, val); 234368350Seric } 234468350Seric /* 234560207Seric ** NULL stubs 234660089Seric */ 234760089Seric 234860207Seric bool 234960207Seric null_map_open(map, mode) 235060089Seric MAP *map; 235160207Seric int mode; 235260089Seric { 235360207Seric return TRUE; 235460089Seric } 235560089Seric 235660207Seric void 235760207Seric null_map_close(map) 235860207Seric MAP *map; 235960089Seric { 236060207Seric return; 236160207Seric } 236260089Seric 236360207Seric void 236460207Seric null_map_store(map, key, val) 236560207Seric MAP *map; 236660207Seric char *key; 236760207Seric char *val; 236860089Seric { 236960207Seric return; 237060089Seric } 237168350Seric 237268350Seric 237368350Seric /* 237468350Seric ** BOGUS stubs 237568350Seric */ 237668350Seric 237768350Seric char * 237868350Seric bogus_map_lookup(map, key, args, pstat) 237968350Seric MAP *map; 238068350Seric char *key; 238168350Seric char **args; 238268350Seric int *pstat; 238368350Seric { 238468350Seric *pstat = EX_TEMPFAIL; 238568350Seric return NULL; 238668350Seric } 238768350Seric 238868350Seric MAPCLASS BogusMapClass = 238968350Seric { 239068350Seric "bogus-map", NULL, 0, 239168350Seric NULL, bogus_map_lookup, null_map_store, 239268350Seric null_map_open, null_map_close, 239368350Seric }; 2394