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*69401Seric static char sccsid[] = "@(#)map.c 8.58 (Berkeley) 05/13/95"; 1156822Seric #endif /* not lint */ 1256822Seric 1356822Seric #include "sendmail.h" 1456822Seric 1560089Seric #ifdef NDBM 1668509Seric # include <ndbm.h> 1756822Seric #endif 1860089Seric #ifdef NEWDB 1968509Seric # include <db.h> 2056822Seric #endif 2160089Seric #ifdef NIS 2268524Seric struct dom_binding { int dummy; }; /* needed on IRIX */ 2368509Seric # include <rpcsvc/ypclnt.h> 2457208Seric #endif 2556822Seric 2656822Seric /* 2760089Seric ** MAP.C -- implementations for various map classes. 2856822Seric ** 2960089Seric ** Each map class implements a series of functions: 3060089Seric ** 3160089Seric ** bool map_parse(MAP *map, char *args) 3260089Seric ** Parse the arguments from the config file. Return TRUE 3360089Seric ** if they were ok, FALSE otherwise. Fill in map with the 3460089Seric ** values. 3560089Seric ** 3660222Seric ** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 3760222Seric ** Look up the key in the given map. If found, do any 3860222Seric ** rewriting the map wants (including "args" if desired) 3960089Seric ** and return the value. Set *pstat to the appropriate status 4060222Seric ** on error and return NULL. Args will be NULL if called 4160222Seric ** from the alias routines, although this should probably 4260222Seric ** not be relied upon. It is suggested you call map_rewrite 4360222Seric ** to return the results -- it takes care of null termination 4460222Seric ** and uses a dynamically expanded buffer as needed. 4560089Seric ** 4660089Seric ** void map_store(MAP *map, char *key, char *value) 4760089Seric ** Store the key:value pair in the map. 4860089Seric ** 4960089Seric ** bool map_open(MAP *map, int mode) 5060222Seric ** Open the map for the indicated mode. Mode should 5160222Seric ** be either O_RDONLY or O_RDWR. Return TRUE if it 5260222Seric ** was opened successfully, FALSE otherwise. If the open 5360222Seric ** failed an the MF_OPTIONAL flag is not set, it should 5460222Seric ** also print an error. If the MF_ALIAS bit is set 5560222Seric ** and this map class understands the @:@ convention, it 5660222Seric ** should call aliaswait() before returning. 5760089Seric ** 5860089Seric ** void map_close(MAP *map) 5960089Seric ** Close the map. 60*69401Seric ** 61*69401Seric ** This file also includes the implementation for getcanonname. 62*69401Seric ** It is currently implemented in a pretty ad-hoc manner; it ought 63*69401Seric ** 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 65360089Seric (void) sprintf(buf, "%010ld", curtime()); 65460089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 65560089Seric 65664941Seric (void) gethostname(buf, sizeof buf); 65760089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 65864075Seric 65964075Seric if (inclnull) 66064075Seric map->map_mflags |= MF_INCLNULL; 66160089Seric #endif 66260089Seric 66360089Seric /* write out the distinguished alias */ 66460089Seric ndbm_map_store(map, "@", "@"); 66560089Seric } 66660089Seric dbm_close((DBM *) map->map_db1); 66760089Seric } 66860089Seric 66960089Seric #endif 67060089Seric /* 67160582Seric ** NEWDB (Hash and BTree) Modules 67260089Seric */ 67360089Seric 67460089Seric #ifdef NEWDB 67560089Seric 67660089Seric /* 67760582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 67860582Seric ** 67960582Seric ** These do rather bizarre locking. If you can lock on open, 68060582Seric ** do that to avoid the condition of opening a database that 68160582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 68260582Seric ** there will be a race condition. If opening for read-only, 68360582Seric ** we immediately release the lock to avoid freezing things up. 68460582Seric ** We really ought to hold the lock, but guarantee that we won't 68560582Seric ** be pokey about it. That's hard to do. 68660089Seric */ 68760089Seric 68856822Seric bool 68960089Seric bt_map_open(map, mode) 69056822Seric MAP *map; 69160089Seric int mode; 69256822Seric { 69356822Seric DB *db; 69460228Seric int i; 69560582Seric int omode; 69664373Seric int fd; 69764284Seric struct stat st; 69868528Seric char buf[MAXNAME + 1]; 69956822Seric 70060537Seric if (tTd(38, 2)) 70168350Seric printf("bt_map_open(%s, %s, %d)\n", 70268350Seric map->map_mname, map->map_file, mode); 70360089Seric 70460582Seric omode = mode; 70560582Seric if (omode == O_RDWR) 70660582Seric { 70760582Seric omode |= O_CREAT|O_TRUNC; 70865830Seric #if defined(O_EXLOCK) && HASFLOCK 70960582Seric omode |= O_EXLOCK; 71066843Seric # if !OLD_NEWDB 71160582Seric } 71260582Seric else 71360582Seric { 71460582Seric omode |= O_SHLOCK; 71560582Seric # endif 71660582Seric #endif 71760582Seric } 71860207Seric 71960228Seric (void) strcpy(buf, map->map_file); 72060228Seric i = strlen(buf); 72160228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 72260228Seric (void) strcat(buf, ".db"); 72360582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 72456822Seric if (db == NULL) 72556822Seric { 72664718Seric #ifdef MAYBENEXTRELEASE 72764718Seric if (aliaswait(map, ".db", FALSE)) 72864718Seric return TRUE; 72964718Seric #endif 73060207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 73156836Seric syserr("Cannot open BTREE database %s", map->map_file); 73256822Seric return FALSE; 73356822Seric } 73468350Seric #if !OLD_NEWDB 73564373Seric fd = db->fd(db); 73668778Seric # if defined(O_EXLOCK) && HASFLOCK 73768778Seric if (fd >= 0) 73868778Seric { 73968778Seric if (mode == O_RDONLY) 74068778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 74168778Seric else 74268778Seric map->map_mflags |= MF_LOCKED; 74368778Seric } 74468778Seric # else 74564373Seric if (mode == O_RDWR && fd >= 0) 74664388Seric { 74764388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 74864388Seric map->map_mflags |= MF_LOCKED; 74964388Seric } 75060582Seric # endif 75160582Seric #endif 75260585Seric 75360585Seric /* try to make sure that at least the database header is on disk */ 75460585Seric if (mode == O_RDWR) 75566843Seric #if OLD_NEWDB 75664373Seric (void) db->sync(db); 75764373Seric #else 75860585Seric (void) db->sync(db, 0); 75960585Seric 76064373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 76164284Seric map->map_mtime = st.st_mtime; 76264284Seric #endif 76364284Seric 76460089Seric map->map_db2 = (void *) db; 76560207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 76664718Seric if (!aliaswait(map, ".db", TRUE)) 76764718Seric return FALSE; 76856822Seric return TRUE; 76956822Seric } 77056822Seric 77156822Seric 77256822Seric /* 77356822Seric ** HASH_MAP_INIT -- HASH-style map initialization 77456822Seric */ 77556822Seric 77656822Seric bool 77760089Seric hash_map_open(map, mode) 77856822Seric MAP *map; 77960089Seric int mode; 78056822Seric { 78156822Seric DB *db; 78260228Seric int i; 78360582Seric int omode; 78464373Seric int fd; 78564284Seric struct stat st; 78668528Seric char buf[MAXNAME + 1]; 78756822Seric 78860537Seric if (tTd(38, 2)) 78968350Seric printf("hash_map_open(%s, %s, %d)\n", 79068350Seric map->map_mname, map->map_file, mode); 79160089Seric 79260582Seric omode = mode; 79360582Seric if (omode == O_RDWR) 79460582Seric { 79560582Seric omode |= O_CREAT|O_TRUNC; 79665830Seric #if defined(O_EXLOCK) && HASFLOCK 79760582Seric omode |= O_EXLOCK; 79866843Seric # if !OLD_NEWDB 79960582Seric } 80060582Seric else 80160582Seric { 80260582Seric omode |= O_SHLOCK; 80360582Seric # endif 80460582Seric #endif 80560582Seric } 80660207Seric 80760228Seric (void) strcpy(buf, map->map_file); 80860228Seric i = strlen(buf); 80960228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 81060228Seric (void) strcat(buf, ".db"); 81160582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 81256822Seric if (db == NULL) 81356822Seric { 81464718Seric #ifdef MAYBENEXTRELEASE 81564718Seric if (aliaswait(map, ".db", FALSE)) 81664718Seric return TRUE; 81764718Seric #endif 81860207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 81956836Seric syserr("Cannot open HASH database %s", map->map_file); 82056822Seric return FALSE; 82156822Seric } 82268350Seric #if !OLD_NEWDB 82364373Seric fd = db->fd(db); 82468778Seric # if defined(O_EXLOCK) && HASFLOCK 82568778Seric if (fd >= 0) 82668778Seric { 82768778Seric if (mode == O_RDONLY) 82868778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 82968778Seric else 83068778Seric map->map_mflags |= MF_LOCKED; 83168778Seric } 83268778Seric # else 83364373Seric if (mode == O_RDWR && fd >= 0) 83464388Seric { 83564388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 83664388Seric map->map_mflags |= MF_LOCKED; 83764388Seric } 83860582Seric # endif 83960582Seric #endif 84060585Seric 84160585Seric /* try to make sure that at least the database header is on disk */ 84260585Seric if (mode == O_RDWR) 84366843Seric #if OLD_NEWDB 84464373Seric (void) db->sync(db); 84564373Seric #else 84660585Seric (void) db->sync(db, 0); 84760585Seric 84864373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 84964284Seric map->map_mtime = st.st_mtime; 85064284Seric #endif 85164284Seric 85260089Seric map->map_db2 = (void *) db; 85360207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 85464718Seric if (!aliaswait(map, ".db", TRUE)) 85564718Seric return FALSE; 85656822Seric return TRUE; 85756822Seric } 85856822Seric 85956822Seric 86056822Seric /* 86156822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 86256822Seric */ 86356822Seric 86456822Seric char * 86560089Seric db_map_lookup(map, name, av, statp) 86656822Seric MAP *map; 86760089Seric char *name; 86856822Seric char **av; 86959084Seric int *statp; 87056822Seric { 87156822Seric DBT key, val; 87260422Seric register DB *db = (DB *) map->map_db2; 87360422Seric int st; 87460422Seric int saveerrno; 87564373Seric int fd; 87660089Seric char keybuf[MAXNAME + 1]; 87756822Seric 87860537Seric if (tTd(38, 20)) 87968350Seric printf("db_map_lookup(%s, %s)\n", 88068350Seric map->map_mname, name); 88160089Seric 88260089Seric key.size = strlen(name); 88360089Seric if (key.size > sizeof keybuf - 1) 88460089Seric key.size = sizeof keybuf - 1; 88560089Seric key.data = keybuf; 88660089Seric bcopy(name, keybuf, key.size + 1); 88760207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 88860089Seric makelower(keybuf); 88966843Seric #if !OLD_NEWDB 89064388Seric fd = db->fd(db); 89164388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 89264388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 89360422Seric #endif 89463753Seric st = 1; 89563753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 89663753Seric { 89763753Seric st = db->get(db, &key, &val, 0); 89863753Seric if (st == 0) 89963753Seric map->map_mflags &= ~MF_TRY1NULL; 90063753Seric } 90163753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 90263753Seric { 90363753Seric key.size++; 90463753Seric st = db->get(db, &key, &val, 0); 90563753Seric if (st == 0) 90663753Seric map->map_mflags &= ~MF_TRY0NULL; 90763753Seric } 90860422Seric saveerrno = errno; 90966843Seric #if !OLD_NEWDB 91064388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 91164373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 91260422Seric #endif 91360422Seric if (st != 0) 91460422Seric { 91560422Seric errno = saveerrno; 91660422Seric if (st < 0) 91760422Seric syserr("db_map_lookup: get (%s)", name); 91856822Seric return NULL; 91960422Seric } 92060207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 92163753Seric return map_rewrite(map, name, strlen(name), NULL); 92263753Seric else 92363753Seric return map_rewrite(map, val.data, val.size, av); 92456822Seric } 92556822Seric 92660089Seric 92760089Seric /* 92860089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 92956822Seric */ 93056822Seric 93160089Seric void 93260089Seric db_map_store(map, lhs, rhs) 93360089Seric register MAP *map; 93460089Seric char *lhs; 93560089Seric char *rhs; 93656822Seric { 93760089Seric int stat; 93860089Seric DBT key; 93960089Seric DBT data; 94060089Seric register DB *db = map->map_db2; 94156822Seric 94260537Seric if (tTd(38, 20)) 94368350Seric printf("db_map_store(%s, %s, %s)\n", 94468350Seric map->map_mname, lhs, rhs); 94560089Seric 94660089Seric key.size = strlen(lhs); 94760089Seric key.data = lhs; 94860089Seric 94960089Seric data.size = strlen(rhs); 95060089Seric data.data = rhs; 95160089Seric 95260207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 95356822Seric { 95460089Seric key.size++; 95560089Seric data.size++; 95660089Seric } 95756836Seric 95860089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 95960089Seric if (stat > 0) 96060089Seric { 96168497Seric if (!bitset(MF_APPEND, map->map_mflags)) 96268497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 96368497Seric else 96468497Seric { 96568497Seric static char *buf = NULL; 96668497Seric static int bufsiz = 0; 96768497Seric DBT old; 96868497Seric 96968497Seric old.data = db_map_lookup(map, key.data, NULL, &stat); 97068497Seric if (old.data != NULL) 97168497Seric { 97268497Seric old.size = strlen(old.data); 97368497Seric if (data.size + old.size + 2 > bufsiz) 97468497Seric { 97568497Seric if (buf != NULL) 97668497Seric (void) free(buf); 97768497Seric bufsiz = data.size + old.size + 2; 97868497Seric buf = xalloc(bufsiz); 97968497Seric } 98068497Seric sprintf(buf, "%s,%s", data.data, old.data); 98168497Seric data.size = data.size + old.size + 1; 98268497Seric data.data = buf; 98368497Seric if (tTd(38, 9)) 98468497Seric printf("db_map_store append=%s\n", data.data); 98568497Seric } 98668497Seric } 98760089Seric stat = db->put(db, &key, &data, 0); 98860089Seric } 98960089Seric if (stat != 0) 99060089Seric syserr("readaliases: db put (%s)", lhs); 99160089Seric } 99256836Seric 99356847Seric 99460089Seric /* 99560089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 99660089Seric */ 99760089Seric 99860089Seric void 99960089Seric db_map_close(map) 100060089Seric MAP *map; 100160089Seric { 100260089Seric register DB *db = map->map_db2; 100360089Seric 100460537Seric if (tTd(38, 9)) 100568350Seric printf("db_map_close(%s, %s, %x)\n", 100668350Seric map->map_mname, map->map_file, map->map_mflags); 100760089Seric 100860207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 100958804Seric { 101060089Seric /* write out the distinguished alias */ 101160089Seric db_map_store(map, "@", "@"); 101258804Seric } 101358963Seric 101460089Seric if (db->close(db) != 0) 101560089Seric syserr("readaliases: db close failure"); 101656822Seric } 101757208Seric 101860089Seric #endif 101960089Seric /* 102060089Seric ** NIS Modules 102160089Seric */ 102260089Seric 102360089Seric # ifdef NIS 102460089Seric 102564369Seric # ifndef YPERR_BUSY 102664369Seric # define YPERR_BUSY 16 102764369Seric # endif 102864369Seric 102957208Seric /* 103060089Seric ** NIS_MAP_OPEN -- open DBM map 103157208Seric */ 103257208Seric 103357208Seric bool 103460089Seric nis_map_open(map, mode) 103557208Seric MAP *map; 103660089Seric int mode; 103757208Seric { 103857216Seric int yperr; 103960215Seric register char *p; 104060215Seric auto char *vp; 104160215Seric auto int vsize; 104257216Seric char *master; 104357216Seric 104460537Seric if (tTd(38, 2)) 104568350Seric printf("nis_map_open(%s, %s)\n", 104668350Seric map->map_mname, map->map_file); 104760089Seric 104860207Seric if (mode != O_RDONLY) 104960207Seric { 105064650Seric /* issue a pseudo-error message */ 105164650Seric #ifdef ENOSYS 105264650Seric errno = ENOSYS; 105364650Seric #else 105464650Seric # ifdef EFTYPE 105564650Seric errno = EFTYPE; 105664650Seric # else 105764650Seric errno = ENXIO; 105864650Seric # endif 105964650Seric #endif 106060207Seric return FALSE; 106160207Seric } 106260207Seric 106360089Seric p = strchr(map->map_file, '@'); 106460089Seric if (p != NULL) 106560089Seric { 106660089Seric *p++ = '\0'; 106760089Seric if (*p != '\0') 106860089Seric map->map_domain = p; 106960089Seric } 107060215Seric 107160089Seric if (*map->map_file == '\0') 107260089Seric map->map_file = "mail.aliases"; 107360089Seric 107466157Seric if (map->map_domain == NULL) 107566157Seric { 107666157Seric yperr = yp_get_default_domain(&map->map_domain); 107766157Seric if (yperr != 0) 107866157Seric { 107966744Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 108068350Seric syserr("421 NIS map %s specified, but NIS not running\n", 108166744Seric map->map_file); 108266157Seric return FALSE; 108366157Seric } 108466157Seric } 108566157Seric 108660215Seric /* check to see if this map actually exists */ 108760089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 108860089Seric &vp, &vsize); 108960537Seric if (tTd(38, 10)) 109060089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 109160089Seric map->map_domain, map->map_file, yperr_string(yperr)); 109260089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 109368350Seric { 109468350Seric if (!bitset(MF_ALIAS, map->map_mflags) || 109568350Seric aliaswait(map, NULL, TRUE)) 109668350Seric return TRUE; 109768350Seric } 109860215Seric 109960215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 110068735Seric { 110168735Seric syserr("421 Cannot bind to map %s in domain %s: %s", 110268735Seric map->map_file, map->map_domain, yperr_string(yperr)); 110368735Seric } 110460215Seric 110560089Seric return FALSE; 110660089Seric } 110760089Seric 110860089Seric 110960089Seric /* 111057208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 111157208Seric */ 111257208Seric 111357208Seric char * 111460089Seric nis_map_lookup(map, name, av, statp) 111557208Seric MAP *map; 111660089Seric char *name; 111757208Seric char **av; 111859084Seric int *statp; 111957208Seric { 112057208Seric char *vp; 112157642Seric auto int vsize; 112259274Seric int buflen; 112360215Seric int yperr; 112460089Seric char keybuf[MAXNAME + 1]; 112557208Seric 112660537Seric if (tTd(38, 20)) 112768350Seric printf("nis_map_lookup(%s, %s)\n", 112868350Seric map->map_mname, name); 112960089Seric 113060089Seric buflen = strlen(name); 113160089Seric if (buflen > sizeof keybuf - 1) 113260089Seric buflen = sizeof keybuf - 1; 113360089Seric bcopy(name, keybuf, buflen + 1); 113460207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 113560089Seric makelower(keybuf); 113663753Seric yperr = YPERR_KEY; 113763753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 113863753Seric { 113963753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 114063753Seric &vp, &vsize); 114163753Seric if (yperr == 0) 114263753Seric map->map_mflags &= ~MF_TRY1NULL; 114363753Seric } 114463753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 114563753Seric { 114659274Seric buflen++; 114763753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 114863753Seric &vp, &vsize); 114963753Seric if (yperr == 0) 115063753Seric map->map_mflags &= ~MF_TRY0NULL; 115163753Seric } 115260089Seric if (yperr != 0) 115360089Seric { 115460089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 115560215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 115657208Seric return NULL; 115760089Seric } 115860207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 115963753Seric return map_rewrite(map, name, strlen(name), NULL); 116063753Seric else 116163753Seric return map_rewrite(map, vp, vsize, av); 116257208Seric } 116357208Seric 1164*69401Seric 1165*69401Seric /* 1166*69401Seric ** NIS_GETCANONNAME -- look up canonical name in NIS 1167*69401Seric */ 1168*69401Seric 1169*69401Seric bool 1170*69401Seric nis_getcanonname(name, hbsize, statp) 1171*69401Seric char *name; 1172*69401Seric int hbsize; 1173*69401Seric int *statp; 1174*69401Seric { 1175*69401Seric char *vp; 1176*69401Seric auto int vsize; 1177*69401Seric int keylen; 1178*69401Seric int yperr; 1179*69401Seric static bool try0null = TRUE; 1180*69401Seric static bool try1null = TRUE; 1181*69401Seric static char *yp_domain = NULL; 1182*69401Seric char *domain, *p; 1183*69401Seric char host_record[MAXLINE]; 1184*69401Seric char buf[MAXNAME]; 1185*69401Seric char *cname; 1186*69401Seric extern char *get_column(); 1187*69401Seric 1188*69401Seric if (tTd(38, 20)) 1189*69401Seric printf("nis_getcanonname(%s)\n", name); 1190*69401Seric 1191*69401Seric shorten_hostname(name); 1192*69401Seric 1193*69401Seric /* we only accept single token search key */ 1194*69401Seric if (strchr(name, '.')) 1195*69401Seric { 1196*69401Seric *statp = EX_NOHOST; 1197*69401Seric return FALSE; 1198*69401Seric } 1199*69401Seric 1200*69401Seric keylen = strlen(name); 1201*69401Seric 1202*69401Seric if (yp_domain == NULL) 1203*69401Seric yp_get_default_domain(&yp_domain); 1204*69401Seric makelower(name); 1205*69401Seric yperr = YPERR_KEY; 1206*69401Seric if (try0null) 1207*69401Seric { 1208*69401Seric yperr = yp_match(yp_domain, "hosts.byname", name, keylen, 1209*69401Seric &vp, &vsize); 1210*69401Seric if (yperr == 0) 1211*69401Seric try1null = FALSE; 1212*69401Seric } 1213*69401Seric if (yperr == YPERR_KEY && try1null) 1214*69401Seric { 1215*69401Seric keylen++; 1216*69401Seric yperr = yp_match(yp_domain, "hosts.byname", name, keylen, 1217*69401Seric &vp, &vsize); 1218*69401Seric if (yperr == 0) 1219*69401Seric try0null = FALSE; 1220*69401Seric } 1221*69401Seric if (yperr != 0) 1222*69401Seric { 1223*69401Seric if (yperr == YPERR_KEY) 1224*69401Seric *statp = EX_NOHOST; 1225*69401Seric else if (yperr == YPERR_BUSY) 1226*69401Seric *statp = EX_TEMPFAIL; 1227*69401Seric else 1228*69401Seric *statp = EX_UNAVAILABLE; 1229*69401Seric return FALSE; 1230*69401Seric } 1231*69401Seric strncpy(host_record, vp, vsize); 1232*69401Seric host_record[vsize] = '\0'; 1233*69401Seric cname = get_column(host_record, 1, '\t', buf); 1234*69401Seric if (cname == NULL) 1235*69401Seric { 1236*69401Seric /* this should not happen, but.... */ 1237*69401Seric *statp = EX_NOHOST; 1238*69401Seric return FALSE; 1239*69401Seric } 1240*69401Seric 1241*69401Seric if (hbsize >= strlen(cname)) 1242*69401Seric { 1243*69401Seric strcpy(name, cname); 1244*69401Seric *statp = EX_OK; 1245*69401Seric return TRUE; 1246*69401Seric } 1247*69401Seric *statp = EX_UNAVAILABLE; 1248*69401Seric return FALSE; 1249*69401Seric } 1250*69401Seric 125168350Seric #endif 125268350Seric /* 125368350Seric ** NISPLUS Modules 125468350Seric ** 125568350Seric ** This code donated by Sun Microsystems. 125668350Seric */ 125767848Seric 125868350Seric #ifdef NISPLUS 125968350Seric 126068350Seric #undef NIS /* symbol conflict in nis.h */ 126168350Seric #include <rpcsvc/nis.h> 126268350Seric #include <rpcsvc/nislib.h> 126368350Seric 126468350Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 126568350Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 126668350Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 126768350Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 126868350Seric 126967848Seric /* 127068350Seric ** NISPLUS_MAP_OPEN -- open nisplus table 127167848Seric */ 127267848Seric 127368350Seric bool 127468350Seric nisplus_map_open(map, mode) 127567848Seric MAP *map; 127668350Seric int mode; 127767848Seric { 127868350Seric register char *p; 127968350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 128068350Seric nis_result *res = NULL; 128168350Seric u_int objs_len; 128268350Seric nis_object *obj_ptr; 128368350Seric int retry_cnt, max_col, i; 128468350Seric 128568350Seric if (tTd(38, 2)) 128668350Seric printf("nisplus_map_open(%s, %s, %d)\n", 128768350Seric map->map_mname, map->map_file, mode); 128868350Seric 128968350Seric if (mode != O_RDONLY) 129068350Seric { 129168350Seric errno = ENODEV; 129268350Seric return FALSE; 129368350Seric } 129468350Seric 129568350Seric if (*map->map_file == '\0') 129668350Seric map->map_file = "mail_aliases.org_dir"; 129768350Seric 129868350Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 129968350Seric { 130068350Seric /* set default NISPLUS Domain to $m */ 130168350Seric extern char *nisplus_default_domain(); 130268350Seric 130368350Seric map->map_domain = newstr(nisplus_default_domain()); 130468350Seric if (tTd(38, 2)) 130568350Seric printf("nisplus_map_open(%s): using domain %s\n", 130668350Seric map->map_file, map->map_domain); 130768350Seric } 130868350Seric if (!PARTIAL_NAME(map->map_file)) 130968350Seric map->map_domain = newstr(""); 131068350Seric 131168350Seric /* check to see if this map actually exists */ 131268350Seric if (PARTIAL_NAME(map->map_file)) 131368350Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 131468350Seric else 131568350Seric strcpy(qbuf, map->map_file); 131668350Seric 131768350Seric retry_cnt = 0; 131868350Seric while (res == NULL || res->status != NIS_SUCCESS) 131968350Seric { 132068350Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 132168350Seric switch (res->status) 132268350Seric { 132368350Seric case NIS_SUCCESS: 132468350Seric case NIS_TRYAGAIN: 132568350Seric case NIS_RPCERROR: 132668350Seric case NIS_NAMEUNREACHABLE: 132768350Seric break; 132868350Seric 132968350Seric default: /* all other nisplus errors */ 133068350Seric #if 0 133168350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 133268350Seric syserr("421 Cannot find table %s.%s: %s", 133368350Seric map->map_file, map->map_domain, 133468350Seric nis_sperrno(res->status)); 133568350Seric #endif 133668350Seric errno = EBADR; 133768350Seric return FALSE; 133868350Seric } 133968350Seric sleep(2); /* try not to overwhelm hosed server */ 134068350Seric if (retry_cnt++ > 4) 134168350Seric { 134268350Seric errno = EBADR; 134368350Seric return FALSE; 134468350Seric } 134568350Seric } 134668350Seric 134768350Seric if (NIS_RES_NUMOBJ(res) != 1 || 134868350Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 134968350Seric { 135068350Seric if (tTd(38, 10)) 135168350Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 135268350Seric #if 0 135368350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 135468350Seric syserr("421 %s.%s: %s is not a table", 135568350Seric map->map_file, map->map_domain, 135668350Seric nis_sperrno(res->status)); 135768350Seric #endif 135868350Seric errno = EBADR; 135968350Seric return FALSE; 136068350Seric } 136168350Seric /* default key column is column 0 */ 136268350Seric if (map->map_keycolnm == NULL) 136368350Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 136468350Seric 136568350Seric max_col = COL_MAX(res); 136668350Seric 136768350Seric /* verify the key column exist */ 136868350Seric for (i=0; i< max_col; i++) 136968350Seric { 137068350Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 137168350Seric break; 137268350Seric } 137368350Seric if (i == max_col) 137468350Seric { 137568350Seric if (tTd(38, 2)) 137668350Seric printf("nisplus_map_open(%s): can not find key column %s\n", 137768350Seric map->map_file, map->map_keycolnm); 137868350Seric errno = EBADR; 137968350Seric return FALSE; 138068350Seric } 138168350Seric 138268350Seric /* default value column is the last column */ 138368350Seric if (map->map_valcolnm == NULL) 138468350Seric { 138568350Seric map->map_valcolno = max_col - 1; 138668350Seric return TRUE; 138768350Seric } 138868350Seric 138968350Seric for (i=0; i< max_col; i++) 139068350Seric { 139168350Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 139268350Seric { 139368350Seric map->map_valcolno = i; 139468350Seric return TRUE; 139568350Seric } 139668350Seric } 139768350Seric 139868350Seric if (tTd(38, 2)) 139968350Seric printf("nisplus_map_open(%s): can not find column %s\n", 140068350Seric map->map_file, map->map_keycolnm); 140168350Seric errno = EBADR; 140268350Seric return FALSE; 140367848Seric } 140467848Seric 140567848Seric 140667848Seric /* 140768350Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 140867848Seric */ 140967848Seric 141068350Seric char * 141168350Seric nisplus_map_lookup(map, name, av, statp) 141267848Seric MAP *map; 141368350Seric char *name; 141468350Seric char **av; 141568350Seric int *statp; 141667848Seric { 141768350Seric char *vp; 141868350Seric auto int vsize; 141968350Seric int buflen; 142068350Seric char search_key[MAXNAME + 1]; 142168350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 142268350Seric nis_result *result; 142368350Seric 142468350Seric if (tTd(38, 20)) 142568350Seric printf("nisplus_map_lookup(%s, %s)\n", 142668350Seric map->map_mname, name); 142768350Seric 142868350Seric if (!bitset(MF_OPEN, map->map_mflags)) 142968350Seric { 143068350Seric if (nisplus_map_open(map, O_RDONLY)) 143168350Seric map->map_mflags |= MF_OPEN; 143268350Seric else 143368350Seric { 143468350Seric *statp = EX_UNAVAILABLE; 143568350Seric return NULL; 143668350Seric } 143768350Seric } 143868350Seric 143968350Seric buflen = strlen(name); 144068350Seric if (buflen > sizeof search_key - 1) 144168350Seric buflen = sizeof search_key - 1; 144268350Seric bcopy(name, search_key, buflen + 1); 144368350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 144468350Seric makelower(search_key); 144568350Seric 144668350Seric /* construct the query */ 144768350Seric if (PARTIAL_NAME(map->map_file)) 144868350Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 144968350Seric search_key, map->map_file, map->map_domain); 145068350Seric else 145168350Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 145268350Seric search_key, map->map_file); 145368350Seric 145468350Seric if (tTd(38, 20)) 145568350Seric printf("qbuf=%s\n", qbuf); 145668350Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 145768350Seric if (result->status == NIS_SUCCESS) 145868350Seric { 145968350Seric int count; 146068350Seric char *str; 146168350Seric 146268350Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 146368350Seric { 146468350Seric if (LogLevel > 10) 146568350Seric syslog(LOG_WARNING, 146668350Seric "%s:Lookup error, expected 1 entry, got (%d)", 146768350Seric map->map_file, count); 146868350Seric 146968350Seric /* ignore second entry */ 147068350Seric if (tTd(38, 20)) 147168350Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 147268350Seric name, count); 147368350Seric } 147468350Seric 147568350Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 147668350Seric /* set the length of the result */ 147768350Seric if (vp == NULL) 147868350Seric vp = ""; 147968350Seric vsize = strlen(vp); 148068350Seric if (tTd(38, 20)) 148168350Seric printf("nisplus_map_lookup(%s), found %s\n", 148268350Seric name, vp); 148368350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 148468350Seric str = map_rewrite(map, name, strlen(name), NULL); 148568350Seric else 148668350Seric str = map_rewrite(map, vp, vsize, av); 148768350Seric nis_freeresult(result); 148868350Seric #ifdef MAP_EXIT_STAT 148968350Seric *statp = EX_OK; 149068350Seric #endif 149168350Seric return str; 149268350Seric } 149368350Seric else 149468350Seric { 149568350Seric #ifdef MAP_EXIT_STAT 149668350Seric if (result->status == NIS_NOTFOUND) 149768350Seric *statp = EX_NOTFOUND; 149868350Seric else if (result->status == NIS_TRYAGAIN) 149968350Seric *statp = EX_TEMPFAIL; 150068350Seric else 150168350Seric { 150268350Seric *statp = EX_UNAVAILABLE; 150368350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 150468350Seric } 150568350Seric #else 150668350Seric if ((result->status != NIS_NOTFOUND) && 150768350Seric (result->status != NIS_TRYAGAIN)) 150868350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 150968350Seric #endif 151068350Seric } 151168350Seric if (tTd(38, 20)) 151268350Seric printf("nisplus_map_lookup(%s), failed\n", name); 151368350Seric nis_freeresult(result); 151468350Seric return NULL; 151567848Seric } 151667848Seric 151768350Seric 1518*69401Seric 1519*69401Seric /* 1520*69401Seric ** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 1521*69401Seric */ 1522*69401Seric 1523*69401Seric bool 1524*69401Seric nisplus_getcanonname(name, hbsize, statp) 1525*69401Seric char *name; 1526*69401Seric int hbsize; 1527*69401Seric int *statp; 1528*69401Seric { 1529*69401Seric char *vp; 1530*69401Seric auto int vsize; 1531*69401Seric int buflen; 1532*69401Seric char buf1[MAXLINE + NIS_MAXNAMELEN]; 1533*69401Seric static char *nis_path = NULL; 1534*69401Seric static char nis_path_buf[MAXLINE]; 1535*69401Seric nis_result *result; 1536*69401Seric char *p; 1537*69401Seric int len; 1538*69401Seric 1539*69401Seric if (nis_path == NULL) 1540*69401Seric { 1541*69401Seric char *ptr; 1542*69401Seric char pathbuf[MAXLINE]; 1543*69401Seric 1544*69401Seric strcpy(buf1, macvalue('m', CurEnv)); 1545*69401Seric strcat(buf1, "."); 1546*69401Seric /* try the host tabe in $m */ 1547*69401Seric if (hosts_table_ok(buf1)) 1548*69401Seric strcpy(pathbuf, buf1); 1549*69401Seric else 1550*69401Seric strcpy(pathbuf, "$"); 1551*69401Seric 1552*69401Seric nis_path = nis_path_buf; 1553*69401Seric sprintf(nis_path, "NIS_PATH=%s", pathbuf); 1554*69401Seric } 1555*69401Seric 1556*69401Seric if (nis_path[0] != '\0') 1557*69401Seric putenv(nis_path); 1558*69401Seric else 1559*69401Seric syslog(LOG_WARNING, "no NIS+ path defined"); 1560*69401Seric 1561*69401Seric shorten_hostname(name); 1562*69401Seric 1563*69401Seric p = strchr(name, '.'); 1564*69401Seric if (p == NULL) 1565*69401Seric { 1566*69401Seric /* single token */ 1567*69401Seric sprintf(buf1, "[name=%s],hosts.org_dir", name); 1568*69401Seric } 1569*69401Seric else if (p[1] != '\0') 1570*69401Seric { 1571*69401Seric /* multi token -- take only first token in name buf */ 1572*69401Seric *p = '\0'; 1573*69401Seric sprintf(buf1, "[name=%s],hosts.org_dir.%s", name, &p[1]); 1574*69401Seric } 1575*69401Seric else 1576*69401Seric { 1577*69401Seric *statp = EX_NOHOST; 1578*69401Seric return FALSE; 1579*69401Seric } 1580*69401Seric 1581*69401Seric if (tTd(38, 20)) 1582*69401Seric printf("\nnisplus_getcanoname(%s), qbuf=%s\n%s\n", 1583*69401Seric name, buf1, nis_path); 1584*69401Seric 1585*69401Seric result = nis_list(buf1, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 1586*69401Seric NULL, NULL); 1587*69401Seric 1588*69401Seric /* unset NIS_PATH, just in case */ 1589*69401Seric unsetenv("NIS_PATH"); 1590*69401Seric 1591*69401Seric if (result->status == NIS_SUCCESS) 1592*69401Seric { 1593*69401Seric int count; 1594*69401Seric char *str; 1595*69401Seric char *domain; 1596*69401Seric 1597*69401Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 1598*69401Seric { 1599*69401Seric #ifdef LOG 1600*69401Seric if (LogLevel > 10) 1601*69401Seric syslog(LOG_WARNING, 1602*69401Seric "nisplus_getcanonname: Lookup error, expected 1 entry, got (%d)", 1603*69401Seric count); 1604*69401Seric #endif 1605*69401Seric 1606*69401Seric /* ignore second entry */ 1607*69401Seric if (tTd(38, 20)) 1608*69401Seric printf("nisplus_getcanoname(%s), got %d entries, addtional entries ignores\n", name); 1609*69401Seric } 1610*69401Seric 1611*69401Seric if (tTd(38, 20)) 1612*69401Seric printf("nisplus_getcanoname(%s), found in directory \"%s\"\n", 1613*69401Seric name, (NIS_RES_OBJECT(result))->zo_domain); 1614*69401Seric 1615*69401Seric 1616*69401Seric vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 1617*69401Seric vsize = strlen(vp); 1618*69401Seric if (tTd(38, 20)) 1619*69401Seric printf("nisplus_getcanonname(%s), found %s\n", 1620*69401Seric name, vp); 1621*69401Seric domain = macvalue('m', CurEnv); 1622*69401Seric if (hbsize > (vsize + ((int) strlen(domain)))) 1623*69401Seric { 1624*69401Seric sprintf(name, "%s.%s", vp, domain); 1625*69401Seric *statp = EX_OK; 1626*69401Seric } 1627*69401Seric else 1628*69401Seric *statp = EX_NOHOST; 1629*69401Seric nis_freeresult(result); 1630*69401Seric return TRUE; 1631*69401Seric } 1632*69401Seric else 1633*69401Seric { 1634*69401Seric if (result->status == NIS_NOTFOUND) 1635*69401Seric *statp = EX_NOHOST; 1636*69401Seric else if (result->status == NIS_TRYAGAIN) 1637*69401Seric *statp = EX_TEMPFAIL; 1638*69401Seric else 1639*69401Seric { 1640*69401Seric *statp = EX_UNAVAILABLE; 1641*69401Seric } 1642*69401Seric } 1643*69401Seric if (tTd(38, 20)) 1644*69401Seric printf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 1645*69401Seric name, result->status, *statp); 1646*69401Seric nis_freeresult(result); 1647*69401Seric return FALSE; 1648*69401Seric } 1649*69401Seric 1650*69401Seric 165168350Seric char * 165268350Seric nisplus_default_domain() 165368350Seric { 165468528Seric static char default_domain[MAXNAME + 1] = ""; 165568350Seric char *p; 165668350Seric 165768350Seric if (default_domain[0] != '\0') 165868350Seric return(default_domain); 165968350Seric 166068458Seric p = nis_local_directory(); 166168350Seric strcpy(default_domain, p); 166268458Seric return default_domain; 166368350Seric } 166468350Seric 166568350Seric #endif /* NISPLUS */ 166667848Seric /* 166768350Seric ** HESIOD Modules 166868350Seric */ 166968350Seric 167068350Seric #ifdef HESIOD 167168350Seric 167268350Seric #include <hesiod.h> 167368350Seric 167468350Seric char * 167568350Seric hes_map_lookup(map, name, av, statp) 167668350Seric MAP *map; 167768350Seric char *name; 167868350Seric char **av; 167968350Seric int *statp; 168068350Seric { 168168350Seric char **hp; 168268350Seric char *retdata = NULL; 168368350Seric int i; 168468350Seric 168568350Seric if (tTd(38, 20)) 168668350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 168768350Seric 168868350Seric hp = hes_resolve(name, map->map_file); 168968350Seric if (hp == NULL) 169068350Seric return NULL; 169168350Seric 169268350Seric if (hp[0] != NULL) 169368350Seric { 169468350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 169568350Seric retdata = map_rewrite(map, name, strlen(name), NULL); 169668350Seric else 169768350Seric retdata = map_rewrite(map, hp[0], strlen(hp[0]), av); 169868350Seric } 169968350Seric 170068350Seric for (i = 0; hp[i] != NULL; i++) 170168350Seric free(hp[i]); 170268350Seric free(hp); 170368350Seric return retdata; 170468350Seric } 170568350Seric 170668350Seric #endif 170768350Seric /* 170868350Seric ** NeXT NETINFO Modules 170968350Seric */ 171068350Seric 171168350Seric #ifdef NETINFO 171268350Seric 171368350Seric #define NETINFO_DEFAULT_DIR "/aliases" 171468350Seric #define NETINFO_DEFAULT_PROPERTY "members" 171568350Seric 171668350Seric 171768350Seric /* 171868350Seric ** NI_MAP_OPEN -- open NetInfo Aliases 171968350Seric */ 172068350Seric 172168350Seric bool 172268350Seric ni_map_open(map, mode) 172368350Seric MAP *map; 172468350Seric int mode; 172568350Seric { 172668350Seric char *p; 172768350Seric 172868350Seric if (tTd(38, 20)) 172968350Seric printf("ni_map_open: %s\n", map->map_file); 173068350Seric 173168350Seric if (*map->map_file == '\0') 173268350Seric map->map_file = NETINFO_DEFAULT_DIR; 173368350Seric 173468350Seric if (map->map_valcolnm == NULL) 173568350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 173668350Seric 173768350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 173868350Seric map->map_coldelim = ','; 173968350Seric 174068350Seric return TRUE; 174168350Seric } 174268350Seric 174368350Seric 174468350Seric /* 174568350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 174668350Seric */ 174768350Seric 174868350Seric char * 174968350Seric ni_map_lookup(map, name, av, statp) 175068350Seric MAP *map; 175168350Seric char *name; 175268350Seric char **av; 175368350Seric int *statp; 175468350Seric { 175568350Seric char *res; 175668350Seric char *propval; 175768350Seric extern char *ni_propval(); 175868350Seric 175968350Seric if (tTd(38, 20)) 176068350Seric printf("ni_map_lookup(%s, %s)\n", 176168350Seric map->map_mname, name); 176268350Seric 176368350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 176468350Seric map->map_valcolnm, map->map_coldelim); 176568350Seric 176668350Seric if (propval == NULL) 176768350Seric return NULL; 176868350Seric 176968350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 177068350Seric res = map_rewrite(map, name, strlen(name), NULL); 177168350Seric else 177268350Seric res = map_rewrite(map, propval, strlen(propval), av); 177368350Seric free(propval); 177468350Seric return res; 177568350Seric } 177668350Seric 177768350Seric #endif 177868350Seric /* 177968350Seric ** TEXT (unindexed text file) Modules 178068350Seric ** 178168350Seric ** This code donated by Sun Microsystems. 178268350Seric */ 178368350Seric 178468350Seric 178568350Seric /* 178668350Seric ** TEXT_MAP_OPEN -- open text table 178768350Seric */ 178868350Seric 178968350Seric bool 179068350Seric text_map_open(map, mode) 179168350Seric MAP *map; 179268350Seric int mode; 179368350Seric { 179468350Seric struct stat sbuf; 179568350Seric 179668350Seric if (tTd(38, 2)) 179768350Seric printf("text_map_open(%s, %s, %d)\n", 179868350Seric map->map_mname, map->map_file, mode); 179968350Seric 180068350Seric if (mode != O_RDONLY) 180168350Seric { 180268350Seric errno = ENODEV; 180368350Seric return FALSE; 180468350Seric } 180568350Seric 180668350Seric if (*map->map_file == '\0') 180768350Seric { 180868350Seric if (tTd(38, 2)) 180968350Seric printf("text_map_open: file name required\n"); 181068350Seric return FALSE; 181168350Seric } 181268350Seric 181368350Seric if (map->map_file[0] != '/') 181468350Seric { 181568350Seric if (tTd(38, 2)) 181668350Seric printf("text_map_open(%s): file name must be fully qualified\n", 181768350Seric map->map_file); 181868350Seric return FALSE; 181968350Seric } 182068350Seric /* check to see if this map actually accessable */ 182168350Seric if (access(map->map_file, R_OK) <0) 182268350Seric return FALSE; 182368350Seric 182468350Seric /* check to see if this map actually exist */ 182568350Seric if (stat(map->map_file, &sbuf) <0) 182668350Seric { 182768350Seric if (tTd(38, 2)) 182868350Seric printf("text_map_open(%s): can not stat %s\n", 182968350Seric map->map_file, map->map_file); 183068350Seric return FALSE; 183168350Seric } 183268350Seric 183368350Seric if (!S_ISREG(sbuf.st_mode)) 183468350Seric { 183568350Seric if (tTd(38, 2)) 183668350Seric printf("text_map_open(%s): %s is not a file\n", 183768350Seric map->map_file, map->map_file); 183868350Seric return FALSE; 183968350Seric } 184068350Seric 184168350Seric if (map->map_keycolnm == NULL) 184268350Seric map->map_keycolno = 0; 184368350Seric else 184468350Seric { 184568350Seric if (!isdigit(*map->map_keycolnm)) 184668350Seric { 184768350Seric if (tTd(38, 2)) 184868350Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 184968350Seric map->map_file, map->map_keycolnm); 185068350Seric return FALSE; 185168350Seric } 185268350Seric map->map_keycolno = atoi(map->map_keycolnm); 185368350Seric } 185468350Seric 185568350Seric if (map->map_valcolnm == NULL) 185668350Seric map->map_valcolno = 0; 185768350Seric else 185868350Seric { 185968350Seric if (!isdigit(*map->map_valcolnm)) 186068350Seric { 186168350Seric if (tTd(38, 2)) 186268350Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 186368350Seric map->map_file, map->map_valcolnm); 186468350Seric return FALSE; 186568350Seric } 186668350Seric map->map_valcolno = atoi(map->map_valcolnm); 186768350Seric } 186868350Seric 186968350Seric if (tTd(38, 2)) 187068350Seric { 187168520Seric printf("text_map_open(%s): delimiter = ", 187268520Seric map->map_file); 187368520Seric if (map->map_coldelim == '\0') 187468520Seric printf("(white space)\n"); 187568520Seric else 187668520Seric printf("%c\n", map->map_coldelim); 187768350Seric } 187868350Seric 187968350Seric return TRUE; 188068350Seric } 188168350Seric 188268350Seric 188368350Seric /* 188468350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 188568350Seric */ 188668350Seric 188768350Seric char * 188868350Seric text_map_lookup(map, name, av, statp) 188968350Seric MAP *map; 189068350Seric char *name; 189168350Seric char **av; 189268350Seric int *statp; 189368350Seric { 189468350Seric char *vp; 189568350Seric auto int vsize; 189668350Seric int buflen; 189768350Seric char search_key[MAXNAME + 1]; 189868350Seric char linebuf[MAXLINE]; 189968350Seric FILE *f; 190068528Seric char buf[MAXNAME + 1]; 190168350Seric char delim; 190268350Seric int key_idx; 190368350Seric bool found_it; 190468350Seric extern char *get_column(); 190568350Seric 190668350Seric 190768350Seric found_it = FALSE; 190868350Seric if (tTd(38, 20)) 190968350Seric printf("text_map_lookup(%s)\n", name); 191068350Seric 191168350Seric buflen = strlen(name); 191268350Seric if (buflen > sizeof search_key - 1) 191368350Seric buflen = sizeof search_key - 1; 191468350Seric bcopy(name, search_key, buflen + 1); 191568350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 191668350Seric makelower(search_key); 191768350Seric 191868350Seric f = fopen(map->map_file, "r"); 191968350Seric if (f == NULL) 192068350Seric { 192168350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 192268350Seric *statp = EX_UNAVAILABLE; 192368350Seric return NULL; 192468350Seric } 192568350Seric key_idx = map->map_keycolno; 192668350Seric delim = map->map_coldelim; 192768350Seric while (fgets(linebuf, MAXLINE, f)) 192868350Seric { 192968350Seric char *lf; 193068350Seric if (linebuf[0] == '#') 193168350Seric continue; /* skip comment line */ 193268350Seric if (lf = strchr(linebuf, '\n')) 193368350Seric *lf = '\0'; 193468350Seric if (!strcasecmp(search_key, 193568350Seric get_column(linebuf, key_idx, delim, buf))) 193668350Seric { 193768350Seric found_it = TRUE; 193868350Seric break; 193968350Seric } 194068350Seric } 194168350Seric fclose(f); 194268350Seric if (!found_it) 194368350Seric { 194468350Seric #ifdef MAP_EXIT_STAT 194568350Seric *statp = EX_NOTFOUND; 194668350Seric #endif 194768350Seric return(NULL); 194868350Seric } 194968350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 195068350Seric vsize = strlen(vp); 195168350Seric #ifdef MAP_EXIT_STAT 195268350Seric *statp = EX_OK; 195368350Seric #endif 195468350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 195568350Seric return map_rewrite(map, name, strlen(name), NULL); 195668350Seric else 195768350Seric return map_rewrite(map, vp, vsize, av); 195868350Seric } 1959*69401Seric 1960*69401Seric 1961*69401Seric /* 1962*69401Seric ** TEXT_GETCANONNAME -- look up canonical name in hosts file 1963*69401Seric */ 1964*69401Seric 1965*69401Seric bool 1966*69401Seric text_getcanonname(name, hbsize, statp) 1967*69401Seric char *name; 1968*69401Seric int hbsize; 1969*69401Seric int *statp; 1970*69401Seric { 1971*69401Seric int buflen; 1972*69401Seric char delim; 1973*69401Seric int key_idx; 1974*69401Seric char *cname; 1975*69401Seric bool found; 1976*69401Seric char *domain; 1977*69401Seric FILE *f; 1978*69401Seric char linebuf[MAXLINE]; 1979*69401Seric char cbuf[MAXNAME + 1]; 1980*69401Seric char buf[MAXNAME + 1]; 1981*69401Seric extern char *get_column(); 1982*69401Seric 1983*69401Seric shorten_hostname(name); 1984*69401Seric 1985*69401Seric /* we only accept single token search key */ 1986*69401Seric if (strchr(name, '.') != NULL) 1987*69401Seric { 1988*69401Seric *statp = EX_NOHOST; 1989*69401Seric return FALSE; 1990*69401Seric } 1991*69401Seric 1992*69401Seric found = FALSE; 1993*69401Seric 1994*69401Seric f = fopen(HostsFile, "r"); 1995*69401Seric if (f == NULL) 1996*69401Seric { 1997*69401Seric #ifdef MAP_EXIT_STAT 1998*69401Seric *statp = EX_UNAVAILABLE; 1999*69401Seric #endif 2000*69401Seric return FALSE; 2001*69401Seric } 2002*69401Seric delim = '\t'; 2003*69401Seric while (!found && fgets(linebuf, MAXLINE, f) != NULL) 2004*69401Seric { 2005*69401Seric char *p; 2006*69401Seric 2007*69401Seric if (linebuf[0] == '#') 2008*69401Seric continue; 2009*69401Seric if ((p = strchr(linebuf, '\n')) != NULL) 2010*69401Seric *p = '\0'; 2011*69401Seric cname = get_column(linebuf, 1, delim, cbuf); 2012*69401Seric if (cname != NULL && strcasecmp(name, cname) == 0) 2013*69401Seric { 2014*69401Seric found = TRUE; 2015*69401Seric break; 2016*69401Seric } 2017*69401Seric 2018*69401Seric key_idx = 2; 2019*69401Seric while ((p = get_column(linebuf, key_idx, delim, buf)) != NULL) 2020*69401Seric { 2021*69401Seric if (strcasecmp(name, p) == 0) 2022*69401Seric { 2023*69401Seric found = TRUE; 2024*69401Seric break; 2025*69401Seric } 2026*69401Seric key_idx++; 2027*69401Seric } 2028*69401Seric } 2029*69401Seric fclose(f); 2030*69401Seric if (!found) 2031*69401Seric { 2032*69401Seric *statp = EX_NOHOST; 2033*69401Seric return FALSE; 2034*69401Seric } 2035*69401Seric 2036*69401Seric if (hbsize >= strlen(cname)) 2037*69401Seric { 2038*69401Seric strcpy(name, cname); 2039*69401Seric *statp = EX_OK; 2040*69401Seric return TRUE; 2041*69401Seric } 2042*69401Seric *statp = EX_UNAVAILABLE; 2043*69401Seric return FALSE; 2044*69401Seric } 204568350Seric /* 204660089Seric ** STAB (Symbol Table) Modules 204760089Seric */ 204860089Seric 204960089Seric 205060089Seric /* 205160207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 205260089Seric */ 205360089Seric 205460089Seric char * 205561707Seric stab_map_lookup(map, name, av, pstat) 205660089Seric register MAP *map; 205760089Seric char *name; 205861707Seric char **av; 205961707Seric int *pstat; 206060089Seric { 206160089Seric register STAB *s; 206260089Seric 206360537Seric if (tTd(38, 20)) 206468350Seric printf("stab_lookup(%s, %s)\n", 206568350Seric map->map_mname, name); 206660089Seric 206760089Seric s = stab(name, ST_ALIAS, ST_FIND); 206860089Seric if (s != NULL) 206960089Seric return (s->s_alias); 207060089Seric return (NULL); 207160089Seric } 207260089Seric 207360089Seric 207460089Seric /* 207560207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 207660089Seric */ 207760089Seric 207860089Seric void 207960089Seric stab_map_store(map, lhs, rhs) 208060089Seric register MAP *map; 208160089Seric char *lhs; 208260089Seric char *rhs; 208360089Seric { 208460089Seric register STAB *s; 208560089Seric 208660089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 208760089Seric s->s_alias = newstr(rhs); 208860089Seric } 208960089Seric 209060089Seric 209160089Seric /* 209260207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 209360207Seric ** 209460207Seric ** This is a wierd case -- it is only intended as a fallback for 209560207Seric ** aliases. For this reason, opens for write (only during a 209660207Seric ** "newaliases") always fails, and opens for read open the 209760207Seric ** actual underlying text file instead of the database. 209860089Seric */ 209960089Seric 210060089Seric bool 210160089Seric stab_map_open(map, mode) 210260089Seric register MAP *map; 210360089Seric int mode; 210460089Seric { 210563835Seric FILE *af; 210664284Seric struct stat st; 210763835Seric 210860537Seric if (tTd(38, 2)) 210968350Seric printf("stab_map_open(%s, %s)\n", 211068350Seric map->map_mname, map->map_file); 211160089Seric 211260089Seric if (mode != O_RDONLY) 211360207Seric { 211460207Seric errno = ENODEV; 211560089Seric return FALSE; 211660207Seric } 211760089Seric 211863835Seric af = fopen(map->map_file, "r"); 211963835Seric if (af == NULL) 212063835Seric return FALSE; 212168350Seric readaliases(map, af, FALSE, FALSE); 212264284Seric 212364284Seric if (fstat(fileno(af), &st) >= 0) 212464284Seric map->map_mtime = st.st_mtime; 212563835Seric fclose(af); 212663835Seric 212760089Seric return TRUE; 212860089Seric } 212960089Seric /* 213060089Seric ** Implicit Modules 213156822Seric ** 213260089Seric ** Tries several types. For back compatibility of aliases. 213356822Seric */ 213456822Seric 213560089Seric 213660089Seric /* 213760207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 213860089Seric */ 213960089Seric 214060089Seric char * 214160089Seric impl_map_lookup(map, name, av, pstat) 214260089Seric MAP *map; 214360089Seric char *name; 214456822Seric char **av; 214560089Seric int *pstat; 214656822Seric { 214760537Seric if (tTd(38, 20)) 214868350Seric printf("impl_map_lookup(%s, %s)\n", 214968350Seric map->map_mname, name); 215056822Seric 215160089Seric #ifdef NEWDB 215260207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 215360089Seric return db_map_lookup(map, name, av, pstat); 215460089Seric #endif 215560089Seric #ifdef NDBM 215660207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 215760089Seric return ndbm_map_lookup(map, name, av, pstat); 215860089Seric #endif 215960089Seric return stab_map_lookup(map, name, av, pstat); 216060089Seric } 216160089Seric 216260089Seric /* 216360207Seric ** IMPL_MAP_STORE -- store in open databases 216460089Seric */ 216560089Seric 216660089Seric void 216760089Seric impl_map_store(map, lhs, rhs) 216860089Seric MAP *map; 216960089Seric char *lhs; 217060089Seric char *rhs; 217160089Seric { 217260089Seric #ifdef NEWDB 217360207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 217460089Seric db_map_store(map, lhs, rhs); 217560089Seric #endif 217660089Seric #ifdef NDBM 217760207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 217860089Seric ndbm_map_store(map, lhs, rhs); 217960089Seric #endif 218060089Seric stab_map_store(map, lhs, rhs); 218160089Seric } 218260089Seric 218360089Seric /* 218460089Seric ** IMPL_MAP_OPEN -- implicit database open 218560089Seric */ 218660089Seric 218760089Seric bool 218860089Seric impl_map_open(map, mode) 218960089Seric MAP *map; 219060089Seric int mode; 219160089Seric { 219260089Seric struct stat stb; 219360089Seric 219460537Seric if (tTd(38, 2)) 219568350Seric printf("impl_map_open(%s, %s, %d)\n", 219668350Seric map->map_mname, map->map_file, mode); 219760089Seric 219860089Seric if (stat(map->map_file, &stb) < 0) 219956822Seric { 220060089Seric /* no alias file at all */ 220164718Seric if (tTd(38, 3)) 220264718Seric printf("no map file\n"); 220360089Seric return FALSE; 220456822Seric } 220556822Seric 220660089Seric #ifdef NEWDB 220760207Seric map->map_mflags |= MF_IMPL_HASH; 220860089Seric if (hash_map_open(map, mode)) 220956822Seric { 221064250Seric #if defined(NDBM) && defined(NIS) 221160561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 221260207Seric #endif 221360207Seric return TRUE; 221460089Seric } 221560207Seric else 221660207Seric map->map_mflags &= ~MF_IMPL_HASH; 221760089Seric #endif 221860089Seric #ifdef NDBM 221960207Seric map->map_mflags |= MF_IMPL_NDBM; 222060089Seric if (ndbm_map_open(map, mode)) 222160089Seric { 222260089Seric return TRUE; 222360089Seric } 222460207Seric else 222560207Seric map->map_mflags &= ~MF_IMPL_NDBM; 222660089Seric #endif 222756822Seric 222864650Seric #if defined(NEWDB) || defined(NDBM) 222960089Seric if (Verbose) 223060089Seric message("WARNING: cannot open alias database %s", map->map_file); 223164964Seric #else 223264964Seric if (mode != O_RDONLY) 223364964Seric usrerr("Cannot rebuild aliases: no database format defined"); 223460207Seric #endif 223560089Seric 223660207Seric return stab_map_open(map, mode); 223756822Seric } 223860089Seric 223960207Seric 224060089Seric /* 224160207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 224260089Seric */ 224360089Seric 224460089Seric void 224560207Seric impl_map_close(map) 224660089Seric MAP *map; 224760089Seric { 224868350Seric if (tTd(38, 20)) 224968350Seric printf("impl_map_close(%s, %s, %x)\n", 225068350Seric map->map_mname, map->map_file, map->map_mflags); 225160089Seric #ifdef NEWDB 225260207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 225360089Seric { 225460207Seric db_map_close(map); 225560207Seric map->map_mflags &= ~MF_IMPL_HASH; 225660089Seric } 225760089Seric #endif 225860089Seric 225960089Seric #ifdef NDBM 226060207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 226160089Seric { 226260207Seric ndbm_map_close(map); 226360207Seric map->map_mflags &= ~MF_IMPL_NDBM; 226460089Seric } 226560089Seric #endif 226660089Seric } 226760207Seric /* 226868350Seric ** User map class. 226968350Seric ** 227068350Seric ** Provides access to the system password file. 227168350Seric */ 227268350Seric 227368350Seric /* 227468350Seric ** USER_MAP_OPEN -- open user map 227568350Seric ** 227668350Seric ** Really just binds field names to field numbers. 227768350Seric */ 227868350Seric 227968350Seric bool 228068350Seric user_map_open(map, mode) 228168350Seric MAP *map; 228268350Seric int mode; 228368350Seric { 228468350Seric if (tTd(38, 2)) 228568350Seric printf("user_map_open(%s)\n", map->map_mname); 228668350Seric 228768350Seric if (mode != O_RDONLY) 228868350Seric { 228968350Seric /* issue a pseudo-error message */ 229068350Seric #ifdef ENOSYS 229168350Seric errno = ENOSYS; 229268350Seric #else 229368350Seric # ifdef EFTYPE 229468350Seric errno = EFTYPE; 229568350Seric # else 229668350Seric errno = ENXIO; 229768350Seric # endif 229868350Seric #endif 229968350Seric return FALSE; 230068350Seric } 230168350Seric if (map->map_valcolnm == NULL) 230268350Seric /* nothing */ ; 230368350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 230468350Seric map->map_valcolno = 1; 230568350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 230668350Seric map->map_valcolno = 2; 230768350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 230868350Seric map->map_valcolno = 3; 230968350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 231068350Seric map->map_valcolno = 4; 231168350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 231268350Seric map->map_valcolno = 5; 231368350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 231468350Seric map->map_valcolno = 6; 231568350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 231668350Seric map->map_valcolno = 7; 231768350Seric else 231868350Seric { 231968350Seric syserr("User map %s: unknown column name %s", 232068350Seric map->map_mname, map->map_valcolnm); 232168350Seric return FALSE; 232268350Seric } 232368350Seric return TRUE; 232468350Seric } 232568350Seric 232668350Seric 232768350Seric /* 232868350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 232968350Seric */ 233068350Seric 233168350Seric char * 233268350Seric user_map_lookup(map, key, av, statp) 233368350Seric MAP *map; 233468350Seric char *key; 233568350Seric char **av; 233668350Seric int *statp; 233768350Seric { 233868350Seric struct passwd *pw; 233968350Seric 234068350Seric if (tTd(38, 20)) 234168350Seric printf("user_map_lookup(%s, %s)\n", 234268350Seric map->map_mname, key); 234368350Seric 234468693Seric pw = sm_getpwnam(key); 234568350Seric if (pw == NULL) 234668350Seric return NULL; 234768350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 234868350Seric return map_rewrite(map, key, strlen(key), NULL); 234968350Seric else 235068350Seric { 235168433Seric char *rwval = NULL; 235268350Seric char buf[30]; 235368350Seric 235468350Seric switch (map->map_valcolno) 235568350Seric { 235668350Seric case 0: 235768350Seric case 1: 235868350Seric rwval = pw->pw_name; 235968350Seric break; 236068350Seric 236168350Seric case 2: 236268350Seric rwval = pw->pw_passwd; 236368350Seric break; 236468350Seric 236568350Seric case 3: 236668350Seric sprintf(buf, "%d", pw->pw_uid); 236768350Seric rwval = buf; 236868350Seric break; 236968350Seric 237068350Seric case 4: 237168350Seric sprintf(buf, "%d", pw->pw_gid); 237268350Seric rwval = buf; 237368350Seric break; 237468350Seric 237568350Seric case 5: 237668350Seric rwval = pw->pw_gecos; 237768350Seric break; 237868350Seric 237968350Seric case 6: 238068350Seric rwval = pw->pw_dir; 238168350Seric break; 238268350Seric 238368350Seric case 7: 238468350Seric rwval = pw->pw_shell; 238568350Seric break; 238668350Seric } 238768350Seric return map_rewrite(map, rwval, strlen(rwval), av); 238868350Seric } 238968350Seric } 239068350Seric /* 239168350Seric ** BESTMX -- find the best MX for a name 239268350Seric ** 239368350Seric ** This is really a hack, but I don't see any obvious way 239468350Seric ** to generalize it at the moment. 239568350Seric */ 239668350Seric 239768350Seric #if NAMED_BIND 239868350Seric 239968350Seric char * 240068350Seric bestmx_map_lookup(map, name, av, statp) 240168350Seric MAP *map; 240268350Seric char *name; 240368350Seric char **av; 240468350Seric int *statp; 240568350Seric { 240668350Seric int nmx; 240768350Seric auto int rcode; 240868350Seric char *mxhosts[MAXMXHOSTS + 1]; 240968350Seric 241068350Seric nmx = getmxrr(name, mxhosts, FALSE, &rcode); 241168350Seric if (nmx <= 0) 241268350Seric return NULL; 241368350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 241468350Seric return map_rewrite(map, name, strlen(name), NULL); 241568350Seric else 241668350Seric return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 241768350Seric } 241868350Seric 241968350Seric #endif 242068350Seric /* 242168350Seric ** Sequenced map type. 242268350Seric ** 242368350Seric ** Tries each map in order until something matches, much like 242468350Seric ** implicit. Stores go to the first map in the list that can 242568350Seric ** support storing. 242668350Seric ** 242768350Seric ** This is slightly unusual in that there are two interfaces. 242868350Seric ** The "sequence" interface lets you stack maps arbitrarily. 242968350Seric ** The "switch" interface builds a sequence map by looking 243068350Seric ** at a system-dependent configuration file such as 243168350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 243268350Seric ** 243368350Seric ** We don't need an explicit open, since all maps are 243468350Seric ** opened during startup, including underlying maps. 243568350Seric */ 243668350Seric 243768350Seric /* 243868350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 243968350Seric */ 244068350Seric 244168350Seric bool 244268350Seric seq_map_parse(map, ap) 244368350Seric MAP *map; 244468350Seric char *ap; 244568350Seric { 244668350Seric int maxmap; 244768350Seric 244868350Seric if (tTd(38, 2)) 244968350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 245068350Seric maxmap = 0; 245168350Seric while (*ap != '\0') 245268350Seric { 245368350Seric register char *p; 245468350Seric STAB *s; 245568350Seric 245668350Seric /* find beginning of map name */ 245768350Seric while (isascii(*ap) && isspace(*ap)) 245868350Seric ap++; 245968350Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 246068350Seric continue; 246168350Seric if (*p != '\0') 246268350Seric *p++ = '\0'; 246368350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 246468350Seric p++; 246568350Seric if (*ap == '\0') 246668350Seric { 246768350Seric ap = p; 246868350Seric continue; 246968350Seric } 247068350Seric s = stab(ap, ST_MAP, ST_FIND); 247168350Seric if (s == NULL) 247268350Seric { 247368350Seric syserr("Sequence map %s: unknown member map %s", 247468350Seric map->map_mname, ap); 247568350Seric } 247668350Seric else if (maxmap == MAXMAPSTACK) 247768350Seric { 247868350Seric syserr("Sequence map %s: too many member maps (%d max)", 247968350Seric map->map_mname, MAXMAPSTACK); 248068350Seric maxmap++; 248168350Seric } 248268350Seric else if (maxmap < MAXMAPSTACK) 248368350Seric { 248468350Seric map->map_stack[maxmap++] = &s->s_map; 248568350Seric } 248668350Seric ap = p; 248768350Seric } 248868350Seric return TRUE; 248968350Seric } 249068350Seric 249168350Seric 249268350Seric /* 249368350Seric ** SWITCH_MAP_OPEN -- open a switched map 249468350Seric ** 249568350Seric ** This looks at the system-dependent configuration and builds 249668350Seric ** a sequence map that does the same thing. 249768350Seric ** 249868350Seric ** Every system must define a switch_map_find routine in conf.c 249968350Seric ** that will return the list of service types associated with a 250068350Seric ** given service class. 250168350Seric */ 250268350Seric 250368350Seric bool 250468350Seric switch_map_open(map, mode) 250568350Seric MAP *map; 250668350Seric int mode; 250768350Seric { 250868350Seric int mapno; 250968350Seric int nmaps; 251068350Seric char *maptype[MAXMAPSTACK]; 251168350Seric 251268350Seric if (tTd(38, 2)) 251368350Seric printf("switch_map_open(%s, %s, %d)\n", 251468350Seric map->map_mname, map->map_file, mode); 251568350Seric 251668350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 251768350Seric if (tTd(38, 19)) 251868350Seric { 251968350Seric printf("\tswitch_map_find => %d\n", nmaps); 252068350Seric for (mapno = 0; mapno < nmaps; mapno++) 252168350Seric printf("\t\t%s\n", maptype[mapno]); 252268350Seric } 252368350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 252468350Seric return FALSE; 252568350Seric 252668350Seric for (mapno = 0; mapno < nmaps; mapno++) 252768350Seric { 252868350Seric register STAB *s; 252968350Seric char nbuf[MAXNAME + 1]; 253068350Seric 253168350Seric if (maptype[mapno] == NULL) 253268350Seric continue; 253368350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 253468350Seric s = stab(nbuf, ST_MAP, ST_FIND); 253568350Seric if (s == NULL) 253668350Seric { 253768350Seric syserr("Switch map %s: unknown member map %s", 253868350Seric map->map_mname, nbuf); 253968350Seric } 254068350Seric else 254168350Seric { 254268350Seric map->map_stack[mapno] = &s->s_map; 254368350Seric if (tTd(38, 4)) 254468350Seric printf("\tmap_stack[%d] = %s:%s\n", 254568350Seric mapno, s->s_map.map_class->map_cname, 254668350Seric nbuf); 254768350Seric } 254868350Seric } 254968350Seric return TRUE; 255068350Seric } 255168350Seric 255268350Seric 255368350Seric /* 255468350Seric ** SEQ_MAP_CLOSE -- close all underlying maps 255568350Seric */ 255668350Seric 255768350Seric seq_map_close(map) 255868350Seric MAP *map; 255968350Seric { 256068350Seric int mapno; 256168350Seric 256268350Seric if (tTd(38, 20)) 256368350Seric printf("seq_map_close(%s)\n", map->map_mname); 256468350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 256568350Seric { 256668350Seric MAP *mm = map->map_stack[mapno]; 256768350Seric 256868350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 256968350Seric continue; 257068350Seric mm->map_class->map_close(mm); 257168798Seric mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 257268350Seric } 257368350Seric } 257468350Seric 257568350Seric 257668350Seric /* 257768350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 257868350Seric */ 257968350Seric 258068350Seric char * 258168350Seric seq_map_lookup(map, key, args, pstat) 258268350Seric MAP *map; 258368350Seric char *key; 258468350Seric char **args; 258568350Seric int *pstat; 258668350Seric { 258768350Seric int mapno; 258868350Seric int mapbit = 0x01; 258968350Seric 259068350Seric if (tTd(38, 20)) 259168350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 259268350Seric 259368350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 259468350Seric { 259568350Seric MAP *mm = map->map_stack[mapno]; 259668350Seric int stat = 0; 259768350Seric char *rv; 259868350Seric 259968350Seric if (mm == NULL) 260068350Seric continue; 260168350Seric if (!bitset(MF_OPEN, mm->map_mflags)) 260268350Seric { 260368350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 260468350Seric { 260568350Seric *pstat = EX_UNAVAILABLE; 260668350Seric return NULL; 260768350Seric } 260868350Seric continue; 260968350Seric } 261068350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 261168350Seric if (rv != NULL) 261268350Seric return rv; 261368350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 261468350Seric return NULL; 261568350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 261668350Seric { 261768350Seric *pstat = stat; 261868350Seric return NULL; 261968350Seric } 262068350Seric } 262168350Seric return NULL; 262268350Seric } 262368350Seric 262468350Seric 262568350Seric /* 262668350Seric ** SEQ_MAP_STORE -- sequenced map store 262768350Seric */ 262868350Seric 262968350Seric void 263068350Seric seq_map_store(map, key, val) 263168350Seric MAP *map; 263268350Seric char *key; 263368350Seric char *val; 263468350Seric { 263568350Seric int mapno; 263668350Seric 263768350Seric if (tTd(38, 12)) 263868350Seric printf("seq_map_store(%s, %s, %s)\n", 263968350Seric map->map_mname, key, val); 264068350Seric 264168350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 264268350Seric { 264368350Seric MAP *mm = map->map_stack[mapno]; 264468350Seric 264568350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 264668350Seric continue; 264768350Seric 264868350Seric mm->map_class->map_store(mm, key, val); 264968350Seric return; 265068350Seric } 265168350Seric syserr("seq_map_store(%s, %s, %s): no writable map", 265268350Seric map->map_mname, key, val); 265368350Seric } 265468350Seric /* 2655*69401Seric ** GETCANONNAME -- look up name using service switch 2656*69401Seric ** 2657*69401Seric ** Parameters: 2658*69401Seric ** host -- the host name to look up. 2659*69401Seric ** hbsize -- the size of the host buffer. 2660*69401Seric ** trymx -- if set, try MX records. 2661*69401Seric ** 2662*69401Seric ** Returns: 2663*69401Seric ** TRUE -- if the host was found. 2664*69401Seric ** FALSE -- otherwise. 2665*69401Seric */ 2666*69401Seric 2667*69401Seric bool 2668*69401Seric getcanonname(host, hbsize, trymx) 2669*69401Seric char *host; 2670*69401Seric int hbsize; 2671*69401Seric bool trymx; 2672*69401Seric { 2673*69401Seric int nmaps; 2674*69401Seric int mapno; 2675*69401Seric bool found = FALSE; 2676*69401Seric auto int stat; 2677*69401Seric char *maptype[MAXMAPSTACK]; 2678*69401Seric short mapreturn[MAXMAPACTIONS]; 2679*69401Seric extern int h_errno; 2680*69401Seric 2681*69401Seric nmaps = switch_map_find("hosts", maptype, mapreturn); 2682*69401Seric for (mapno = 0; mapno < nmaps; mapno++) 2683*69401Seric { 2684*69401Seric int i; 2685*69401Seric 2686*69401Seric if (tTd(38, 20)) 2687*69401Seric printf("getcanonname(%s), trying %s\n", 2688*69401Seric host, maptype[mapno]); 2689*69401Seric if (strcmp("files", maptype[mapno]) == 0) 2690*69401Seric found = text_getcanonname(host, hbsize, &stat); 2691*69401Seric #ifdef NIS 2692*69401Seric else if (strcmp("nis", maptype[mapno]) == 0) 2693*69401Seric found = nis_getcanonname(host, hbsize, &stat); 2694*69401Seric #endif 2695*69401Seric #ifdef NISPLUS 2696*69401Seric else if (strcmp("nisplus", maptype[mapno]) == 0) 2697*69401Seric found = nisplus_getcanonname(host, hbsize, &stat); 2698*69401Seric #endif 2699*69401Seric #if NAMED_BIND 2700*69401Seric else if (strcmp("dns", maptype[mapno]) == 0) 2701*69401Seric found = dns_getcanonname(host, hbsize, trymx, &stat); 2702*69401Seric #endif 2703*69401Seric else 2704*69401Seric { 2705*69401Seric found = FALSE; 2706*69401Seric stat = EX_UNAVAILABLE; 2707*69401Seric } 2708*69401Seric if (found) 2709*69401Seric break; 2710*69401Seric 2711*69401Seric /* see if we should continue */ 2712*69401Seric if (stat == EX_TEMPFAIL) 2713*69401Seric i = MA_TRYAGAIN; 2714*69401Seric else if (stat == EX_NOHOST) 2715*69401Seric i = MA_NOTFOUND; 2716*69401Seric else 2717*69401Seric i = MA_UNAVAIL; 2718*69401Seric if (bitset(1 << mapno, mapreturn[i])) 2719*69401Seric break; 2720*69401Seric } 2721*69401Seric 2722*69401Seric if (found) 2723*69401Seric { 2724*69401Seric char *d; 2725*69401Seric 2726*69401Seric if (tTd(38, 20)) 2727*69401Seric printf("getcanonname(%s), found\n", host); 2728*69401Seric 2729*69401Seric /* 2730*69401Seric ** If returned name is still single token, compensate 2731*69401Seric ** by tagging on $m. This is because some sites set 2732*69401Seric ** up their DNS or NIS databases wrong. 2733*69401Seric */ 2734*69401Seric 2735*69401Seric if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 2736*69401Seric { 2737*69401Seric d = macvalue('m', CurEnv); 2738*69401Seric if (d != NULL && 2739*69401Seric hbsize > (int) (strlen(host) + strlen(d) + 1)) 2740*69401Seric { 2741*69401Seric if (host[strlen(host) - 1] != '.') 2742*69401Seric strcat(host, "."); 2743*69401Seric strcat(host, d); 2744*69401Seric } 2745*69401Seric else 2746*69401Seric { 2747*69401Seric return FALSE; 2748*69401Seric } 2749*69401Seric } 2750*69401Seric return TRUE; 2751*69401Seric } 2752*69401Seric 2753*69401Seric if (tTd(38, 20)) 2754*69401Seric printf("getcanonname(%s), failed, stat=%d\n", host, stat); 2755*69401Seric 2756*69401Seric #if NAMED_BIND 2757*69401Seric if (stat == EX_NOHOST) 2758*69401Seric h_errno = HOST_NOT_FOUND; 2759*69401Seric else 2760*69401Seric h_errno = TRY_AGAIN; 2761*69401Seric #endif 2762*69401Seric 2763*69401Seric return FALSE; 2764*69401Seric } 2765*69401Seric /* 276660207Seric ** NULL stubs 276760089Seric */ 276860089Seric 276960207Seric bool 277060207Seric null_map_open(map, mode) 277160089Seric MAP *map; 277260207Seric int mode; 277360089Seric { 277460207Seric return TRUE; 277560089Seric } 277660089Seric 277760207Seric void 277860207Seric null_map_close(map) 277960207Seric MAP *map; 278060089Seric { 278160207Seric return; 278260207Seric } 278360089Seric 278460207Seric void 278560207Seric null_map_store(map, key, val) 278660207Seric MAP *map; 278760207Seric char *key; 278860207Seric char *val; 278960089Seric { 279060207Seric return; 279160089Seric } 279268350Seric 279368350Seric 279468350Seric /* 279568350Seric ** BOGUS stubs 279668350Seric */ 279768350Seric 279868350Seric char * 279968350Seric bogus_map_lookup(map, key, args, pstat) 280068350Seric MAP *map; 280168350Seric char *key; 280268350Seric char **args; 280368350Seric int *pstat; 280468350Seric { 280568350Seric *pstat = EX_TEMPFAIL; 280668350Seric return NULL; 280768350Seric } 280868350Seric 280968350Seric MAPCLASS BogusMapClass = 281068350Seric { 281168350Seric "bogus-map", NULL, 0, 281268350Seric NULL, bogus_map_lookup, null_map_store, 281368350Seric null_map_open, null_map_close, 281468350Seric }; 2815