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*69688Seric static char sccsid[] = "@(#)map.c 8.67 (Berkeley) 05/25/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 2269651Seric struct dom_binding; /* forward reference 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. 6069401Seric ** 6169401Seric ** This file also includes the implementation for getcanonname. 6269401Seric ** It is currently implemented in a pretty ad-hoc manner; it ought 6369401Seric ** to be more properly integrated into the map structure. 6460089Seric */ 6560089Seric 6660089Seric #define DBMMODE 0644 6764718Seric 6864718Seric extern bool aliaswait __P((MAP *, char *, int)); 6960089Seric /* 7060089Seric ** MAP_PARSEARGS -- parse config line arguments for database lookup 7160089Seric ** 7260089Seric ** This is a generic version of the map_parse method. 7360089Seric ** 7456822Seric ** Parameters: 7560089Seric ** map -- the map being initialized. 7660089Seric ** ap -- a pointer to the args on the config line. 7756822Seric ** 7856822Seric ** Returns: 7960089Seric ** TRUE -- if everything parsed OK. 8056822Seric ** FALSE -- otherwise. 8156822Seric ** 8256822Seric ** Side Effects: 8360089Seric ** null terminates the filename; stores it in map 8456822Seric */ 8556822Seric 8656822Seric bool 8760089Seric map_parseargs(map, ap) 8856822Seric MAP *map; 8960089Seric char *ap; 9056822Seric { 9160089Seric register char *p = ap; 9256822Seric 9363753Seric map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; 9460089Seric for (;;) 9560089Seric { 9660089Seric while (isascii(*p) && isspace(*p)) 9760089Seric p++; 9860089Seric if (*p != '-') 9960089Seric break; 10060089Seric switch (*++p) 10160089Seric { 10260089Seric case 'N': 10360207Seric map->map_mflags |= MF_INCLNULL; 10463753Seric map->map_mflags &= ~MF_TRY0NULL; 10560089Seric break; 10660089Seric 10763753Seric case 'O': 10863753Seric map->map_mflags &= ~MF_TRY1NULL; 10963753Seric break; 11063753Seric 11160089Seric case 'o': 11260207Seric map->map_mflags |= MF_OPTIONAL; 11360089Seric break; 11460089Seric 11560089Seric case 'f': 11660207Seric map->map_mflags |= MF_NOFOLDCASE; 11760089Seric break; 11860089Seric 11960089Seric case 'm': 12060207Seric map->map_mflags |= MF_MATCHONLY; 12160089Seric break; 12260089Seric 12368497Seric case 'A': 12468497Seric map->map_mflags |= MF_APPEND; 12568497Seric break; 12668497Seric 12760089Seric case 'a': 12860089Seric map->map_app = ++p; 12960089Seric break; 13068350Seric 13168350Seric case 'k': 13268350Seric while (isascii(*++p) && isspace(*p)) 13368350Seric continue; 13468350Seric map->map_keycolnm = p; 13568350Seric break; 13668350Seric 13768350Seric case 'v': 13868350Seric while (isascii(*++p) && isspace(*p)) 13968350Seric continue; 14068350Seric map->map_valcolnm = p; 14168350Seric break; 14268350Seric 14368350Seric case 'z': 14468350Seric if (*++p != '\\') 14568350Seric map->map_coldelim = *p; 14668350Seric else 14768350Seric { 14868350Seric switch (*++p) 14968350Seric { 15068350Seric case 'n': 15168350Seric map->map_coldelim = '\n'; 15268350Seric break; 15368350Seric 15468350Seric case 't': 15568350Seric map->map_coldelim = '\t'; 15668350Seric break; 15768350Seric 15868350Seric default: 15968350Seric map->map_coldelim = '\\'; 16068350Seric } 16168350Seric } 16268350Seric break; 16368497Seric #ifdef RESERVED_FOR_SUN 16468497Seric case 'd': 16568497Seric map->map_mflags |= MF_DOMAIN_WIDE; 16668497Seric break; 16768497Seric 16868497Seric case 's': 16968497Seric /* info type */ 17068497Seric break; 17168497Seric #endif 17260089Seric } 17360089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 17460089Seric p++; 17560089Seric if (*p != '\0') 17660089Seric *p++ = '\0'; 17760089Seric } 17860089Seric if (map->map_app != NULL) 17960089Seric map->map_app = newstr(map->map_app); 18068350Seric if (map->map_keycolnm != NULL) 18168350Seric map->map_keycolnm = newstr(map->map_keycolnm); 18268350Seric if (map->map_valcolnm != NULL) 18368350Seric map->map_valcolnm = newstr(map->map_valcolnm); 18460089Seric 18560089Seric if (*p != '\0') 18660089Seric { 18760089Seric map->map_file = p; 18860089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 18960089Seric p++; 19060089Seric if (*p != '\0') 19160089Seric *p++ = '\0'; 19260089Seric map->map_file = newstr(map->map_file); 19360089Seric } 19460089Seric 19560089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 19660089Seric p++; 19760089Seric if (*p != '\0') 19860089Seric map->map_rebuild = newstr(p); 19960089Seric 20068350Seric if (map->map_file == NULL && 20168350Seric !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 20257208Seric { 20360089Seric syserr("No file name for %s map %s", 20460089Seric map->map_class->map_cname, map->map_mname); 20556822Seric return FALSE; 20657208Seric } 20760089Seric return TRUE; 20860089Seric } 20960089Seric /* 21060089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 21160089Seric ** 21260089Seric ** It also adds the map_app string. It can be used as a utility 21360089Seric ** in the map_lookup method. 21460089Seric ** 21560089Seric ** Parameters: 21660089Seric ** map -- the map that causes this. 21760089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 21860089Seric ** slen -- the length of s. 21960089Seric ** av -- arguments to interpolate into buf. 22060089Seric ** 22160089Seric ** Returns: 22267895Seric ** Pointer to rewritten result. This is static data that 22367895Seric ** should be copied if it is to be saved! 22460089Seric ** 22560089Seric ** Side Effects: 22660089Seric ** none. 22760089Seric */ 22860089Seric 22960089Seric char * 23060089Seric map_rewrite(map, s, slen, av) 23160089Seric register MAP *map; 23260089Seric register char *s; 23360089Seric int slen; 23460089Seric char **av; 23560089Seric { 23660089Seric register char *bp; 23760089Seric register char c; 23860089Seric char **avp; 23960089Seric register char *ap; 24060089Seric int i; 24160089Seric int len; 24267895Seric static int buflen = -1; 24367895Seric static char *buf = NULL; 24460089Seric 24560537Seric if (tTd(39, 1)) 24660089Seric { 24760256Seric printf("map_rewrite(%.*s), av =", slen, s); 24860256Seric if (av == NULL) 24960256Seric printf(" (nullv)"); 25060256Seric else 25160256Seric { 25260256Seric for (avp = av; *avp != NULL; avp++) 25360256Seric printf("\n\t%s", *avp); 25460256Seric } 25560256Seric printf("\n"); 25660089Seric } 25760089Seric 25860089Seric /* count expected size of output (can safely overestimate) */ 25960089Seric i = len = slen; 26060089Seric if (av != NULL) 26160089Seric { 26260089Seric bp = s; 26360089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 26460089Seric { 26560089Seric if (c != '%') 26660089Seric continue; 26760089Seric if (--i < 0) 26860089Seric break; 26960089Seric c = *bp++; 27060089Seric if (!(isascii(c) && isdigit(c))) 27160089Seric continue; 27263937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 27360089Seric continue; 27460089Seric if (*avp == NULL) 27560089Seric continue; 27660089Seric len += strlen(*avp); 27760089Seric } 27860089Seric } 27960089Seric if (map->map_app != NULL) 28060089Seric len += strlen(map->map_app); 28167895Seric if (buflen < ++len) 28260089Seric { 28360089Seric /* need to malloc additional space */ 28467895Seric buflen = len; 28567895Seric if (buf != NULL) 28667895Seric free(buf); 28767895Seric buf = xalloc(buflen); 28860089Seric } 28960089Seric 29067895Seric bp = buf; 29160089Seric if (av == NULL) 29260089Seric { 29360089Seric bcopy(s, bp, slen); 29460089Seric bp += slen; 29560089Seric } 29660089Seric else 29760089Seric { 29860089Seric while (--slen >= 0 && (c = *s++) != '\0') 29960089Seric { 30060089Seric if (c != '%') 30160089Seric { 30260089Seric pushc: 30360089Seric *bp++ = c; 30460089Seric continue; 30560089Seric } 30660089Seric if (--slen < 0 || (c = *s++) == '\0') 30760089Seric c = '%'; 30860089Seric if (c == '%') 30960089Seric goto pushc; 31060089Seric if (!(isascii(c) && isdigit(c))) 31160089Seric { 31260089Seric *bp++ = '%'; 31360089Seric goto pushc; 31460089Seric } 31563937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 31660089Seric continue; 31760089Seric if (*avp == NULL) 31860089Seric continue; 31960089Seric 32060089Seric /* transliterate argument into output string */ 32160089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 32260089Seric *bp++ = c; 32360089Seric } 32460089Seric } 32560089Seric if (map->map_app != NULL) 32660089Seric strcpy(bp, map->map_app); 32760089Seric else 32860089Seric *bp = '\0'; 32960537Seric if (tTd(39, 1)) 33067895Seric printf("map_rewrite => %s\n", buf); 33167895Seric return buf; 33260089Seric } 33360089Seric /* 33460537Seric ** INITMAPS -- initialize for aliasing 33560537Seric ** 33660537Seric ** Parameters: 33760537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 33860537Seric ** e -- current envelope. 33960537Seric ** 34060537Seric ** Returns: 34160537Seric ** none. 34260537Seric ** 34360537Seric ** Side Effects: 34460537Seric ** initializes aliases: 34560537Seric ** if NDBM: opens the database. 34660537Seric ** if ~NDBM: reads the aliases into the symbol table. 34760537Seric */ 34860537Seric 34960537Seric initmaps(rebuild, e) 35060537Seric bool rebuild; 35160537Seric register ENVELOPE *e; 35260537Seric { 35360537Seric extern void map_init(); 35460537Seric 35564671Seric #ifdef XDEBUG 35664671Seric checkfd012("entering initmaps"); 35764671Seric #endif 35860537Seric CurEnv = e; 35965085Seric if (rebuild) 36065085Seric { 36165085Seric stabapply(map_init, 1); 36265085Seric stabapply(map_init, 2); 36365085Seric } 36465085Seric else 36565085Seric { 36665085Seric stabapply(map_init, 0); 36765085Seric } 36864671Seric #ifdef XDEBUG 36964671Seric checkfd012("exiting initmaps"); 37064671Seric #endif 37160537Seric } 37260537Seric 37360537Seric void 37460537Seric map_init(s, rebuild) 37560537Seric register STAB *s; 37660537Seric int rebuild; 37760537Seric { 37860537Seric register MAP *map; 37960537Seric 38060537Seric /* has to be a map */ 38160537Seric if (s->s_type != ST_MAP) 38260537Seric return; 38360537Seric 38460537Seric map = &s->s_map; 38560537Seric if (!bitset(MF_VALID, map->map_mflags)) 38660537Seric return; 38760537Seric 38860537Seric if (tTd(38, 2)) 38968350Seric printf("map_init(%s:%s, %s, %d)\n", 39064690Seric map->map_class->map_cname == NULL ? "NULL" : 39164690Seric map->map_class->map_cname, 39268350Seric map->map_mname == NULL ? "NULL" : map->map_mname, 39365085Seric map->map_file == NULL ? "NULL" : map->map_file, 39465085Seric rebuild); 39560537Seric 39665085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && 39765085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) 39865085Seric { 39965085Seric if (tTd(38, 3)) 40065085Seric printf("\twrong pass\n"); 40165085Seric return; 40265085Seric } 40365085Seric 40460537Seric /* if already open, close it (for nested open) */ 40560537Seric if (bitset(MF_OPEN, map->map_mflags)) 40660537Seric { 40760537Seric map->map_class->map_close(map); 40860537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 40960537Seric } 41060537Seric 41165085Seric if (rebuild == 2) 41260537Seric { 41365085Seric rebuildaliases(map, FALSE); 41460537Seric } 41560537Seric else 41660537Seric { 41760537Seric if (map->map_class->map_open(map, O_RDONLY)) 41860537Seric { 41960537Seric if (tTd(38, 4)) 42068350Seric printf("\t%s:%s %s: valid\n", 42164690Seric map->map_class->map_cname == NULL ? "NULL" : 42264690Seric map->map_class->map_cname, 42368350Seric map->map_mname == NULL ? "NULL" : 42468350Seric map->map_mname, 42564690Seric map->map_file == NULL ? "NULL" : 42664690Seric map->map_file); 42760537Seric map->map_mflags |= MF_OPEN; 42860537Seric } 42968350Seric else 43068350Seric { 43168350Seric if (tTd(38, 4)) 43268350Seric printf("\t%s:%s %s: invalid: %s\n", 43368350Seric map->map_class->map_cname == NULL ? "NULL" : 43468350Seric map->map_class->map_cname, 43568350Seric map->map_mname == NULL ? "NULL" : 43668350Seric map->map_mname, 43768350Seric map->map_file == NULL ? "NULL" : 43868350Seric map->map_file, 43968350Seric errstring(errno)); 44068350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 44168350Seric { 44268350Seric extern MAPCLASS BogusMapClass; 44368350Seric 44468350Seric map->map_class = &BogusMapClass; 44568350Seric map->map_mflags |= MF_OPEN; 44668350Seric } 44768350Seric } 44860537Seric } 44960537Seric } 45060537Seric /* 45160089Seric ** NDBM modules 45260089Seric */ 45360089Seric 45460089Seric #ifdef NDBM 45560089Seric 45660089Seric /* 45760089Seric ** DBM_MAP_OPEN -- DBM-style map open 45860089Seric */ 45960089Seric 46060089Seric bool 46160089Seric ndbm_map_open(map, mode) 46260089Seric MAP *map; 46360089Seric int mode; 46460089Seric { 46564284Seric register DBM *dbm; 46664284Seric struct stat st; 46760089Seric 46860537Seric if (tTd(38, 2)) 46968350Seric printf("ndbm_map_open(%s, %s, %d)\n", 47068350Seric map->map_mname, map->map_file, mode); 47160089Seric 47260207Seric if (mode == O_RDWR) 47360207Seric mode |= O_CREAT|O_TRUNC; 47460207Seric 47560089Seric /* open the database */ 47660089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 47756822Seric if (dbm == NULL) 47856822Seric { 47964718Seric if (aliaswait(map, ".pag", FALSE)) 48064718Seric return TRUE; 48160207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 48256836Seric syserr("Cannot open DBM database %s", map->map_file); 48356822Seric return FALSE; 48456822Seric } 48560089Seric map->map_db1 = (void *) dbm; 48664964Seric if (mode == O_RDONLY) 48764964Seric { 48864964Seric if (bitset(MF_ALIAS, map->map_mflags) && 48964964Seric !aliaswait(map, ".pag", TRUE)) 49064718Seric return FALSE; 49164964Seric } 49264964Seric else 49364964Seric { 49464964Seric int fd; 49564964Seric 49664964Seric /* exclusive lock for duration of rebuild */ 49764964Seric fd = dbm_dirfno((DBM *) map->map_db1); 49864964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 49964964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 50064964Seric map->map_mflags |= MF_LOCKED; 50164964Seric } 50264718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 50364284Seric map->map_mtime = st.st_mtime; 50456822Seric return TRUE; 50556822Seric } 50660089Seric 50760089Seric 50860089Seric /* 50956822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 51056822Seric */ 51156822Seric 51256822Seric char * 51360089Seric ndbm_map_lookup(map, name, av, statp) 51456822Seric MAP *map; 51560089Seric char *name; 51656822Seric char **av; 51759084Seric int *statp; 51856822Seric { 51956822Seric datum key, val; 52064373Seric int fd; 52160089Seric char keybuf[MAXNAME + 1]; 52256822Seric 52360537Seric if (tTd(38, 20)) 52468350Seric printf("ndbm_map_lookup(%s, %s)\n", 52568350Seric map->map_mname, name); 52660089Seric 52760089Seric key.dptr = name; 52860089Seric key.dsize = strlen(name); 52960207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 53057014Seric { 53160089Seric if (key.dsize > sizeof keybuf - 1) 53260089Seric key.dsize = sizeof keybuf - 1; 53360089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 53460089Seric makelower(keybuf); 53560089Seric key.dptr = keybuf; 53657014Seric } 53764373Seric fd = dbm_dirfno((DBM *) map->map_db1); 53864388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 53964373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 54063753Seric val.dptr = NULL; 54163753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 54263753Seric { 54363753Seric val = dbm_fetch((DBM *) map->map_db1, key); 54463753Seric if (val.dptr != NULL) 54563753Seric map->map_mflags &= ~MF_TRY1NULL; 54663753Seric } 54763753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 54863753Seric { 54956822Seric key.dsize++; 55063753Seric val = dbm_fetch((DBM *) map->map_db1, key); 55163753Seric if (val.dptr != NULL) 55263753Seric map->map_mflags &= ~MF_TRY0NULL; 55363753Seric } 55464388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 55564373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 55656822Seric if (val.dptr == NULL) 55756822Seric return NULL; 55860207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 55963753Seric return map_rewrite(map, name, strlen(name), NULL); 56063753Seric else 56163753Seric return map_rewrite(map, val.dptr, val.dsize, av); 56256822Seric } 56356822Seric 56456822Seric 56556822Seric /* 56660089Seric ** DBM_MAP_STORE -- store a datum in the database 56756822Seric */ 56856822Seric 56960089Seric void 57060089Seric ndbm_map_store(map, lhs, rhs) 57160089Seric register MAP *map; 57260089Seric char *lhs; 57360089Seric char *rhs; 57460089Seric { 57560089Seric datum key; 57660089Seric datum data; 57760089Seric int stat; 57860089Seric 57960537Seric if (tTd(38, 12)) 58068350Seric printf("ndbm_map_store(%s, %s, %s)\n", 58168350Seric map->map_mname, lhs, rhs); 58260089Seric 58360089Seric key.dsize = strlen(lhs); 58460089Seric key.dptr = lhs; 58560089Seric 58660089Seric data.dsize = strlen(rhs); 58760089Seric data.dptr = rhs; 58860089Seric 58960207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 59060089Seric { 59160089Seric key.dsize++; 59260089Seric data.dsize++; 59360089Seric } 59460089Seric 59560089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 59660089Seric if (stat > 0) 59760089Seric { 59868497Seric if (!bitset(MF_APPEND, map->map_mflags)) 59968497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 60068497Seric else 60168497Seric { 60268497Seric static char *buf = NULL; 60368497Seric static int bufsiz = 0; 60468879Seric auto int xstat; 60568497Seric datum old; 60668497Seric 60768879Seric old.dptr = ndbm_map_lookup(map, key.dptr, NULL, &xstat); 60868497Seric if (old.dptr != NULL && *old.dptr != '\0') 60968497Seric { 61068497Seric old.dsize = strlen(old.dptr); 61168497Seric if (data.dsize + old.dsize + 2 > bufsiz) 61268497Seric { 61368497Seric if (buf != NULL) 61468497Seric (void) free(buf); 61568497Seric bufsiz = data.dsize + old.dsize + 2; 61668497Seric buf = xalloc(bufsiz); 61768497Seric } 61868497Seric sprintf(buf, "%s,%s", data.dptr, old.dptr); 61968497Seric data.dsize = data.dsize + old.dsize + 1; 62068497Seric data.dptr = buf; 62168497Seric if (tTd(38, 9)) 62268497Seric printf("ndbm_map_store append=%s\n", data.dptr); 62368497Seric } 62468497Seric } 62560089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 62660089Seric } 62760089Seric if (stat != 0) 62860089Seric syserr("readaliases: dbm put (%s)", lhs); 62960089Seric } 63060089Seric 63160089Seric 63260089Seric /* 63360207Seric ** NDBM_MAP_CLOSE -- close the database 63460089Seric */ 63560089Seric 63660089Seric void 63760089Seric ndbm_map_close(map) 63860089Seric register MAP *map; 63960089Seric { 64066773Seric if (tTd(38, 9)) 64168350Seric printf("ndbm_map_close(%s, %s, %x)\n", 64268350Seric map->map_mname, map->map_file, map->map_mflags); 64366773Seric 64460207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 64560089Seric { 64664250Seric #ifdef NIS 64764075Seric bool inclnull; 64860089Seric char buf[200]; 64960089Seric 65064075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 65164075Seric map->map_mflags &= ~MF_INCLNULL; 65264075Seric 65369651Seric if (strstr(map->map_file, "/yp/") != NULL) 65469651Seric { 65569651Seric (void) sprintf(buf, "%010ld", curtime()); 65669651Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 65760089Seric 65869651Seric (void) gethostname(buf, sizeof buf); 65969651Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 66069651Seric } 66164075Seric 66264075Seric if (inclnull) 66364075Seric map->map_mflags |= MF_INCLNULL; 66460089Seric #endif 66560089Seric 66660089Seric /* write out the distinguished alias */ 66760089Seric ndbm_map_store(map, "@", "@"); 66860089Seric } 66960089Seric dbm_close((DBM *) map->map_db1); 67060089Seric } 67160089Seric 67260089Seric #endif 67360089Seric /* 67460582Seric ** NEWDB (Hash and BTree) Modules 67560089Seric */ 67660089Seric 67760089Seric #ifdef NEWDB 67860089Seric 67960089Seric /* 68060582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 68160582Seric ** 68260582Seric ** These do rather bizarre locking. If you can lock on open, 68360582Seric ** do that to avoid the condition of opening a database that 68460582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 68560582Seric ** there will be a race condition. If opening for read-only, 68660582Seric ** we immediately release the lock to avoid freezing things up. 68760582Seric ** We really ought to hold the lock, but guarantee that we won't 68860582Seric ** be pokey about it. That's hard to do. 68960089Seric */ 69060089Seric 69156822Seric bool 69260089Seric bt_map_open(map, mode) 69356822Seric MAP *map; 69460089Seric int mode; 69556822Seric { 69656822Seric DB *db; 69760228Seric int i; 69860582Seric int omode; 69964373Seric int fd; 70064284Seric struct stat st; 70168528Seric char buf[MAXNAME + 1]; 70256822Seric 70360537Seric if (tTd(38, 2)) 70468350Seric printf("bt_map_open(%s, %s, %d)\n", 70568350Seric map->map_mname, map->map_file, mode); 70660089Seric 70760582Seric omode = mode; 70860582Seric if (omode == O_RDWR) 70960582Seric { 71060582Seric omode |= O_CREAT|O_TRUNC; 71165830Seric #if defined(O_EXLOCK) && HASFLOCK 71260582Seric omode |= O_EXLOCK; 71366843Seric # if !OLD_NEWDB 71460582Seric } 71560582Seric else 71660582Seric { 71760582Seric omode |= O_SHLOCK; 71860582Seric # endif 71960582Seric #endif 72060582Seric } 72160207Seric 72260228Seric (void) strcpy(buf, map->map_file); 72360228Seric i = strlen(buf); 72460228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 72560228Seric (void) strcat(buf, ".db"); 72660582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 72756822Seric if (db == NULL) 72856822Seric { 72964718Seric #ifdef MAYBENEXTRELEASE 73064718Seric if (aliaswait(map, ".db", FALSE)) 73164718Seric return TRUE; 73264718Seric #endif 73360207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 73456836Seric syserr("Cannot open BTREE database %s", map->map_file); 73556822Seric return FALSE; 73656822Seric } 73768350Seric #if !OLD_NEWDB 73864373Seric fd = db->fd(db); 73968778Seric # if defined(O_EXLOCK) && HASFLOCK 74068778Seric if (fd >= 0) 74168778Seric { 74268778Seric if (mode == O_RDONLY) 74368778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 74468778Seric else 74568778Seric map->map_mflags |= MF_LOCKED; 74668778Seric } 74768778Seric # else 74864373Seric if (mode == O_RDWR && fd >= 0) 74964388Seric { 75064388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 75164388Seric map->map_mflags |= MF_LOCKED; 75264388Seric } 75360582Seric # endif 75460582Seric #endif 75560585Seric 75660585Seric /* try to make sure that at least the database header is on disk */ 75760585Seric if (mode == O_RDWR) 75866843Seric #if OLD_NEWDB 75964373Seric (void) db->sync(db); 76064373Seric #else 76160585Seric (void) db->sync(db, 0); 76260585Seric 76364373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 76464284Seric map->map_mtime = st.st_mtime; 76564284Seric #endif 76664284Seric 76760089Seric map->map_db2 = (void *) db; 76860207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 76964718Seric if (!aliaswait(map, ".db", TRUE)) 77064718Seric return FALSE; 77156822Seric return TRUE; 77256822Seric } 77356822Seric 77456822Seric 77556822Seric /* 77656822Seric ** HASH_MAP_INIT -- HASH-style map initialization 77756822Seric */ 77856822Seric 77956822Seric bool 78060089Seric hash_map_open(map, mode) 78156822Seric MAP *map; 78260089Seric int mode; 78356822Seric { 78456822Seric DB *db; 78560228Seric int i; 78660582Seric int omode; 78764373Seric int fd; 78864284Seric struct stat st; 78968528Seric char buf[MAXNAME + 1]; 79056822Seric 79160537Seric if (tTd(38, 2)) 79268350Seric printf("hash_map_open(%s, %s, %d)\n", 79368350Seric map->map_mname, map->map_file, mode); 79460089Seric 79560582Seric omode = mode; 79660582Seric if (omode == O_RDWR) 79760582Seric { 79860582Seric omode |= O_CREAT|O_TRUNC; 79965830Seric #if defined(O_EXLOCK) && HASFLOCK 80060582Seric omode |= O_EXLOCK; 80166843Seric # if !OLD_NEWDB 80260582Seric } 80360582Seric else 80460582Seric { 80560582Seric omode |= O_SHLOCK; 80660582Seric # endif 80760582Seric #endif 80860582Seric } 80960207Seric 81060228Seric (void) strcpy(buf, map->map_file); 81160228Seric i = strlen(buf); 81260228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 81360228Seric (void) strcat(buf, ".db"); 81460582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 81556822Seric if (db == NULL) 81656822Seric { 81764718Seric #ifdef MAYBENEXTRELEASE 81864718Seric if (aliaswait(map, ".db", FALSE)) 81964718Seric return TRUE; 82064718Seric #endif 82160207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 82256836Seric syserr("Cannot open HASH database %s", map->map_file); 82356822Seric return FALSE; 82456822Seric } 82568350Seric #if !OLD_NEWDB 82664373Seric fd = db->fd(db); 82768778Seric # if defined(O_EXLOCK) && HASFLOCK 82868778Seric if (fd >= 0) 82968778Seric { 83068778Seric if (mode == O_RDONLY) 83168778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 83268778Seric else 83368778Seric map->map_mflags |= MF_LOCKED; 83468778Seric } 83568778Seric # else 83664373Seric if (mode == O_RDWR && fd >= 0) 83764388Seric { 83864388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 83964388Seric map->map_mflags |= MF_LOCKED; 84064388Seric } 84160582Seric # endif 84260582Seric #endif 84360585Seric 84460585Seric /* try to make sure that at least the database header is on disk */ 84560585Seric if (mode == O_RDWR) 84666843Seric #if OLD_NEWDB 84764373Seric (void) db->sync(db); 84864373Seric #else 84960585Seric (void) db->sync(db, 0); 85060585Seric 85164373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 85264284Seric map->map_mtime = st.st_mtime; 85364284Seric #endif 85464284Seric 85560089Seric map->map_db2 = (void *) db; 85660207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 85764718Seric if (!aliaswait(map, ".db", TRUE)) 85864718Seric return FALSE; 85956822Seric return TRUE; 86056822Seric } 86156822Seric 86256822Seric 86356822Seric /* 86456822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 86556822Seric */ 86656822Seric 86756822Seric char * 86860089Seric db_map_lookup(map, name, av, statp) 86956822Seric MAP *map; 87060089Seric char *name; 87156822Seric char **av; 87259084Seric int *statp; 87356822Seric { 87456822Seric DBT key, val; 87560422Seric register DB *db = (DB *) map->map_db2; 87660422Seric int st; 87760422Seric int saveerrno; 87864373Seric int fd; 87960089Seric char keybuf[MAXNAME + 1]; 88056822Seric 88160537Seric if (tTd(38, 20)) 88268350Seric printf("db_map_lookup(%s, %s)\n", 88368350Seric map->map_mname, name); 88460089Seric 88560089Seric key.size = strlen(name); 88660089Seric if (key.size > sizeof keybuf - 1) 88760089Seric key.size = sizeof keybuf - 1; 88860089Seric key.data = keybuf; 88960089Seric bcopy(name, keybuf, key.size + 1); 89060207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 89160089Seric makelower(keybuf); 89266843Seric #if !OLD_NEWDB 89364388Seric fd = db->fd(db); 89464388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 89564388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 89660422Seric #endif 89763753Seric st = 1; 89863753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 89963753Seric { 90063753Seric st = db->get(db, &key, &val, 0); 90163753Seric if (st == 0) 90263753Seric map->map_mflags &= ~MF_TRY1NULL; 90363753Seric } 90463753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 90563753Seric { 90663753Seric key.size++; 90763753Seric st = db->get(db, &key, &val, 0); 90863753Seric if (st == 0) 90963753Seric map->map_mflags &= ~MF_TRY0NULL; 91063753Seric } 91160422Seric saveerrno = errno; 91266843Seric #if !OLD_NEWDB 91364388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 91464373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 91560422Seric #endif 91660422Seric if (st != 0) 91760422Seric { 91860422Seric errno = saveerrno; 91960422Seric if (st < 0) 92060422Seric syserr("db_map_lookup: get (%s)", name); 92156822Seric return NULL; 92260422Seric } 92360207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 92463753Seric return map_rewrite(map, name, strlen(name), NULL); 92563753Seric else 92663753Seric return map_rewrite(map, val.data, val.size, av); 92756822Seric } 92856822Seric 92960089Seric 93060089Seric /* 93160089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 93256822Seric */ 93356822Seric 93460089Seric void 93560089Seric db_map_store(map, lhs, rhs) 93660089Seric register MAP *map; 93760089Seric char *lhs; 93860089Seric char *rhs; 93956822Seric { 94060089Seric int stat; 94160089Seric DBT key; 94260089Seric DBT data; 94360089Seric register DB *db = map->map_db2; 94456822Seric 94560537Seric if (tTd(38, 20)) 94668350Seric printf("db_map_store(%s, %s, %s)\n", 94768350Seric map->map_mname, lhs, rhs); 94860089Seric 94960089Seric key.size = strlen(lhs); 95060089Seric key.data = lhs; 95160089Seric 95260089Seric data.size = strlen(rhs); 95360089Seric data.data = rhs; 95460089Seric 95560207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 95656822Seric { 95760089Seric key.size++; 95860089Seric data.size++; 95960089Seric } 96056836Seric 96160089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 96260089Seric if (stat > 0) 96360089Seric { 96468497Seric if (!bitset(MF_APPEND, map->map_mflags)) 96568497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 96668497Seric else 96768497Seric { 96868497Seric static char *buf = NULL; 96968497Seric static int bufsiz = 0; 97068497Seric DBT old; 97168497Seric 97268497Seric old.data = db_map_lookup(map, key.data, NULL, &stat); 97368497Seric if (old.data != NULL) 97468497Seric { 97568497Seric old.size = strlen(old.data); 97668497Seric if (data.size + old.size + 2 > bufsiz) 97768497Seric { 97868497Seric if (buf != NULL) 97968497Seric (void) free(buf); 98068497Seric bufsiz = data.size + old.size + 2; 98168497Seric buf = xalloc(bufsiz); 98268497Seric } 98368497Seric sprintf(buf, "%s,%s", data.data, old.data); 98468497Seric data.size = data.size + old.size + 1; 98568497Seric data.data = buf; 98668497Seric if (tTd(38, 9)) 98768497Seric printf("db_map_store append=%s\n", data.data); 98868497Seric } 98968497Seric } 99060089Seric stat = db->put(db, &key, &data, 0); 99160089Seric } 99260089Seric if (stat != 0) 99360089Seric syserr("readaliases: db put (%s)", lhs); 99460089Seric } 99556836Seric 99656847Seric 99760089Seric /* 99860089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 99960089Seric */ 100060089Seric 100160089Seric void 100260089Seric db_map_close(map) 100360089Seric MAP *map; 100460089Seric { 100560089Seric register DB *db = map->map_db2; 100660089Seric 100760537Seric if (tTd(38, 9)) 100868350Seric printf("db_map_close(%s, %s, %x)\n", 100968350Seric map->map_mname, map->map_file, map->map_mflags); 101060089Seric 101160207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 101258804Seric { 101360089Seric /* write out the distinguished alias */ 101460089Seric db_map_store(map, "@", "@"); 101558804Seric } 101658963Seric 101760089Seric if (db->close(db) != 0) 101860089Seric syserr("readaliases: db close failure"); 101956822Seric } 102057208Seric 102160089Seric #endif 102260089Seric /* 102360089Seric ** NIS Modules 102460089Seric */ 102560089Seric 102660089Seric # ifdef NIS 102760089Seric 102864369Seric # ifndef YPERR_BUSY 102964369Seric # define YPERR_BUSY 16 103064369Seric # endif 103164369Seric 103257208Seric /* 103360089Seric ** NIS_MAP_OPEN -- open DBM map 103457208Seric */ 103557208Seric 103657208Seric bool 103760089Seric nis_map_open(map, mode) 103857208Seric MAP *map; 103960089Seric int mode; 104057208Seric { 104157216Seric int yperr; 104260215Seric register char *p; 104360215Seric auto char *vp; 104460215Seric auto int vsize; 104557216Seric char *master; 104657216Seric 104760537Seric if (tTd(38, 2)) 104868350Seric printf("nis_map_open(%s, %s)\n", 104968350Seric map->map_mname, map->map_file); 105060089Seric 105160207Seric if (mode != O_RDONLY) 105260207Seric { 105364650Seric /* issue a pseudo-error message */ 105464650Seric #ifdef ENOSYS 105564650Seric errno = ENOSYS; 105664650Seric #else 105764650Seric # ifdef EFTYPE 105864650Seric errno = EFTYPE; 105964650Seric # else 106064650Seric errno = ENXIO; 106164650Seric # endif 106264650Seric #endif 106360207Seric return FALSE; 106460207Seric } 106560207Seric 106660089Seric p = strchr(map->map_file, '@'); 106760089Seric if (p != NULL) 106860089Seric { 106960089Seric *p++ = '\0'; 107060089Seric if (*p != '\0') 107160089Seric map->map_domain = p; 107260089Seric } 107360215Seric 107460089Seric if (*map->map_file == '\0') 107560089Seric map->map_file = "mail.aliases"; 107660089Seric 107766157Seric if (map->map_domain == NULL) 107866157Seric { 107966157Seric yperr = yp_get_default_domain(&map->map_domain); 108066157Seric if (yperr != 0) 108166157Seric { 108266744Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 108368350Seric syserr("421 NIS map %s specified, but NIS not running\n", 108466744Seric map->map_file); 108566157Seric return FALSE; 108666157Seric } 108766157Seric } 108866157Seric 108960215Seric /* check to see if this map actually exists */ 109060089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 109160089Seric &vp, &vsize); 109260537Seric if (tTd(38, 10)) 109360089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 109460089Seric map->map_domain, map->map_file, yperr_string(yperr)); 109560089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 109668350Seric { 109768350Seric if (!bitset(MF_ALIAS, map->map_mflags) || 109868350Seric aliaswait(map, NULL, TRUE)) 109968350Seric return TRUE; 110068350Seric } 110160215Seric 110260215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 110368735Seric { 110468735Seric syserr("421 Cannot bind to map %s in domain %s: %s", 110568735Seric map->map_file, map->map_domain, yperr_string(yperr)); 110668735Seric } 110760215Seric 110860089Seric return FALSE; 110960089Seric } 111060089Seric 111160089Seric 111260089Seric /* 111357208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 111457208Seric */ 111557208Seric 111657208Seric char * 111760089Seric nis_map_lookup(map, name, av, statp) 111857208Seric MAP *map; 111960089Seric char *name; 112057208Seric char **av; 112159084Seric int *statp; 112257208Seric { 112357208Seric char *vp; 112457642Seric auto int vsize; 112559274Seric int buflen; 112660215Seric int yperr; 112760089Seric char keybuf[MAXNAME + 1]; 112857208Seric 112960537Seric if (tTd(38, 20)) 113068350Seric printf("nis_map_lookup(%s, %s)\n", 113168350Seric map->map_mname, name); 113260089Seric 113360089Seric buflen = strlen(name); 113460089Seric if (buflen > sizeof keybuf - 1) 113560089Seric buflen = sizeof keybuf - 1; 113660089Seric bcopy(name, keybuf, buflen + 1); 113760207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 113860089Seric makelower(keybuf); 113963753Seric yperr = YPERR_KEY; 114063753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 114163753Seric { 114263753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 114363753Seric &vp, &vsize); 114463753Seric if (yperr == 0) 114563753Seric map->map_mflags &= ~MF_TRY1NULL; 114663753Seric } 114763753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 114863753Seric { 114959274Seric buflen++; 115063753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 115163753Seric &vp, &vsize); 115263753Seric if (yperr == 0) 115363753Seric map->map_mflags &= ~MF_TRY0NULL; 115463753Seric } 115560089Seric if (yperr != 0) 115660089Seric { 115760089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 115860215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 115957208Seric return NULL; 116060089Seric } 116160207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 116263753Seric return map_rewrite(map, name, strlen(name), NULL); 116363753Seric else 116463753Seric return map_rewrite(map, vp, vsize, av); 116557208Seric } 116657208Seric 116769401Seric 116869401Seric /* 116969401Seric ** NIS_GETCANONNAME -- look up canonical name in NIS 117069401Seric */ 117169401Seric 117269401Seric bool 117369401Seric nis_getcanonname(name, hbsize, statp) 117469401Seric char *name; 117569401Seric int hbsize; 117669401Seric int *statp; 117769401Seric { 117869401Seric char *vp; 117969401Seric auto int vsize; 118069401Seric int keylen; 118169401Seric int yperr; 118269401Seric static bool try0null = TRUE; 118369401Seric static bool try1null = TRUE; 118469401Seric static char *yp_domain = NULL; 118569401Seric char *domain, *p; 118669401Seric char host_record[MAXLINE]; 118769401Seric char buf[MAXNAME]; 118869401Seric char *cname; 118969401Seric extern char *get_column(); 119069401Seric 119169401Seric if (tTd(38, 20)) 119269401Seric printf("nis_getcanonname(%s)\n", name); 119369401Seric 119469401Seric shorten_hostname(name); 119569401Seric 119669401Seric /* we only accept single token search key */ 119769401Seric if (strchr(name, '.')) 119869401Seric { 119969401Seric *statp = EX_NOHOST; 120069401Seric return FALSE; 120169401Seric } 120269401Seric 120369401Seric keylen = strlen(name); 120469401Seric 120569401Seric if (yp_domain == NULL) 120669401Seric yp_get_default_domain(&yp_domain); 120769401Seric makelower(name); 120869401Seric yperr = YPERR_KEY; 120969401Seric if (try0null) 121069401Seric { 121169401Seric yperr = yp_match(yp_domain, "hosts.byname", name, keylen, 121269401Seric &vp, &vsize); 121369401Seric if (yperr == 0) 121469401Seric try1null = FALSE; 121569401Seric } 121669401Seric if (yperr == YPERR_KEY && try1null) 121769401Seric { 121869401Seric keylen++; 121969401Seric yperr = yp_match(yp_domain, "hosts.byname", name, keylen, 122069401Seric &vp, &vsize); 122169401Seric if (yperr == 0) 122269401Seric try0null = FALSE; 122369401Seric } 122469401Seric if (yperr != 0) 122569401Seric { 122669401Seric if (yperr == YPERR_KEY) 122769401Seric *statp = EX_NOHOST; 122869401Seric else if (yperr == YPERR_BUSY) 122969401Seric *statp = EX_TEMPFAIL; 123069401Seric else 123169401Seric *statp = EX_UNAVAILABLE; 123269401Seric return FALSE; 123369401Seric } 123469401Seric strncpy(host_record, vp, vsize); 123569401Seric host_record[vsize] = '\0'; 123669663Seric if (tTd(38, 44)) 123769663Seric printf("got record `%s'\n", host_record); 123869663Seric cname = get_column(host_record, 1, '\0', buf); 123969401Seric if (cname == NULL) 124069401Seric { 124169401Seric /* this should not happen, but.... */ 124269401Seric *statp = EX_NOHOST; 124369401Seric return FALSE; 124469401Seric } 124569401Seric 124669401Seric if (hbsize >= strlen(cname)) 124769401Seric { 124869401Seric strcpy(name, cname); 124969401Seric *statp = EX_OK; 125069401Seric return TRUE; 125169401Seric } 125269401Seric *statp = EX_UNAVAILABLE; 125369401Seric return FALSE; 125469401Seric } 125569401Seric 125668350Seric #endif 125768350Seric /* 125868350Seric ** NISPLUS Modules 125968350Seric ** 126068350Seric ** This code donated by Sun Microsystems. 126168350Seric */ 126267848Seric 126368350Seric #ifdef NISPLUS 126468350Seric 126568350Seric #undef NIS /* symbol conflict in nis.h */ 126668350Seric #include <rpcsvc/nis.h> 126768350Seric #include <rpcsvc/nislib.h> 126868350Seric 126968350Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 127068350Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 127168350Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 127268350Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 127368350Seric 127467848Seric /* 127568350Seric ** NISPLUS_MAP_OPEN -- open nisplus table 127667848Seric */ 127767848Seric 127868350Seric bool 127968350Seric nisplus_map_open(map, mode) 128067848Seric MAP *map; 128168350Seric int mode; 128267848Seric { 128368350Seric register char *p; 128468350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 128568350Seric nis_result *res = NULL; 128668350Seric u_int objs_len; 128768350Seric nis_object *obj_ptr; 128868350Seric int retry_cnt, max_col, i; 128968350Seric 129068350Seric if (tTd(38, 2)) 129168350Seric printf("nisplus_map_open(%s, %s, %d)\n", 129268350Seric map->map_mname, map->map_file, mode); 129368350Seric 129468350Seric if (mode != O_RDONLY) 129568350Seric { 129668350Seric errno = ENODEV; 129768350Seric return FALSE; 129868350Seric } 129968350Seric 130068350Seric if (*map->map_file == '\0') 130168350Seric map->map_file = "mail_aliases.org_dir"; 130268350Seric 130368350Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 130468350Seric { 130568350Seric /* set default NISPLUS Domain to $m */ 130668350Seric extern char *nisplus_default_domain(); 130768350Seric 130868350Seric map->map_domain = newstr(nisplus_default_domain()); 130968350Seric if (tTd(38, 2)) 131068350Seric printf("nisplus_map_open(%s): using domain %s\n", 131168350Seric map->map_file, map->map_domain); 131268350Seric } 131368350Seric if (!PARTIAL_NAME(map->map_file)) 131468350Seric map->map_domain = newstr(""); 131568350Seric 131668350Seric /* check to see if this map actually exists */ 131768350Seric if (PARTIAL_NAME(map->map_file)) 131868350Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 131968350Seric else 132068350Seric strcpy(qbuf, map->map_file); 132168350Seric 132268350Seric retry_cnt = 0; 132368350Seric while (res == NULL || res->status != NIS_SUCCESS) 132468350Seric { 132568350Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 132668350Seric switch (res->status) 132768350Seric { 132868350Seric case NIS_SUCCESS: 132968350Seric case NIS_TRYAGAIN: 133068350Seric case NIS_RPCERROR: 133168350Seric case NIS_NAMEUNREACHABLE: 133268350Seric break; 133368350Seric 133468350Seric default: /* all other nisplus errors */ 133568350Seric #if 0 133668350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 133768350Seric syserr("421 Cannot find table %s.%s: %s", 133868350Seric map->map_file, map->map_domain, 133968350Seric nis_sperrno(res->status)); 134068350Seric #endif 134168350Seric errno = EBADR; 134268350Seric return FALSE; 134368350Seric } 134468350Seric sleep(2); /* try not to overwhelm hosed server */ 134568350Seric if (retry_cnt++ > 4) 134668350Seric { 134768350Seric errno = EBADR; 134868350Seric return FALSE; 134968350Seric } 135068350Seric } 135168350Seric 135268350Seric if (NIS_RES_NUMOBJ(res) != 1 || 135368350Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 135468350Seric { 135568350Seric if (tTd(38, 10)) 135668350Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 135768350Seric #if 0 135868350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 135968350Seric syserr("421 %s.%s: %s is not a table", 136068350Seric map->map_file, map->map_domain, 136168350Seric nis_sperrno(res->status)); 136268350Seric #endif 136368350Seric errno = EBADR; 136468350Seric return FALSE; 136568350Seric } 136668350Seric /* default key column is column 0 */ 136768350Seric if (map->map_keycolnm == NULL) 136868350Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 136968350Seric 137068350Seric max_col = COL_MAX(res); 137168350Seric 137268350Seric /* verify the key column exist */ 137368350Seric for (i=0; i< max_col; i++) 137468350Seric { 137568350Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 137668350Seric break; 137768350Seric } 137868350Seric if (i == max_col) 137968350Seric { 138068350Seric if (tTd(38, 2)) 138168350Seric printf("nisplus_map_open(%s): can not find key column %s\n", 138268350Seric map->map_file, map->map_keycolnm); 138368350Seric errno = EBADR; 138468350Seric return FALSE; 138568350Seric } 138668350Seric 138768350Seric /* default value column is the last column */ 138868350Seric if (map->map_valcolnm == NULL) 138968350Seric { 139068350Seric map->map_valcolno = max_col - 1; 139168350Seric return TRUE; 139268350Seric } 139368350Seric 139468350Seric for (i=0; i< max_col; i++) 139568350Seric { 139668350Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 139768350Seric { 139868350Seric map->map_valcolno = i; 139968350Seric return TRUE; 140068350Seric } 140168350Seric } 140268350Seric 140368350Seric if (tTd(38, 2)) 140468350Seric printf("nisplus_map_open(%s): can not find column %s\n", 140568350Seric map->map_file, map->map_keycolnm); 140668350Seric errno = EBADR; 140768350Seric return FALSE; 140867848Seric } 140967848Seric 141067848Seric 141167848Seric /* 141268350Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 141367848Seric */ 141467848Seric 141568350Seric char * 141668350Seric nisplus_map_lookup(map, name, av, statp) 141767848Seric MAP *map; 141868350Seric char *name; 141968350Seric char **av; 142068350Seric int *statp; 142167848Seric { 142268350Seric char *vp; 142368350Seric auto int vsize; 142468350Seric int buflen; 142568350Seric char search_key[MAXNAME + 1]; 142668350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 142768350Seric nis_result *result; 142868350Seric 142968350Seric if (tTd(38, 20)) 143068350Seric printf("nisplus_map_lookup(%s, %s)\n", 143168350Seric map->map_mname, name); 143268350Seric 143368350Seric if (!bitset(MF_OPEN, map->map_mflags)) 143468350Seric { 143568350Seric if (nisplus_map_open(map, O_RDONLY)) 143668350Seric map->map_mflags |= MF_OPEN; 143768350Seric else 143868350Seric { 143968350Seric *statp = EX_UNAVAILABLE; 144068350Seric return NULL; 144168350Seric } 144268350Seric } 144368350Seric 144468350Seric buflen = strlen(name); 144568350Seric if (buflen > sizeof search_key - 1) 144668350Seric buflen = sizeof search_key - 1; 144768350Seric bcopy(name, search_key, buflen + 1); 144868350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 144968350Seric makelower(search_key); 145068350Seric 145168350Seric /* construct the query */ 145268350Seric if (PARTIAL_NAME(map->map_file)) 145368350Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 145468350Seric search_key, map->map_file, map->map_domain); 145568350Seric else 145668350Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 145768350Seric search_key, map->map_file); 145868350Seric 145968350Seric if (tTd(38, 20)) 146068350Seric printf("qbuf=%s\n", qbuf); 146168350Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 146268350Seric if (result->status == NIS_SUCCESS) 146368350Seric { 146468350Seric int count; 146568350Seric char *str; 146668350Seric 146768350Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 146868350Seric { 146968350Seric if (LogLevel > 10) 147068350Seric syslog(LOG_WARNING, 147168350Seric "%s:Lookup error, expected 1 entry, got (%d)", 147268350Seric map->map_file, count); 147368350Seric 147468350Seric /* ignore second entry */ 147568350Seric if (tTd(38, 20)) 147668350Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 147768350Seric name, count); 147868350Seric } 147968350Seric 148068350Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 148168350Seric /* set the length of the result */ 148268350Seric if (vp == NULL) 148368350Seric vp = ""; 148468350Seric vsize = strlen(vp); 148568350Seric if (tTd(38, 20)) 148668350Seric printf("nisplus_map_lookup(%s), found %s\n", 148768350Seric name, vp); 148868350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 148968350Seric str = map_rewrite(map, name, strlen(name), NULL); 149068350Seric else 149168350Seric str = map_rewrite(map, vp, vsize, av); 149268350Seric nis_freeresult(result); 149368350Seric #ifdef MAP_EXIT_STAT 149468350Seric *statp = EX_OK; 149568350Seric #endif 149668350Seric return str; 149768350Seric } 149868350Seric else 149968350Seric { 150068350Seric #ifdef MAP_EXIT_STAT 150168350Seric if (result->status == NIS_NOTFOUND) 150268350Seric *statp = EX_NOTFOUND; 150368350Seric else if (result->status == NIS_TRYAGAIN) 150468350Seric *statp = EX_TEMPFAIL; 150568350Seric else 150668350Seric { 150768350Seric *statp = EX_UNAVAILABLE; 150868350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 150968350Seric } 151068350Seric #else 151168350Seric if ((result->status != NIS_NOTFOUND) && 151268350Seric (result->status != NIS_TRYAGAIN)) 151368350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 151468350Seric #endif 151568350Seric } 151668350Seric if (tTd(38, 20)) 151768350Seric printf("nisplus_map_lookup(%s), failed\n", name); 151868350Seric nis_freeresult(result); 151968350Seric return NULL; 152067848Seric } 152167848Seric 152268350Seric 152369401Seric 152469401Seric /* 152569401Seric ** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 152669401Seric */ 152769401Seric 152869401Seric bool 152969401Seric nisplus_getcanonname(name, hbsize, statp) 153069401Seric char *name; 153169401Seric int hbsize; 153269401Seric int *statp; 153369401Seric { 153469401Seric char *vp; 153569401Seric auto int vsize; 153669401Seric int buflen; 153769477Seric char buf[MAXLINE + NIS_MAXNAMELEN]; 153869401Seric nis_result *result; 153969401Seric char *p; 154069401Seric int len; 154169401Seric 154269401Seric shorten_hostname(name); 154369401Seric 154469401Seric p = strchr(name, '.'); 154569401Seric if (p == NULL) 154669401Seric { 154769401Seric /* single token */ 154869477Seric sprintf(buf, "[name=%s],hosts.org_dir", name); 154969401Seric } 155069401Seric else if (p[1] != '\0') 155169401Seric { 155269401Seric /* multi token -- take only first token in name buf */ 155369401Seric *p = '\0'; 155469477Seric sprintf(buf, "[name=%s],hosts.org_dir.%s", name, &p[1]); 155569401Seric } 155669401Seric else 155769401Seric { 155869401Seric *statp = EX_NOHOST; 155969401Seric return FALSE; 156069401Seric } 156169401Seric 156269401Seric if (tTd(38, 20)) 156369478Seric printf("\nnisplus_getcanoname(%s), qbuf=%s\n", 156469478Seric name, buf); 156569401Seric 156669477Seric result = nis_list(buf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 156769401Seric NULL, NULL); 156869401Seric 156969401Seric if (result->status == NIS_SUCCESS) 157069401Seric { 157169401Seric int count; 157269401Seric char *str; 157369401Seric char *domain; 157469401Seric 157569401Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 157669401Seric { 157769401Seric #ifdef LOG 157869401Seric if (LogLevel > 10) 157969401Seric syslog(LOG_WARNING, 158069401Seric "nisplus_getcanonname: Lookup error, expected 1 entry, got (%d)", 158169401Seric count); 158269401Seric #endif 158369401Seric 158469401Seric /* ignore second entry */ 158569401Seric if (tTd(38, 20)) 158669401Seric printf("nisplus_getcanoname(%s), got %d entries, addtional entries ignores\n", name); 158769401Seric } 158869401Seric 158969401Seric if (tTd(38, 20)) 159069401Seric printf("nisplus_getcanoname(%s), found in directory \"%s\"\n", 159169401Seric name, (NIS_RES_OBJECT(result))->zo_domain); 159269401Seric 159369401Seric 159469401Seric vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 159569401Seric vsize = strlen(vp); 159669401Seric if (tTd(38, 20)) 159769401Seric printf("nisplus_getcanonname(%s), found %s\n", 159869401Seric name, vp); 159969401Seric domain = macvalue('m', CurEnv); 160069636Seric if (domain == NULL) 160169636Seric domain = ""; 160269636Seric if (hbsize > vsize + (int) strlen(domain) + 1) 160369401Seric { 160469636Seric if (domain[0] == '\0') 160569636Seric strcpy(name, vp); 160669636Seric else 160769636Seric sprintf(name, "%s.%s", vp, domain); 160869401Seric *statp = EX_OK; 160969401Seric } 161069401Seric else 161169401Seric *statp = EX_NOHOST; 161269401Seric nis_freeresult(result); 161369401Seric return TRUE; 161469401Seric } 161569401Seric else 161669401Seric { 161769401Seric if (result->status == NIS_NOTFOUND) 161869401Seric *statp = EX_NOHOST; 161969401Seric else if (result->status == NIS_TRYAGAIN) 162069401Seric *statp = EX_TEMPFAIL; 162169401Seric else 162269401Seric *statp = EX_UNAVAILABLE; 162369401Seric } 162469401Seric if (tTd(38, 20)) 162569401Seric printf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 162669401Seric name, result->status, *statp); 162769401Seric nis_freeresult(result); 162869401Seric return FALSE; 162969401Seric } 163069401Seric 163169401Seric 163268350Seric char * 163368350Seric nisplus_default_domain() 163468350Seric { 163568528Seric static char default_domain[MAXNAME + 1] = ""; 163668350Seric char *p; 163768350Seric 163868350Seric if (default_domain[0] != '\0') 163968350Seric return(default_domain); 164068350Seric 164168458Seric p = nis_local_directory(); 164268350Seric strcpy(default_domain, p); 164368458Seric return default_domain; 164468350Seric } 164568350Seric 164668350Seric #endif /* NISPLUS */ 164767848Seric /* 164868350Seric ** HESIOD Modules 164968350Seric */ 165068350Seric 165168350Seric #ifdef HESIOD 165268350Seric 165368350Seric #include <hesiod.h> 165468350Seric 165568350Seric char * 165668350Seric hes_map_lookup(map, name, av, statp) 165768350Seric MAP *map; 165868350Seric char *name; 165968350Seric char **av; 166068350Seric int *statp; 166168350Seric { 166268350Seric char **hp; 166368350Seric int i; 166468350Seric 166568350Seric if (tTd(38, 20)) 166668350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 166768350Seric 1668*69688Seric if (name[0] == '\\') 1669*69688Seric { 1670*69688Seric char *np; 1671*69688Seric int nl; 1672*69688Seric char nbuf[MAXNAME]; 1673*69688Seric 1674*69688Seric nl = strlen(name); 1675*69688Seric if (nl < sizeof nbuf - 1) 1676*69688Seric np = nbuf; 1677*69688Seric else 1678*69688Seric np = xalloc(strlen(name) + 2); 1679*69688Seric np[0] = '\\'; 1680*69688Seric strcpy(&np[1], name); 1681*69688Seric hp = hes_resolve(np, map->map_file); 1682*69688Seric if (np != nbuf) 1683*69688Seric free(np); 1684*69688Seric } 1685*69688Seric else 1686*69688Seric { 1687*69688Seric hp = hes_resolve(name, map->map_file); 1688*69688Seric } 168969623Seric if (hp == NULL || hp[0] == NULL) 169068350Seric return NULL; 169168350Seric 169269623Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 169369623Seric return map_rewrite(map, name, strlen(name), NULL); 169469623Seric else 169569623Seric return map_rewrite(map, hp[0], strlen(hp[0]), av); 169668350Seric } 169768350Seric 169868350Seric #endif 169968350Seric /* 170068350Seric ** NeXT NETINFO Modules 170168350Seric */ 170268350Seric 170368350Seric #ifdef NETINFO 170468350Seric 170568350Seric #define NETINFO_DEFAULT_DIR "/aliases" 170668350Seric #define NETINFO_DEFAULT_PROPERTY "members" 170768350Seric 170868350Seric 170968350Seric /* 171068350Seric ** NI_MAP_OPEN -- open NetInfo Aliases 171168350Seric */ 171268350Seric 171368350Seric bool 171468350Seric ni_map_open(map, mode) 171568350Seric MAP *map; 171668350Seric int mode; 171768350Seric { 171868350Seric char *p; 171968350Seric 172068350Seric if (tTd(38, 20)) 172168350Seric printf("ni_map_open: %s\n", map->map_file); 172268350Seric 172368350Seric if (*map->map_file == '\0') 172468350Seric map->map_file = NETINFO_DEFAULT_DIR; 172568350Seric 172668350Seric if (map->map_valcolnm == NULL) 172768350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 172868350Seric 172968350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 173068350Seric map->map_coldelim = ','; 173168350Seric 173268350Seric return TRUE; 173368350Seric } 173468350Seric 173568350Seric 173668350Seric /* 173768350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 173868350Seric */ 173968350Seric 174068350Seric char * 174168350Seric ni_map_lookup(map, name, av, statp) 174268350Seric MAP *map; 174368350Seric char *name; 174468350Seric char **av; 174568350Seric int *statp; 174668350Seric { 174768350Seric char *res; 174868350Seric char *propval; 174968350Seric extern char *ni_propval(); 175068350Seric 175168350Seric if (tTd(38, 20)) 175268350Seric printf("ni_map_lookup(%s, %s)\n", 175368350Seric map->map_mname, name); 175468350Seric 175568350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 175668350Seric map->map_valcolnm, map->map_coldelim); 175768350Seric 175868350Seric if (propval == NULL) 175968350Seric return NULL; 176068350Seric 176168350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 176268350Seric res = map_rewrite(map, name, strlen(name), NULL); 176368350Seric else 176468350Seric res = map_rewrite(map, propval, strlen(propval), av); 176568350Seric free(propval); 176668350Seric return res; 176768350Seric } 176868350Seric 176968350Seric #endif 177068350Seric /* 177168350Seric ** TEXT (unindexed text file) Modules 177268350Seric ** 177368350Seric ** This code donated by Sun Microsystems. 177468350Seric */ 177568350Seric 177668350Seric 177768350Seric /* 177868350Seric ** TEXT_MAP_OPEN -- open text table 177968350Seric */ 178068350Seric 178168350Seric bool 178268350Seric text_map_open(map, mode) 178368350Seric MAP *map; 178468350Seric int mode; 178568350Seric { 178668350Seric struct stat sbuf; 178768350Seric 178868350Seric if (tTd(38, 2)) 178968350Seric printf("text_map_open(%s, %s, %d)\n", 179068350Seric map->map_mname, map->map_file, mode); 179168350Seric 179268350Seric if (mode != O_RDONLY) 179368350Seric { 179468350Seric errno = ENODEV; 179568350Seric return FALSE; 179668350Seric } 179768350Seric 179868350Seric if (*map->map_file == '\0') 179968350Seric { 180068350Seric if (tTd(38, 2)) 180168350Seric printf("text_map_open: file name required\n"); 180268350Seric return FALSE; 180368350Seric } 180468350Seric 180568350Seric if (map->map_file[0] != '/') 180668350Seric { 180768350Seric if (tTd(38, 2)) 180868350Seric printf("text_map_open(%s): file name must be fully qualified\n", 180968350Seric map->map_file); 181068350Seric return FALSE; 181168350Seric } 181268350Seric /* check to see if this map actually accessable */ 181368350Seric if (access(map->map_file, R_OK) <0) 181468350Seric return FALSE; 181568350Seric 181668350Seric /* check to see if this map actually exist */ 181768350Seric if (stat(map->map_file, &sbuf) <0) 181868350Seric { 181968350Seric if (tTd(38, 2)) 182068350Seric printf("text_map_open(%s): can not stat %s\n", 182168350Seric map->map_file, map->map_file); 182268350Seric return FALSE; 182368350Seric } 182468350Seric 182568350Seric if (!S_ISREG(sbuf.st_mode)) 182668350Seric { 182768350Seric if (tTd(38, 2)) 182868350Seric printf("text_map_open(%s): %s is not a file\n", 182968350Seric map->map_file, map->map_file); 183068350Seric return FALSE; 183168350Seric } 183268350Seric 183368350Seric if (map->map_keycolnm == NULL) 183468350Seric map->map_keycolno = 0; 183568350Seric else 183668350Seric { 183768350Seric if (!isdigit(*map->map_keycolnm)) 183868350Seric { 183968350Seric if (tTd(38, 2)) 184068350Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 184168350Seric map->map_file, map->map_keycolnm); 184268350Seric return FALSE; 184368350Seric } 184468350Seric map->map_keycolno = atoi(map->map_keycolnm); 184568350Seric } 184668350Seric 184768350Seric if (map->map_valcolnm == NULL) 184868350Seric map->map_valcolno = 0; 184968350Seric else 185068350Seric { 185168350Seric if (!isdigit(*map->map_valcolnm)) 185268350Seric { 185368350Seric if (tTd(38, 2)) 185468350Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 185568350Seric map->map_file, map->map_valcolnm); 185668350Seric return FALSE; 185768350Seric } 185868350Seric map->map_valcolno = atoi(map->map_valcolnm); 185968350Seric } 186068350Seric 186168350Seric if (tTd(38, 2)) 186268350Seric { 186368520Seric printf("text_map_open(%s): delimiter = ", 186468520Seric map->map_file); 186568520Seric if (map->map_coldelim == '\0') 186668520Seric printf("(white space)\n"); 186768520Seric else 186868520Seric printf("%c\n", map->map_coldelim); 186968350Seric } 187068350Seric 187168350Seric return TRUE; 187268350Seric } 187368350Seric 187468350Seric 187568350Seric /* 187668350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 187768350Seric */ 187868350Seric 187968350Seric char * 188068350Seric text_map_lookup(map, name, av, statp) 188168350Seric MAP *map; 188268350Seric char *name; 188368350Seric char **av; 188468350Seric int *statp; 188568350Seric { 188668350Seric char *vp; 188768350Seric auto int vsize; 188868350Seric int buflen; 188968350Seric char search_key[MAXNAME + 1]; 189068350Seric char linebuf[MAXLINE]; 189168350Seric FILE *f; 189268528Seric char buf[MAXNAME + 1]; 189368350Seric char delim; 189468350Seric int key_idx; 189568350Seric bool found_it; 189668350Seric extern char *get_column(); 189768350Seric 189868350Seric 189968350Seric found_it = FALSE; 190068350Seric if (tTd(38, 20)) 190168350Seric printf("text_map_lookup(%s)\n", name); 190268350Seric 190368350Seric buflen = strlen(name); 190468350Seric if (buflen > sizeof search_key - 1) 190568350Seric buflen = sizeof search_key - 1; 190668350Seric bcopy(name, search_key, buflen + 1); 190768350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 190868350Seric makelower(search_key); 190968350Seric 191068350Seric f = fopen(map->map_file, "r"); 191168350Seric if (f == NULL) 191268350Seric { 191368350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 191468350Seric *statp = EX_UNAVAILABLE; 191568350Seric return NULL; 191668350Seric } 191768350Seric key_idx = map->map_keycolno; 191868350Seric delim = map->map_coldelim; 191968350Seric while (fgets(linebuf, MAXLINE, f)) 192068350Seric { 192168350Seric char *lf; 192268350Seric if (linebuf[0] == '#') 192368350Seric continue; /* skip comment line */ 192468350Seric if (lf = strchr(linebuf, '\n')) 192568350Seric *lf = '\0'; 192668350Seric if (!strcasecmp(search_key, 192768350Seric get_column(linebuf, key_idx, delim, buf))) 192868350Seric { 192968350Seric found_it = TRUE; 193068350Seric break; 193168350Seric } 193268350Seric } 193368350Seric fclose(f); 193468350Seric if (!found_it) 193568350Seric { 193668350Seric #ifdef MAP_EXIT_STAT 193768350Seric *statp = EX_NOTFOUND; 193868350Seric #endif 193968350Seric return(NULL); 194068350Seric } 194168350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 194268350Seric vsize = strlen(vp); 194368350Seric #ifdef MAP_EXIT_STAT 194468350Seric *statp = EX_OK; 194568350Seric #endif 194668350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 194768350Seric return map_rewrite(map, name, strlen(name), NULL); 194868350Seric else 194968350Seric return map_rewrite(map, vp, vsize, av); 195068350Seric } 195169401Seric 195269401Seric 195369401Seric /* 195469401Seric ** TEXT_GETCANONNAME -- look up canonical name in hosts file 195569401Seric */ 195669401Seric 195769401Seric bool 195869401Seric text_getcanonname(name, hbsize, statp) 195969401Seric char *name; 196069401Seric int hbsize; 196169401Seric int *statp; 196269401Seric { 196369401Seric int buflen; 196469401Seric int key_idx; 196569401Seric char *cname; 196669401Seric bool found; 196769401Seric char *domain; 196869401Seric FILE *f; 196969401Seric char linebuf[MAXLINE]; 197069401Seric char cbuf[MAXNAME + 1]; 197169401Seric char buf[MAXNAME + 1]; 197269401Seric extern char *get_column(); 197369401Seric 197469401Seric shorten_hostname(name); 197569401Seric 197669401Seric /* we only accept single token search key */ 197769401Seric if (strchr(name, '.') != NULL) 197869401Seric { 197969401Seric *statp = EX_NOHOST; 198069401Seric return FALSE; 198169401Seric } 198269401Seric 198369401Seric found = FALSE; 198469401Seric 198569401Seric f = fopen(HostsFile, "r"); 198669401Seric if (f == NULL) 198769401Seric { 198869401Seric #ifdef MAP_EXIT_STAT 198969401Seric *statp = EX_UNAVAILABLE; 199069401Seric #endif 199169401Seric return FALSE; 199269401Seric } 199369401Seric while (!found && fgets(linebuf, MAXLINE, f) != NULL) 199469401Seric { 199569401Seric char *p; 199669401Seric 199769401Seric if (linebuf[0] == '#') 199869401Seric continue; 199969401Seric if ((p = strchr(linebuf, '\n')) != NULL) 200069401Seric *p = '\0'; 200169663Seric cname = get_column(linebuf, 1, '\0', cbuf); 200269401Seric if (cname != NULL && strcasecmp(name, cname) == 0) 200369401Seric { 200469401Seric found = TRUE; 200569401Seric break; 200669401Seric } 200769401Seric 200869401Seric key_idx = 2; 200969663Seric while ((p = get_column(linebuf, key_idx, '\0', buf)) != NULL) 201069401Seric { 201169401Seric if (strcasecmp(name, p) == 0) 201269401Seric { 201369401Seric found = TRUE; 201469401Seric break; 201569401Seric } 201669401Seric key_idx++; 201769401Seric } 201869401Seric } 201969401Seric fclose(f); 202069401Seric if (!found) 202169401Seric { 202269401Seric *statp = EX_NOHOST; 202369401Seric return FALSE; 202469401Seric } 202569401Seric 202669401Seric if (hbsize >= strlen(cname)) 202769401Seric { 202869401Seric strcpy(name, cname); 202969401Seric *statp = EX_OK; 203069401Seric return TRUE; 203169401Seric } 203269401Seric *statp = EX_UNAVAILABLE; 203369401Seric return FALSE; 203469401Seric } 203568350Seric /* 203660089Seric ** STAB (Symbol Table) Modules 203760089Seric */ 203860089Seric 203960089Seric 204060089Seric /* 204160207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 204260089Seric */ 204360089Seric 204460089Seric char * 204561707Seric stab_map_lookup(map, name, av, pstat) 204660089Seric register MAP *map; 204760089Seric char *name; 204861707Seric char **av; 204961707Seric int *pstat; 205060089Seric { 205160089Seric register STAB *s; 205260089Seric 205360537Seric if (tTd(38, 20)) 205468350Seric printf("stab_lookup(%s, %s)\n", 205568350Seric map->map_mname, name); 205660089Seric 205760089Seric s = stab(name, ST_ALIAS, ST_FIND); 205860089Seric if (s != NULL) 205960089Seric return (s->s_alias); 206060089Seric return (NULL); 206160089Seric } 206260089Seric 206360089Seric 206460089Seric /* 206560207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 206660089Seric */ 206760089Seric 206860089Seric void 206960089Seric stab_map_store(map, lhs, rhs) 207060089Seric register MAP *map; 207160089Seric char *lhs; 207260089Seric char *rhs; 207360089Seric { 207460089Seric register STAB *s; 207560089Seric 207660089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 207760089Seric s->s_alias = newstr(rhs); 207860089Seric } 207960089Seric 208060089Seric 208160089Seric /* 208260207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 208360207Seric ** 208460207Seric ** This is a wierd case -- it is only intended as a fallback for 208560207Seric ** aliases. For this reason, opens for write (only during a 208660207Seric ** "newaliases") always fails, and opens for read open the 208760207Seric ** actual underlying text file instead of the database. 208860089Seric */ 208960089Seric 209060089Seric bool 209160089Seric stab_map_open(map, mode) 209260089Seric register MAP *map; 209360089Seric int mode; 209460089Seric { 209563835Seric FILE *af; 209664284Seric struct stat st; 209763835Seric 209860537Seric if (tTd(38, 2)) 209968350Seric printf("stab_map_open(%s, %s)\n", 210068350Seric map->map_mname, map->map_file); 210160089Seric 210260089Seric if (mode != O_RDONLY) 210360207Seric { 210460207Seric errno = ENODEV; 210560089Seric return FALSE; 210660207Seric } 210760089Seric 210863835Seric af = fopen(map->map_file, "r"); 210963835Seric if (af == NULL) 211063835Seric return FALSE; 211168350Seric readaliases(map, af, FALSE, FALSE); 211264284Seric 211364284Seric if (fstat(fileno(af), &st) >= 0) 211464284Seric map->map_mtime = st.st_mtime; 211563835Seric fclose(af); 211663835Seric 211760089Seric return TRUE; 211860089Seric } 211960089Seric /* 212060089Seric ** Implicit Modules 212156822Seric ** 212260089Seric ** Tries several types. For back compatibility of aliases. 212356822Seric */ 212456822Seric 212560089Seric 212660089Seric /* 212760207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 212860089Seric */ 212960089Seric 213060089Seric char * 213160089Seric impl_map_lookup(map, name, av, pstat) 213260089Seric MAP *map; 213360089Seric char *name; 213456822Seric char **av; 213560089Seric int *pstat; 213656822Seric { 213760537Seric if (tTd(38, 20)) 213868350Seric printf("impl_map_lookup(%s, %s)\n", 213968350Seric map->map_mname, name); 214056822Seric 214160089Seric #ifdef NEWDB 214260207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 214360089Seric return db_map_lookup(map, name, av, pstat); 214460089Seric #endif 214560089Seric #ifdef NDBM 214660207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 214760089Seric return ndbm_map_lookup(map, name, av, pstat); 214860089Seric #endif 214960089Seric return stab_map_lookup(map, name, av, pstat); 215060089Seric } 215160089Seric 215260089Seric /* 215360207Seric ** IMPL_MAP_STORE -- store in open databases 215460089Seric */ 215560089Seric 215660089Seric void 215760089Seric impl_map_store(map, lhs, rhs) 215860089Seric MAP *map; 215960089Seric char *lhs; 216060089Seric char *rhs; 216160089Seric { 216260089Seric #ifdef NEWDB 216360207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 216460089Seric db_map_store(map, lhs, rhs); 216560089Seric #endif 216660089Seric #ifdef NDBM 216760207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 216860089Seric ndbm_map_store(map, lhs, rhs); 216960089Seric #endif 217060089Seric stab_map_store(map, lhs, rhs); 217160089Seric } 217260089Seric 217360089Seric /* 217460089Seric ** IMPL_MAP_OPEN -- implicit database open 217560089Seric */ 217660089Seric 217760089Seric bool 217860089Seric impl_map_open(map, mode) 217960089Seric MAP *map; 218060089Seric int mode; 218160089Seric { 218260089Seric struct stat stb; 218360089Seric 218460537Seric if (tTd(38, 2)) 218568350Seric printf("impl_map_open(%s, %s, %d)\n", 218668350Seric map->map_mname, map->map_file, mode); 218760089Seric 218860089Seric if (stat(map->map_file, &stb) < 0) 218956822Seric { 219060089Seric /* no alias file at all */ 219164718Seric if (tTd(38, 3)) 219264718Seric printf("no map file\n"); 219360089Seric return FALSE; 219456822Seric } 219556822Seric 219660089Seric #ifdef NEWDB 219760207Seric map->map_mflags |= MF_IMPL_HASH; 219860089Seric if (hash_map_open(map, mode)) 219956822Seric { 220064250Seric #if defined(NDBM) && defined(NIS) 220169651Seric if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 220260207Seric #endif 220360207Seric return TRUE; 220460089Seric } 220560207Seric else 220660207Seric map->map_mflags &= ~MF_IMPL_HASH; 220760089Seric #endif 220860089Seric #ifdef NDBM 220960207Seric map->map_mflags |= MF_IMPL_NDBM; 221060089Seric if (ndbm_map_open(map, mode)) 221160089Seric { 221260089Seric return TRUE; 221360089Seric } 221460207Seric else 221560207Seric map->map_mflags &= ~MF_IMPL_NDBM; 221660089Seric #endif 221756822Seric 221864650Seric #if defined(NEWDB) || defined(NDBM) 221960089Seric if (Verbose) 222060089Seric message("WARNING: cannot open alias database %s", map->map_file); 222164964Seric #else 222264964Seric if (mode != O_RDONLY) 222364964Seric usrerr("Cannot rebuild aliases: no database format defined"); 222460207Seric #endif 222560089Seric 222660207Seric return stab_map_open(map, mode); 222756822Seric } 222860089Seric 222960207Seric 223060089Seric /* 223160207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 223260089Seric */ 223360089Seric 223460089Seric void 223560207Seric impl_map_close(map) 223660089Seric MAP *map; 223760089Seric { 223868350Seric if (tTd(38, 20)) 223968350Seric printf("impl_map_close(%s, %s, %x)\n", 224068350Seric map->map_mname, map->map_file, map->map_mflags); 224160089Seric #ifdef NEWDB 224260207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 224360089Seric { 224460207Seric db_map_close(map); 224560207Seric map->map_mflags &= ~MF_IMPL_HASH; 224660089Seric } 224760089Seric #endif 224860089Seric 224960089Seric #ifdef NDBM 225060207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 225160089Seric { 225260207Seric ndbm_map_close(map); 225360207Seric map->map_mflags &= ~MF_IMPL_NDBM; 225460089Seric } 225560089Seric #endif 225660089Seric } 225760207Seric /* 225868350Seric ** User map class. 225968350Seric ** 226068350Seric ** Provides access to the system password file. 226168350Seric */ 226268350Seric 226368350Seric /* 226468350Seric ** USER_MAP_OPEN -- open user map 226568350Seric ** 226668350Seric ** Really just binds field names to field numbers. 226768350Seric */ 226868350Seric 226968350Seric bool 227068350Seric user_map_open(map, mode) 227168350Seric MAP *map; 227268350Seric int mode; 227368350Seric { 227468350Seric if (tTd(38, 2)) 227568350Seric printf("user_map_open(%s)\n", map->map_mname); 227668350Seric 227768350Seric if (mode != O_RDONLY) 227868350Seric { 227968350Seric /* issue a pseudo-error message */ 228068350Seric #ifdef ENOSYS 228168350Seric errno = ENOSYS; 228268350Seric #else 228368350Seric # ifdef EFTYPE 228468350Seric errno = EFTYPE; 228568350Seric # else 228668350Seric errno = ENXIO; 228768350Seric # endif 228868350Seric #endif 228968350Seric return FALSE; 229068350Seric } 229168350Seric if (map->map_valcolnm == NULL) 229268350Seric /* nothing */ ; 229368350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 229468350Seric map->map_valcolno = 1; 229568350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 229668350Seric map->map_valcolno = 2; 229768350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 229868350Seric map->map_valcolno = 3; 229968350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 230068350Seric map->map_valcolno = 4; 230168350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 230268350Seric map->map_valcolno = 5; 230368350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 230468350Seric map->map_valcolno = 6; 230568350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 230668350Seric map->map_valcolno = 7; 230768350Seric else 230868350Seric { 230968350Seric syserr("User map %s: unknown column name %s", 231068350Seric map->map_mname, map->map_valcolnm); 231168350Seric return FALSE; 231268350Seric } 231368350Seric return TRUE; 231468350Seric } 231568350Seric 231668350Seric 231768350Seric /* 231868350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 231968350Seric */ 232068350Seric 232168350Seric char * 232268350Seric user_map_lookup(map, key, av, statp) 232368350Seric MAP *map; 232468350Seric char *key; 232568350Seric char **av; 232668350Seric int *statp; 232768350Seric { 232868350Seric struct passwd *pw; 232968350Seric 233068350Seric if (tTd(38, 20)) 233168350Seric printf("user_map_lookup(%s, %s)\n", 233268350Seric map->map_mname, key); 233368350Seric 233468693Seric pw = sm_getpwnam(key); 233568350Seric if (pw == NULL) 233668350Seric return NULL; 233768350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 233868350Seric return map_rewrite(map, key, strlen(key), NULL); 233968350Seric else 234068350Seric { 234168433Seric char *rwval = NULL; 234268350Seric char buf[30]; 234368350Seric 234468350Seric switch (map->map_valcolno) 234568350Seric { 234668350Seric case 0: 234768350Seric case 1: 234868350Seric rwval = pw->pw_name; 234968350Seric break; 235068350Seric 235168350Seric case 2: 235268350Seric rwval = pw->pw_passwd; 235368350Seric break; 235468350Seric 235568350Seric case 3: 235668350Seric sprintf(buf, "%d", pw->pw_uid); 235768350Seric rwval = buf; 235868350Seric break; 235968350Seric 236068350Seric case 4: 236168350Seric sprintf(buf, "%d", pw->pw_gid); 236268350Seric rwval = buf; 236368350Seric break; 236468350Seric 236568350Seric case 5: 236668350Seric rwval = pw->pw_gecos; 236768350Seric break; 236868350Seric 236968350Seric case 6: 237068350Seric rwval = pw->pw_dir; 237168350Seric break; 237268350Seric 237368350Seric case 7: 237468350Seric rwval = pw->pw_shell; 237568350Seric break; 237668350Seric } 237768350Seric return map_rewrite(map, rwval, strlen(rwval), av); 237868350Seric } 237968350Seric } 238068350Seric /* 238168350Seric ** BESTMX -- find the best MX for a name 238268350Seric ** 238368350Seric ** This is really a hack, but I don't see any obvious way 238468350Seric ** to generalize it at the moment. 238568350Seric */ 238668350Seric 238768350Seric #if NAMED_BIND 238868350Seric 238968350Seric char * 239068350Seric bestmx_map_lookup(map, name, av, statp) 239168350Seric MAP *map; 239268350Seric char *name; 239368350Seric char **av; 239468350Seric int *statp; 239568350Seric { 239668350Seric int nmx; 239768350Seric auto int rcode; 239868350Seric char *mxhosts[MAXMXHOSTS + 1]; 239968350Seric 240068350Seric nmx = getmxrr(name, mxhosts, FALSE, &rcode); 240168350Seric if (nmx <= 0) 240268350Seric return NULL; 240368350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 240468350Seric return map_rewrite(map, name, strlen(name), NULL); 240568350Seric else 240668350Seric return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 240768350Seric } 240868350Seric 240968350Seric #endif 241068350Seric /* 241169453Seric ** Program map type. 241269453Seric ** 241369453Seric ** This provides access to arbitrary programs. It should be used 241469453Seric ** only very sparingly, since there is no way to bound the cost 241569453Seric ** of invoking an arbitrary program. 241669453Seric */ 241769453Seric 241869453Seric char * 241969453Seric prog_map_lookup(map, name, av, statp) 242069453Seric MAP *map; 242169453Seric char *name; 242269453Seric char **av; 242369453Seric int *statp; 242469453Seric { 242569453Seric int i; 242669453Seric register char *p; 242769453Seric int fd; 242869453Seric auto pid_t pid; 242969453Seric char *argv[MAXPV + 1]; 243069453Seric char buf[MAXLINE]; 243169453Seric 243269453Seric if (tTd(38, 20)) 243369453Seric printf("prog_map_lookup(%s, %s) %s\n", 243469453Seric map->map_mname, name, map->map_file); 243569453Seric 243669453Seric i = 0; 243769453Seric argv[i++] = map->map_file; 243869453Seric strcpy(buf, map->map_rebuild); 243969453Seric for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 244069453Seric { 244169453Seric if (i >= MAXPV - 1) 244269453Seric break; 244369453Seric argv[i++] = p; 244469453Seric } 244569453Seric argv[i++] = name; 244669453Seric argv[i] = NULL; 244769453Seric pid = prog_open(argv, &fd, CurEnv); 244869453Seric if (pid < 0) 244969453Seric { 245069453Seric if (tTd(38, 9)) 245169453Seric printf("prog_map_lookup(%s) failed (%s) -- closing", 245269453Seric map->map_mname, errstring(errno)); 245369453Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 245469453Seric return NULL; 245569453Seric } 245669453Seric i = read(fd, buf, sizeof buf - 1); 245769453Seric if (i <= 0 && tTd(38, 2)) 245869453Seric printf("prog_map_lookup(%s): read error %s\n", 245969562Seric map->map_mname, errstring(errno)); 246069453Seric if (i > 0) 246169453Seric { 246269453Seric char *rval; 246369453Seric 246469453Seric buf[i] = '\0'; 246569453Seric p = strchr(buf, '\n'); 246669453Seric if (p != NULL) 246769453Seric *p = '\0'; 246869453Seric 246969453Seric /* collect the return value */ 247069453Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 247169453Seric rval = map_rewrite(map, name, strlen(name), NULL); 247269453Seric else 247369453Seric rval = map_rewrite(map, buf, strlen(buf), NULL); 247469453Seric 247569453Seric /* now flush any additional output */ 247669453Seric while ((i = read(fd, buf, sizeof buf)) > 0) 247769453Seric continue; 247869453Seric close(fd); 247969453Seric 248069453Seric /* and wait for the process to terminate */ 248169453Seric *statp = waitfor(pid); 248269453Seric 248369453Seric return rval; 248469453Seric } 248569453Seric 248669453Seric close(fd); 248769453Seric *statp = waitfor(pid); 248869453Seric return NULL; 248969453Seric } 249069453Seric /* 249168350Seric ** Sequenced map type. 249268350Seric ** 249368350Seric ** Tries each map in order until something matches, much like 249468350Seric ** implicit. Stores go to the first map in the list that can 249568350Seric ** support storing. 249668350Seric ** 249768350Seric ** This is slightly unusual in that there are two interfaces. 249868350Seric ** The "sequence" interface lets you stack maps arbitrarily. 249968350Seric ** The "switch" interface builds a sequence map by looking 250068350Seric ** at a system-dependent configuration file such as 250168350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 250268350Seric ** 250368350Seric ** We don't need an explicit open, since all maps are 250468350Seric ** opened during startup, including underlying maps. 250568350Seric */ 250668350Seric 250768350Seric /* 250868350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 250968350Seric */ 251068350Seric 251168350Seric bool 251268350Seric seq_map_parse(map, ap) 251368350Seric MAP *map; 251468350Seric char *ap; 251568350Seric { 251668350Seric int maxmap; 251768350Seric 251868350Seric if (tTd(38, 2)) 251968350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 252068350Seric maxmap = 0; 252168350Seric while (*ap != '\0') 252268350Seric { 252368350Seric register char *p; 252468350Seric STAB *s; 252568350Seric 252668350Seric /* find beginning of map name */ 252768350Seric while (isascii(*ap) && isspace(*ap)) 252868350Seric ap++; 252968350Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 253068350Seric continue; 253168350Seric if (*p != '\0') 253268350Seric *p++ = '\0'; 253368350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 253468350Seric p++; 253568350Seric if (*ap == '\0') 253668350Seric { 253768350Seric ap = p; 253868350Seric continue; 253968350Seric } 254068350Seric s = stab(ap, ST_MAP, ST_FIND); 254168350Seric if (s == NULL) 254268350Seric { 254368350Seric syserr("Sequence map %s: unknown member map %s", 254468350Seric map->map_mname, ap); 254568350Seric } 254668350Seric else if (maxmap == MAXMAPSTACK) 254768350Seric { 254868350Seric syserr("Sequence map %s: too many member maps (%d max)", 254968350Seric map->map_mname, MAXMAPSTACK); 255068350Seric maxmap++; 255168350Seric } 255268350Seric else if (maxmap < MAXMAPSTACK) 255368350Seric { 255468350Seric map->map_stack[maxmap++] = &s->s_map; 255568350Seric } 255668350Seric ap = p; 255768350Seric } 255868350Seric return TRUE; 255968350Seric } 256068350Seric 256168350Seric 256268350Seric /* 256368350Seric ** SWITCH_MAP_OPEN -- open a switched map 256468350Seric ** 256568350Seric ** This looks at the system-dependent configuration and builds 256668350Seric ** a sequence map that does the same thing. 256768350Seric ** 256868350Seric ** Every system must define a switch_map_find routine in conf.c 256968350Seric ** that will return the list of service types associated with a 257068350Seric ** given service class. 257168350Seric */ 257268350Seric 257368350Seric bool 257468350Seric switch_map_open(map, mode) 257568350Seric MAP *map; 257668350Seric int mode; 257768350Seric { 257868350Seric int mapno; 257968350Seric int nmaps; 258068350Seric char *maptype[MAXMAPSTACK]; 258168350Seric 258268350Seric if (tTd(38, 2)) 258368350Seric printf("switch_map_open(%s, %s, %d)\n", 258468350Seric map->map_mname, map->map_file, mode); 258568350Seric 258668350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 258768350Seric if (tTd(38, 19)) 258868350Seric { 258968350Seric printf("\tswitch_map_find => %d\n", nmaps); 259068350Seric for (mapno = 0; mapno < nmaps; mapno++) 259168350Seric printf("\t\t%s\n", maptype[mapno]); 259268350Seric } 259368350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 259468350Seric return FALSE; 259568350Seric 259668350Seric for (mapno = 0; mapno < nmaps; mapno++) 259768350Seric { 259868350Seric register STAB *s; 259968350Seric char nbuf[MAXNAME + 1]; 260068350Seric 260168350Seric if (maptype[mapno] == NULL) 260268350Seric continue; 260368350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 260468350Seric s = stab(nbuf, ST_MAP, ST_FIND); 260568350Seric if (s == NULL) 260668350Seric { 260768350Seric syserr("Switch map %s: unknown member map %s", 260868350Seric map->map_mname, nbuf); 260968350Seric } 261068350Seric else 261168350Seric { 261268350Seric map->map_stack[mapno] = &s->s_map; 261368350Seric if (tTd(38, 4)) 261468350Seric printf("\tmap_stack[%d] = %s:%s\n", 261568350Seric mapno, s->s_map.map_class->map_cname, 261668350Seric nbuf); 261768350Seric } 261868350Seric } 261968350Seric return TRUE; 262068350Seric } 262168350Seric 262268350Seric 262368350Seric /* 262468350Seric ** SEQ_MAP_CLOSE -- close all underlying maps 262568350Seric */ 262668350Seric 262768350Seric seq_map_close(map) 262868350Seric MAP *map; 262968350Seric { 263068350Seric int mapno; 263168350Seric 263268350Seric if (tTd(38, 20)) 263368350Seric printf("seq_map_close(%s)\n", map->map_mname); 263468350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 263568350Seric { 263668350Seric MAP *mm = map->map_stack[mapno]; 263768350Seric 263868350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 263968350Seric continue; 264068350Seric mm->map_class->map_close(mm); 264168798Seric mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 264268350Seric } 264368350Seric } 264468350Seric 264568350Seric 264668350Seric /* 264768350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 264868350Seric */ 264968350Seric 265068350Seric char * 265168350Seric seq_map_lookup(map, key, args, pstat) 265268350Seric MAP *map; 265368350Seric char *key; 265468350Seric char **args; 265568350Seric int *pstat; 265668350Seric { 265768350Seric int mapno; 265868350Seric int mapbit = 0x01; 265968350Seric 266068350Seric if (tTd(38, 20)) 266168350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 266268350Seric 266368350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 266468350Seric { 266568350Seric MAP *mm = map->map_stack[mapno]; 266668350Seric int stat = 0; 266768350Seric char *rv; 266868350Seric 266968350Seric if (mm == NULL) 267068350Seric continue; 267168350Seric if (!bitset(MF_OPEN, mm->map_mflags)) 267268350Seric { 267368350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 267468350Seric { 267568350Seric *pstat = EX_UNAVAILABLE; 267668350Seric return NULL; 267768350Seric } 267868350Seric continue; 267968350Seric } 268068350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 268168350Seric if (rv != NULL) 268268350Seric return rv; 268368350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 268468350Seric return NULL; 268568350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 268668350Seric { 268768350Seric *pstat = stat; 268868350Seric return NULL; 268968350Seric } 269068350Seric } 269168350Seric return NULL; 269268350Seric } 269368350Seric 269468350Seric 269568350Seric /* 269668350Seric ** SEQ_MAP_STORE -- sequenced map store 269768350Seric */ 269868350Seric 269968350Seric void 270068350Seric seq_map_store(map, key, val) 270168350Seric MAP *map; 270268350Seric char *key; 270368350Seric char *val; 270468350Seric { 270568350Seric int mapno; 270668350Seric 270768350Seric if (tTd(38, 12)) 270868350Seric printf("seq_map_store(%s, %s, %s)\n", 270968350Seric map->map_mname, key, val); 271068350Seric 271168350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 271268350Seric { 271368350Seric MAP *mm = map->map_stack[mapno]; 271468350Seric 271568350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 271668350Seric continue; 271768350Seric 271868350Seric mm->map_class->map_store(mm, key, val); 271968350Seric return; 272068350Seric } 272168350Seric syserr("seq_map_store(%s, %s, %s): no writable map", 272268350Seric map->map_mname, key, val); 272368350Seric } 272468350Seric /* 272569401Seric ** GETCANONNAME -- look up name using service switch 272669401Seric ** 272769401Seric ** Parameters: 272869401Seric ** host -- the host name to look up. 272969401Seric ** hbsize -- the size of the host buffer. 273069401Seric ** trymx -- if set, try MX records. 273169401Seric ** 273269401Seric ** Returns: 273369401Seric ** TRUE -- if the host was found. 273469401Seric ** FALSE -- otherwise. 273569401Seric */ 273669401Seric 273769401Seric bool 273869401Seric getcanonname(host, hbsize, trymx) 273969401Seric char *host; 274069401Seric int hbsize; 274169401Seric bool trymx; 274269401Seric { 274369401Seric int nmaps; 274469401Seric int mapno; 274569401Seric bool found = FALSE; 274669401Seric auto int stat; 274769401Seric char *maptype[MAXMAPSTACK]; 274869401Seric short mapreturn[MAXMAPACTIONS]; 274969401Seric extern int h_errno; 275069401Seric 275169401Seric nmaps = switch_map_find("hosts", maptype, mapreturn); 275269401Seric for (mapno = 0; mapno < nmaps; mapno++) 275369401Seric { 275469401Seric int i; 275569401Seric 275669401Seric if (tTd(38, 20)) 275769401Seric printf("getcanonname(%s), trying %s\n", 275869401Seric host, maptype[mapno]); 275969401Seric if (strcmp("files", maptype[mapno]) == 0) 276069401Seric found = text_getcanonname(host, hbsize, &stat); 276169401Seric #ifdef NIS 276269401Seric else if (strcmp("nis", maptype[mapno]) == 0) 276369401Seric found = nis_getcanonname(host, hbsize, &stat); 276469401Seric #endif 276569401Seric #ifdef NISPLUS 276669401Seric else if (strcmp("nisplus", maptype[mapno]) == 0) 276769401Seric found = nisplus_getcanonname(host, hbsize, &stat); 276869401Seric #endif 276969401Seric #if NAMED_BIND 277069401Seric else if (strcmp("dns", maptype[mapno]) == 0) 277169401Seric found = dns_getcanonname(host, hbsize, trymx, &stat); 277269401Seric #endif 277369401Seric else 277469401Seric { 277569401Seric found = FALSE; 277669401Seric stat = EX_UNAVAILABLE; 277769401Seric } 277869401Seric if (found) 277969401Seric break; 278069401Seric 278169401Seric /* see if we should continue */ 278269401Seric if (stat == EX_TEMPFAIL) 278369401Seric i = MA_TRYAGAIN; 278469401Seric else if (stat == EX_NOHOST) 278569401Seric i = MA_NOTFOUND; 278669401Seric else 278769401Seric i = MA_UNAVAIL; 278869401Seric if (bitset(1 << mapno, mapreturn[i])) 278969401Seric break; 279069401Seric } 279169401Seric 279269401Seric if (found) 279369401Seric { 279469401Seric char *d; 279569401Seric 279669401Seric if (tTd(38, 20)) 279769401Seric printf("getcanonname(%s), found\n", host); 279869401Seric 279969401Seric /* 280069401Seric ** If returned name is still single token, compensate 280169401Seric ** by tagging on $m. This is because some sites set 280269401Seric ** up their DNS or NIS databases wrong. 280369401Seric */ 280469401Seric 280569401Seric if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 280669401Seric { 280769401Seric d = macvalue('m', CurEnv); 280869401Seric if (d != NULL && 280969401Seric hbsize > (int) (strlen(host) + strlen(d) + 1)) 281069401Seric { 281169401Seric if (host[strlen(host) - 1] != '.') 281269401Seric strcat(host, "."); 281369401Seric strcat(host, d); 281469401Seric } 281569401Seric else 281669401Seric { 281769401Seric return FALSE; 281869401Seric } 281969401Seric } 282069401Seric return TRUE; 282169401Seric } 282269401Seric 282369401Seric if (tTd(38, 20)) 282469401Seric printf("getcanonname(%s), failed, stat=%d\n", host, stat); 282569401Seric 282669401Seric #if NAMED_BIND 282769401Seric if (stat == EX_NOHOST) 282869401Seric h_errno = HOST_NOT_FOUND; 282969401Seric else 283069401Seric h_errno = TRY_AGAIN; 283169401Seric #endif 283269401Seric 283369401Seric return FALSE; 283469401Seric } 283569401Seric /* 283660207Seric ** NULL stubs 283760089Seric */ 283860089Seric 283960207Seric bool 284060207Seric null_map_open(map, mode) 284160089Seric MAP *map; 284260207Seric int mode; 284360089Seric { 284460207Seric return TRUE; 284560089Seric } 284660089Seric 284760207Seric void 284860207Seric null_map_close(map) 284960207Seric MAP *map; 285060089Seric { 285160207Seric return; 285260207Seric } 285360089Seric 285460207Seric void 285560207Seric null_map_store(map, key, val) 285660207Seric MAP *map; 285760207Seric char *key; 285860207Seric char *val; 285960089Seric { 286060207Seric return; 286160089Seric } 286268350Seric 286368350Seric 286468350Seric /* 286568350Seric ** BOGUS stubs 286668350Seric */ 286768350Seric 286868350Seric char * 286968350Seric bogus_map_lookup(map, key, args, pstat) 287068350Seric MAP *map; 287168350Seric char *key; 287268350Seric char **args; 287368350Seric int *pstat; 287468350Seric { 287568350Seric *pstat = EX_TEMPFAIL; 287668350Seric return NULL; 287768350Seric } 287868350Seric 287968350Seric MAPCLASS BogusMapClass = 288068350Seric { 288168350Seric "bogus-map", NULL, 0, 288268350Seric NULL, bogus_map_lookup, null_map_store, 288368350Seric null_map_open, null_map_close, 288468350Seric }; 2885