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*69703Seric static char sccsid[] = "@(#)map.c 8.68 (Berkeley) 05/26/95"; 1156822Seric #endif /* not lint */ 1256822Seric 1356822Seric #include "sendmail.h" 1456822Seric 1560089Seric #ifdef NDBM 1668509Seric # include <ndbm.h> 1756822Seric #endif 1860089Seric #ifdef NEWDB 1968509Seric # include <db.h> 2056822Seric #endif 2160089Seric #ifdef NIS 2269651Seric struct dom_binding; /* forward reference needed on IRIX */ 2368509Seric # include <rpcsvc/ypclnt.h> 2457208Seric #endif 2556822Seric 2656822Seric /* 2760089Seric ** MAP.C -- implementations for various map classes. 2856822Seric ** 2960089Seric ** Each map class implements a series of functions: 3060089Seric ** 3160089Seric ** bool map_parse(MAP *map, char *args) 3260089Seric ** Parse the arguments from the config file. Return TRUE 3360089Seric ** if they were ok, FALSE otherwise. Fill in map with the 3460089Seric ** values. 3560089Seric ** 3660222Seric ** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 3760222Seric ** Look up the key in the given map. If found, do any 3860222Seric ** rewriting the map wants (including "args" if desired) 3960089Seric ** and return the value. Set *pstat to the appropriate status 4060222Seric ** on error and return NULL. Args will be NULL if called 4160222Seric ** from the alias routines, although this should probably 4260222Seric ** not be relied upon. It is suggested you call map_rewrite 4360222Seric ** to return the results -- it takes care of null termination 4460222Seric ** and uses a dynamically expanded buffer as needed. 4560089Seric ** 4660089Seric ** void map_store(MAP *map, char *key, char *value) 4760089Seric ** Store the key:value pair in the map. 4860089Seric ** 4960089Seric ** bool map_open(MAP *map, int mode) 5060222Seric ** Open the map for the indicated mode. Mode should 5160222Seric ** be either O_RDONLY or O_RDWR. Return TRUE if it 5260222Seric ** was opened successfully, FALSE otherwise. If the open 5360222Seric ** failed an the MF_OPTIONAL flag is not set, it should 5460222Seric ** also print an error. If the MF_ALIAS bit is set 5560222Seric ** and this map class understands the @:@ convention, it 5660222Seric ** should call aliaswait() before returning. 5760089Seric ** 5860089Seric ** void map_close(MAP *map) 5960089Seric ** Close the map. 6069401Seric ** 6169401Seric ** This file also includes the implementation for getcanonname. 6269401Seric ** It is currently implemented in a pretty ad-hoc manner; it ought 6369401Seric ** to be more properly integrated into the map structure. 6460089Seric */ 6560089Seric 6660089Seric #define DBMMODE 0644 6764718Seric 6864718Seric extern bool aliaswait __P((MAP *, char *, int)); 6960089Seric /* 7060089Seric ** MAP_PARSEARGS -- parse config line arguments for database lookup 7160089Seric ** 7260089Seric ** This is a generic version of the map_parse method. 7360089Seric ** 7456822Seric ** Parameters: 7560089Seric ** map -- the map being initialized. 7660089Seric ** ap -- a pointer to the args on the config line. 7756822Seric ** 7856822Seric ** Returns: 7960089Seric ** TRUE -- if everything parsed OK. 8056822Seric ** FALSE -- otherwise. 8156822Seric ** 8256822Seric ** Side Effects: 8360089Seric ** null terminates the filename; stores it in map 8456822Seric */ 8556822Seric 8656822Seric bool 8760089Seric map_parseargs(map, ap) 8856822Seric MAP *map; 8960089Seric char *ap; 9056822Seric { 9160089Seric register char *p = ap; 9256822Seric 9363753Seric map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; 9460089Seric for (;;) 9560089Seric { 9660089Seric while (isascii(*p) && isspace(*p)) 9760089Seric p++; 9860089Seric if (*p != '-') 9960089Seric break; 10060089Seric switch (*++p) 10160089Seric { 10260089Seric case 'N': 10360207Seric map->map_mflags |= MF_INCLNULL; 10463753Seric map->map_mflags &= ~MF_TRY0NULL; 10560089Seric break; 10660089Seric 10763753Seric case 'O': 10863753Seric map->map_mflags &= ~MF_TRY1NULL; 10963753Seric break; 11063753Seric 11160089Seric case 'o': 11260207Seric map->map_mflags |= MF_OPTIONAL; 11360089Seric break; 11460089Seric 11560089Seric case 'f': 11660207Seric map->map_mflags |= MF_NOFOLDCASE; 11760089Seric break; 11860089Seric 11960089Seric case 'm': 12060207Seric map->map_mflags |= MF_MATCHONLY; 12160089Seric break; 12260089Seric 12368497Seric case 'A': 12468497Seric map->map_mflags |= MF_APPEND; 12568497Seric break; 12668497Seric 127*69703Seric case 'q': 128*69703Seric map->map_mflags |= MF_KEEPQUOTES; 129*69703Seric break; 130*69703Seric 13160089Seric case 'a': 13260089Seric map->map_app = ++p; 13360089Seric break; 13468350Seric 13568350Seric case 'k': 13668350Seric while (isascii(*++p) && isspace(*p)) 13768350Seric continue; 13868350Seric map->map_keycolnm = p; 13968350Seric break; 14068350Seric 14168350Seric case 'v': 14268350Seric while (isascii(*++p) && isspace(*p)) 14368350Seric continue; 14468350Seric map->map_valcolnm = p; 14568350Seric break; 14668350Seric 14768350Seric case 'z': 14868350Seric if (*++p != '\\') 14968350Seric map->map_coldelim = *p; 15068350Seric else 15168350Seric { 15268350Seric switch (*++p) 15368350Seric { 15468350Seric case 'n': 15568350Seric map->map_coldelim = '\n'; 15668350Seric break; 15768350Seric 15868350Seric case 't': 15968350Seric map->map_coldelim = '\t'; 16068350Seric break; 16168350Seric 16268350Seric default: 16368350Seric map->map_coldelim = '\\'; 16468350Seric } 16568350Seric } 16668350Seric break; 16768497Seric #ifdef RESERVED_FOR_SUN 16868497Seric case 'd': 16968497Seric map->map_mflags |= MF_DOMAIN_WIDE; 17068497Seric break; 17168497Seric 17268497Seric case 's': 17368497Seric /* info type */ 17468497Seric break; 17568497Seric #endif 17660089Seric } 17760089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 17860089Seric p++; 17960089Seric if (*p != '\0') 18060089Seric *p++ = '\0'; 18160089Seric } 18260089Seric if (map->map_app != NULL) 18360089Seric map->map_app = newstr(map->map_app); 18468350Seric if (map->map_keycolnm != NULL) 18568350Seric map->map_keycolnm = newstr(map->map_keycolnm); 18668350Seric if (map->map_valcolnm != NULL) 18768350Seric map->map_valcolnm = newstr(map->map_valcolnm); 18860089Seric 18960089Seric if (*p != '\0') 19060089Seric { 19160089Seric map->map_file = p; 19260089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 19360089Seric p++; 19460089Seric if (*p != '\0') 19560089Seric *p++ = '\0'; 19660089Seric map->map_file = newstr(map->map_file); 19760089Seric } 19860089Seric 19960089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 20060089Seric p++; 20160089Seric if (*p != '\0') 20260089Seric map->map_rebuild = newstr(p); 20360089Seric 20468350Seric if (map->map_file == NULL && 20568350Seric !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 20657208Seric { 20760089Seric syserr("No file name for %s map %s", 20860089Seric map->map_class->map_cname, map->map_mname); 20956822Seric return FALSE; 21057208Seric } 21160089Seric return TRUE; 21260089Seric } 21360089Seric /* 21460089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 21560089Seric ** 21660089Seric ** It also adds the map_app string. It can be used as a utility 21760089Seric ** in the map_lookup method. 21860089Seric ** 21960089Seric ** Parameters: 22060089Seric ** map -- the map that causes this. 22160089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 22260089Seric ** slen -- the length of s. 22360089Seric ** av -- arguments to interpolate into buf. 22460089Seric ** 22560089Seric ** Returns: 22667895Seric ** Pointer to rewritten result. This is static data that 22767895Seric ** should be copied if it is to be saved! 22860089Seric ** 22960089Seric ** Side Effects: 23060089Seric ** none. 23160089Seric */ 23260089Seric 23360089Seric char * 23460089Seric map_rewrite(map, s, slen, av) 23560089Seric register MAP *map; 23660089Seric register char *s; 23760089Seric int slen; 23860089Seric char **av; 23960089Seric { 24060089Seric register char *bp; 24160089Seric register char c; 24260089Seric char **avp; 24360089Seric register char *ap; 24460089Seric int i; 24560089Seric int len; 24667895Seric static int buflen = -1; 24767895Seric static char *buf = NULL; 24860089Seric 24960537Seric if (tTd(39, 1)) 25060089Seric { 25160256Seric printf("map_rewrite(%.*s), av =", slen, s); 25260256Seric if (av == NULL) 25360256Seric printf(" (nullv)"); 25460256Seric else 25560256Seric { 25660256Seric for (avp = av; *avp != NULL; avp++) 25760256Seric printf("\n\t%s", *avp); 25860256Seric } 25960256Seric printf("\n"); 26060089Seric } 26160089Seric 26260089Seric /* count expected size of output (can safely overestimate) */ 26360089Seric i = len = slen; 26460089Seric if (av != NULL) 26560089Seric { 26660089Seric bp = s; 26760089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 26860089Seric { 26960089Seric if (c != '%') 27060089Seric continue; 27160089Seric if (--i < 0) 27260089Seric break; 27360089Seric c = *bp++; 27460089Seric if (!(isascii(c) && isdigit(c))) 27560089Seric continue; 27663937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 27760089Seric continue; 27860089Seric if (*avp == NULL) 27960089Seric continue; 28060089Seric len += strlen(*avp); 28160089Seric } 28260089Seric } 28360089Seric if (map->map_app != NULL) 28460089Seric len += strlen(map->map_app); 28567895Seric if (buflen < ++len) 28660089Seric { 28760089Seric /* need to malloc additional space */ 28867895Seric buflen = len; 28967895Seric if (buf != NULL) 29067895Seric free(buf); 29167895Seric buf = xalloc(buflen); 29260089Seric } 29360089Seric 29467895Seric bp = buf; 29560089Seric if (av == NULL) 29660089Seric { 29760089Seric bcopy(s, bp, slen); 29860089Seric bp += slen; 29960089Seric } 30060089Seric else 30160089Seric { 30260089Seric while (--slen >= 0 && (c = *s++) != '\0') 30360089Seric { 30460089Seric if (c != '%') 30560089Seric { 30660089Seric pushc: 30760089Seric *bp++ = c; 30860089Seric continue; 30960089Seric } 31060089Seric if (--slen < 0 || (c = *s++) == '\0') 31160089Seric c = '%'; 31260089Seric if (c == '%') 31360089Seric goto pushc; 31460089Seric if (!(isascii(c) && isdigit(c))) 31560089Seric { 31660089Seric *bp++ = '%'; 31760089Seric goto pushc; 31860089Seric } 31963937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 32060089Seric continue; 32160089Seric if (*avp == NULL) 32260089Seric continue; 32360089Seric 32460089Seric /* transliterate argument into output string */ 32560089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 32660089Seric *bp++ = c; 32760089Seric } 32860089Seric } 32960089Seric if (map->map_app != NULL) 33060089Seric strcpy(bp, map->map_app); 33160089Seric else 33260089Seric *bp = '\0'; 33360537Seric if (tTd(39, 1)) 33467895Seric printf("map_rewrite => %s\n", buf); 33567895Seric return buf; 33660089Seric } 33760089Seric /* 33860537Seric ** INITMAPS -- initialize for aliasing 33960537Seric ** 34060537Seric ** Parameters: 34160537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 34260537Seric ** e -- current envelope. 34360537Seric ** 34460537Seric ** Returns: 34560537Seric ** none. 34660537Seric ** 34760537Seric ** Side Effects: 34860537Seric ** initializes aliases: 34960537Seric ** if NDBM: opens the database. 35060537Seric ** if ~NDBM: reads the aliases into the symbol table. 35160537Seric */ 35260537Seric 35360537Seric initmaps(rebuild, e) 35460537Seric bool rebuild; 35560537Seric register ENVELOPE *e; 35660537Seric { 35760537Seric extern void map_init(); 35860537Seric 35964671Seric #ifdef XDEBUG 36064671Seric checkfd012("entering initmaps"); 36164671Seric #endif 36260537Seric CurEnv = e; 36365085Seric if (rebuild) 36465085Seric { 36565085Seric stabapply(map_init, 1); 36665085Seric stabapply(map_init, 2); 36765085Seric } 36865085Seric else 36965085Seric { 37065085Seric stabapply(map_init, 0); 37165085Seric } 37264671Seric #ifdef XDEBUG 37364671Seric checkfd012("exiting initmaps"); 37464671Seric #endif 37560537Seric } 37660537Seric 37760537Seric void 37860537Seric map_init(s, rebuild) 37960537Seric register STAB *s; 38060537Seric int rebuild; 38160537Seric { 38260537Seric register MAP *map; 38360537Seric 38460537Seric /* has to be a map */ 38560537Seric if (s->s_type != ST_MAP) 38660537Seric return; 38760537Seric 38860537Seric map = &s->s_map; 38960537Seric if (!bitset(MF_VALID, map->map_mflags)) 39060537Seric return; 39160537Seric 39260537Seric if (tTd(38, 2)) 39368350Seric printf("map_init(%s:%s, %s, %d)\n", 39464690Seric map->map_class->map_cname == NULL ? "NULL" : 39564690Seric map->map_class->map_cname, 39668350Seric map->map_mname == NULL ? "NULL" : map->map_mname, 39765085Seric map->map_file == NULL ? "NULL" : map->map_file, 39865085Seric rebuild); 39960537Seric 40065085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && 40165085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) 40265085Seric { 40365085Seric if (tTd(38, 3)) 40465085Seric printf("\twrong pass\n"); 40565085Seric return; 40665085Seric } 40765085Seric 40860537Seric /* if already open, close it (for nested open) */ 40960537Seric if (bitset(MF_OPEN, map->map_mflags)) 41060537Seric { 41160537Seric map->map_class->map_close(map); 41260537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 41360537Seric } 41460537Seric 41565085Seric if (rebuild == 2) 41660537Seric { 41765085Seric rebuildaliases(map, FALSE); 41860537Seric } 41960537Seric else 42060537Seric { 42160537Seric if (map->map_class->map_open(map, O_RDONLY)) 42260537Seric { 42360537Seric if (tTd(38, 4)) 42468350Seric printf("\t%s:%s %s: valid\n", 42564690Seric map->map_class->map_cname == NULL ? "NULL" : 42664690Seric map->map_class->map_cname, 42768350Seric map->map_mname == NULL ? "NULL" : 42868350Seric map->map_mname, 42964690Seric map->map_file == NULL ? "NULL" : 43064690Seric map->map_file); 43160537Seric map->map_mflags |= MF_OPEN; 43260537Seric } 43368350Seric else 43468350Seric { 43568350Seric if (tTd(38, 4)) 43668350Seric printf("\t%s:%s %s: invalid: %s\n", 43768350Seric map->map_class->map_cname == NULL ? "NULL" : 43868350Seric map->map_class->map_cname, 43968350Seric map->map_mname == NULL ? "NULL" : 44068350Seric map->map_mname, 44168350Seric map->map_file == NULL ? "NULL" : 44268350Seric map->map_file, 44368350Seric errstring(errno)); 44468350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 44568350Seric { 44668350Seric extern MAPCLASS BogusMapClass; 44768350Seric 44868350Seric map->map_class = &BogusMapClass; 44968350Seric map->map_mflags |= MF_OPEN; 45068350Seric } 45168350Seric } 45260537Seric } 45360537Seric } 45460537Seric /* 45560089Seric ** NDBM modules 45660089Seric */ 45760089Seric 45860089Seric #ifdef NDBM 45960089Seric 46060089Seric /* 46160089Seric ** DBM_MAP_OPEN -- DBM-style map open 46260089Seric */ 46360089Seric 46460089Seric bool 46560089Seric ndbm_map_open(map, mode) 46660089Seric MAP *map; 46760089Seric int mode; 46860089Seric { 46964284Seric register DBM *dbm; 47064284Seric struct stat st; 47160089Seric 47260537Seric if (tTd(38, 2)) 47368350Seric printf("ndbm_map_open(%s, %s, %d)\n", 47468350Seric map->map_mname, map->map_file, mode); 47560089Seric 47660207Seric if (mode == O_RDWR) 47760207Seric mode |= O_CREAT|O_TRUNC; 47860207Seric 47960089Seric /* open the database */ 48060089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 48156822Seric if (dbm == NULL) 48256822Seric { 48364718Seric if (aliaswait(map, ".pag", FALSE)) 48464718Seric return TRUE; 48560207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 48656836Seric syserr("Cannot open DBM database %s", map->map_file); 48756822Seric return FALSE; 48856822Seric } 48960089Seric map->map_db1 = (void *) dbm; 49064964Seric if (mode == O_RDONLY) 49164964Seric { 49264964Seric if (bitset(MF_ALIAS, map->map_mflags) && 49364964Seric !aliaswait(map, ".pag", TRUE)) 49464718Seric return FALSE; 49564964Seric } 49664964Seric else 49764964Seric { 49864964Seric int fd; 49964964Seric 50064964Seric /* exclusive lock for duration of rebuild */ 50164964Seric fd = dbm_dirfno((DBM *) map->map_db1); 50264964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 50364964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 50464964Seric map->map_mflags |= MF_LOCKED; 50564964Seric } 50664718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 50764284Seric map->map_mtime = st.st_mtime; 50856822Seric return TRUE; 50956822Seric } 51060089Seric 51160089Seric 51260089Seric /* 51356822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 51456822Seric */ 51556822Seric 51656822Seric char * 51760089Seric ndbm_map_lookup(map, name, av, statp) 51856822Seric MAP *map; 51960089Seric char *name; 52056822Seric char **av; 52159084Seric int *statp; 52256822Seric { 52356822Seric datum key, val; 52464373Seric int fd; 52560089Seric char keybuf[MAXNAME + 1]; 52656822Seric 52760537Seric if (tTd(38, 20)) 52868350Seric printf("ndbm_map_lookup(%s, %s)\n", 52968350Seric map->map_mname, name); 53060089Seric 53160089Seric key.dptr = name; 53260089Seric key.dsize = strlen(name); 53360207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 53457014Seric { 53560089Seric if (key.dsize > sizeof keybuf - 1) 53660089Seric key.dsize = sizeof keybuf - 1; 53760089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 53860089Seric makelower(keybuf); 53960089Seric key.dptr = keybuf; 54057014Seric } 54164373Seric fd = dbm_dirfno((DBM *) map->map_db1); 54264388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 54364373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 54463753Seric val.dptr = NULL; 54563753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 54663753Seric { 54763753Seric val = dbm_fetch((DBM *) map->map_db1, key); 54863753Seric if (val.dptr != NULL) 54963753Seric map->map_mflags &= ~MF_TRY1NULL; 55063753Seric } 55163753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 55263753Seric { 55356822Seric key.dsize++; 55463753Seric val = dbm_fetch((DBM *) map->map_db1, key); 55563753Seric if (val.dptr != NULL) 55663753Seric map->map_mflags &= ~MF_TRY0NULL; 55763753Seric } 55864388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 55964373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 56056822Seric if (val.dptr == NULL) 56156822Seric return NULL; 56260207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 56363753Seric return map_rewrite(map, name, strlen(name), NULL); 56463753Seric else 56563753Seric return map_rewrite(map, val.dptr, val.dsize, av); 56656822Seric } 56756822Seric 56856822Seric 56956822Seric /* 57060089Seric ** DBM_MAP_STORE -- store a datum in the database 57156822Seric */ 57256822Seric 57360089Seric void 57460089Seric ndbm_map_store(map, lhs, rhs) 57560089Seric register MAP *map; 57660089Seric char *lhs; 57760089Seric char *rhs; 57860089Seric { 57960089Seric datum key; 58060089Seric datum data; 58160089Seric int stat; 58260089Seric 58360537Seric if (tTd(38, 12)) 58468350Seric printf("ndbm_map_store(%s, %s, %s)\n", 58568350Seric map->map_mname, lhs, rhs); 58660089Seric 58760089Seric key.dsize = strlen(lhs); 58860089Seric key.dptr = lhs; 58960089Seric 59060089Seric data.dsize = strlen(rhs); 59160089Seric data.dptr = rhs; 59260089Seric 59360207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 59460089Seric { 59560089Seric key.dsize++; 59660089Seric data.dsize++; 59760089Seric } 59860089Seric 59960089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 60060089Seric if (stat > 0) 60160089Seric { 60268497Seric if (!bitset(MF_APPEND, map->map_mflags)) 60368497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 60468497Seric else 60568497Seric { 60668497Seric static char *buf = NULL; 60768497Seric static int bufsiz = 0; 60868879Seric auto int xstat; 60968497Seric datum old; 61068497Seric 61168879Seric old.dptr = ndbm_map_lookup(map, key.dptr, NULL, &xstat); 61268497Seric if (old.dptr != NULL && *old.dptr != '\0') 61368497Seric { 61468497Seric old.dsize = strlen(old.dptr); 61568497Seric if (data.dsize + old.dsize + 2 > bufsiz) 61668497Seric { 61768497Seric if (buf != NULL) 61868497Seric (void) free(buf); 61968497Seric bufsiz = data.dsize + old.dsize + 2; 62068497Seric buf = xalloc(bufsiz); 62168497Seric } 62268497Seric sprintf(buf, "%s,%s", data.dptr, old.dptr); 62368497Seric data.dsize = data.dsize + old.dsize + 1; 62468497Seric data.dptr = buf; 62568497Seric if (tTd(38, 9)) 62668497Seric printf("ndbm_map_store append=%s\n", data.dptr); 62768497Seric } 62868497Seric } 62960089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 63060089Seric } 63160089Seric if (stat != 0) 63260089Seric syserr("readaliases: dbm put (%s)", lhs); 63360089Seric } 63460089Seric 63560089Seric 63660089Seric /* 63760207Seric ** NDBM_MAP_CLOSE -- close the database 63860089Seric */ 63960089Seric 64060089Seric void 64160089Seric ndbm_map_close(map) 64260089Seric register MAP *map; 64360089Seric { 64466773Seric if (tTd(38, 9)) 64568350Seric printf("ndbm_map_close(%s, %s, %x)\n", 64668350Seric map->map_mname, map->map_file, map->map_mflags); 64766773Seric 64860207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 64960089Seric { 65064250Seric #ifdef NIS 65164075Seric bool inclnull; 65260089Seric char buf[200]; 65360089Seric 65464075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 65564075Seric map->map_mflags &= ~MF_INCLNULL; 65664075Seric 65769651Seric if (strstr(map->map_file, "/yp/") != NULL) 65869651Seric { 65969651Seric (void) sprintf(buf, "%010ld", curtime()); 66069651Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 66160089Seric 66269651Seric (void) gethostname(buf, sizeof buf); 66369651Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 66469651Seric } 66564075Seric 66664075Seric if (inclnull) 66764075Seric map->map_mflags |= MF_INCLNULL; 66860089Seric #endif 66960089Seric 67060089Seric /* write out the distinguished alias */ 67160089Seric ndbm_map_store(map, "@", "@"); 67260089Seric } 67360089Seric dbm_close((DBM *) map->map_db1); 67460089Seric } 67560089Seric 67660089Seric #endif 67760089Seric /* 67860582Seric ** NEWDB (Hash and BTree) Modules 67960089Seric */ 68060089Seric 68160089Seric #ifdef NEWDB 68260089Seric 68360089Seric /* 68460582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 68560582Seric ** 68660582Seric ** These do rather bizarre locking. If you can lock on open, 68760582Seric ** do that to avoid the condition of opening a database that 68860582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 68960582Seric ** there will be a race condition. If opening for read-only, 69060582Seric ** we immediately release the lock to avoid freezing things up. 69160582Seric ** We really ought to hold the lock, but guarantee that we won't 69260582Seric ** be pokey about it. That's hard to do. 69360089Seric */ 69460089Seric 69556822Seric bool 69660089Seric bt_map_open(map, mode) 69756822Seric MAP *map; 69860089Seric int mode; 69956822Seric { 70056822Seric DB *db; 70160228Seric int i; 70260582Seric int omode; 70364373Seric int fd; 70464284Seric struct stat st; 70568528Seric char buf[MAXNAME + 1]; 70656822Seric 70760537Seric if (tTd(38, 2)) 70868350Seric printf("bt_map_open(%s, %s, %d)\n", 70968350Seric map->map_mname, map->map_file, mode); 71060089Seric 71160582Seric omode = mode; 71260582Seric if (omode == O_RDWR) 71360582Seric { 71460582Seric omode |= O_CREAT|O_TRUNC; 71565830Seric #if defined(O_EXLOCK) && HASFLOCK 71660582Seric omode |= O_EXLOCK; 71766843Seric # if !OLD_NEWDB 71860582Seric } 71960582Seric else 72060582Seric { 72160582Seric omode |= O_SHLOCK; 72260582Seric # endif 72360582Seric #endif 72460582Seric } 72560207Seric 72660228Seric (void) strcpy(buf, map->map_file); 72760228Seric i = strlen(buf); 72860228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 72960228Seric (void) strcat(buf, ".db"); 73060582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 73156822Seric if (db == NULL) 73256822Seric { 73364718Seric #ifdef MAYBENEXTRELEASE 73464718Seric if (aliaswait(map, ".db", FALSE)) 73564718Seric return TRUE; 73664718Seric #endif 73760207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 73856836Seric syserr("Cannot open BTREE database %s", map->map_file); 73956822Seric return FALSE; 74056822Seric } 74168350Seric #if !OLD_NEWDB 74264373Seric fd = db->fd(db); 74368778Seric # if defined(O_EXLOCK) && HASFLOCK 74468778Seric if (fd >= 0) 74568778Seric { 74668778Seric if (mode == O_RDONLY) 74768778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 74868778Seric else 74968778Seric map->map_mflags |= MF_LOCKED; 75068778Seric } 75168778Seric # else 75264373Seric if (mode == O_RDWR && fd >= 0) 75364388Seric { 75464388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 75564388Seric map->map_mflags |= MF_LOCKED; 75664388Seric } 75760582Seric # endif 75860582Seric #endif 75960585Seric 76060585Seric /* try to make sure that at least the database header is on disk */ 76160585Seric if (mode == O_RDWR) 76266843Seric #if OLD_NEWDB 76364373Seric (void) db->sync(db); 76464373Seric #else 76560585Seric (void) db->sync(db, 0); 76660585Seric 76764373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 76864284Seric map->map_mtime = st.st_mtime; 76964284Seric #endif 77064284Seric 77160089Seric map->map_db2 = (void *) db; 77260207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 77364718Seric if (!aliaswait(map, ".db", TRUE)) 77464718Seric return FALSE; 77556822Seric return TRUE; 77656822Seric } 77756822Seric 77856822Seric 77956822Seric /* 78056822Seric ** HASH_MAP_INIT -- HASH-style map initialization 78156822Seric */ 78256822Seric 78356822Seric bool 78460089Seric hash_map_open(map, mode) 78556822Seric MAP *map; 78660089Seric int mode; 78756822Seric { 78856822Seric DB *db; 78960228Seric int i; 79060582Seric int omode; 79164373Seric int fd; 79264284Seric struct stat st; 79368528Seric char buf[MAXNAME + 1]; 79456822Seric 79560537Seric if (tTd(38, 2)) 79668350Seric printf("hash_map_open(%s, %s, %d)\n", 79768350Seric map->map_mname, map->map_file, mode); 79860089Seric 79960582Seric omode = mode; 80060582Seric if (omode == O_RDWR) 80160582Seric { 80260582Seric omode |= O_CREAT|O_TRUNC; 80365830Seric #if defined(O_EXLOCK) && HASFLOCK 80460582Seric omode |= O_EXLOCK; 80566843Seric # if !OLD_NEWDB 80660582Seric } 80760582Seric else 80860582Seric { 80960582Seric omode |= O_SHLOCK; 81060582Seric # endif 81160582Seric #endif 81260582Seric } 81360207Seric 81460228Seric (void) strcpy(buf, map->map_file); 81560228Seric i = strlen(buf); 81660228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 81760228Seric (void) strcat(buf, ".db"); 81860582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 81956822Seric if (db == NULL) 82056822Seric { 82164718Seric #ifdef MAYBENEXTRELEASE 82264718Seric if (aliaswait(map, ".db", FALSE)) 82364718Seric return TRUE; 82464718Seric #endif 82560207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 82656836Seric syserr("Cannot open HASH database %s", map->map_file); 82756822Seric return FALSE; 82856822Seric } 82968350Seric #if !OLD_NEWDB 83064373Seric fd = db->fd(db); 83168778Seric # if defined(O_EXLOCK) && HASFLOCK 83268778Seric if (fd >= 0) 83368778Seric { 83468778Seric if (mode == O_RDONLY) 83568778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 83668778Seric else 83768778Seric map->map_mflags |= MF_LOCKED; 83868778Seric } 83968778Seric # else 84064373Seric if (mode == O_RDWR && fd >= 0) 84164388Seric { 84264388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 84364388Seric map->map_mflags |= MF_LOCKED; 84464388Seric } 84560582Seric # endif 84660582Seric #endif 84760585Seric 84860585Seric /* try to make sure that at least the database header is on disk */ 84960585Seric if (mode == O_RDWR) 85066843Seric #if OLD_NEWDB 85164373Seric (void) db->sync(db); 85264373Seric #else 85360585Seric (void) db->sync(db, 0); 85460585Seric 85564373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 85664284Seric map->map_mtime = st.st_mtime; 85764284Seric #endif 85864284Seric 85960089Seric map->map_db2 = (void *) db; 86060207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 86164718Seric if (!aliaswait(map, ".db", TRUE)) 86264718Seric return FALSE; 86356822Seric return TRUE; 86456822Seric } 86556822Seric 86656822Seric 86756822Seric /* 86856822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 86956822Seric */ 87056822Seric 87156822Seric char * 87260089Seric db_map_lookup(map, name, av, statp) 87356822Seric MAP *map; 87460089Seric char *name; 87556822Seric char **av; 87659084Seric int *statp; 87756822Seric { 87856822Seric DBT key, val; 87960422Seric register DB *db = (DB *) map->map_db2; 88060422Seric int st; 88160422Seric int saveerrno; 88264373Seric int fd; 88360089Seric char keybuf[MAXNAME + 1]; 88456822Seric 88560537Seric if (tTd(38, 20)) 88668350Seric printf("db_map_lookup(%s, %s)\n", 88768350Seric map->map_mname, name); 88860089Seric 88960089Seric key.size = strlen(name); 89060089Seric if (key.size > sizeof keybuf - 1) 89160089Seric key.size = sizeof keybuf - 1; 89260089Seric key.data = keybuf; 89360089Seric bcopy(name, keybuf, key.size + 1); 89460207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 89560089Seric makelower(keybuf); 89666843Seric #if !OLD_NEWDB 89764388Seric fd = db->fd(db); 89864388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 89964388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 90060422Seric #endif 90163753Seric st = 1; 90263753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 90363753Seric { 90463753Seric st = db->get(db, &key, &val, 0); 90563753Seric if (st == 0) 90663753Seric map->map_mflags &= ~MF_TRY1NULL; 90763753Seric } 90863753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 90963753Seric { 91063753Seric key.size++; 91163753Seric st = db->get(db, &key, &val, 0); 91263753Seric if (st == 0) 91363753Seric map->map_mflags &= ~MF_TRY0NULL; 91463753Seric } 91560422Seric saveerrno = errno; 91666843Seric #if !OLD_NEWDB 91764388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 91864373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 91960422Seric #endif 92060422Seric if (st != 0) 92160422Seric { 92260422Seric errno = saveerrno; 92360422Seric if (st < 0) 92460422Seric syserr("db_map_lookup: get (%s)", name); 92556822Seric return NULL; 92660422Seric } 92760207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 92863753Seric return map_rewrite(map, name, strlen(name), NULL); 92963753Seric else 93063753Seric return map_rewrite(map, val.data, val.size, av); 93156822Seric } 93256822Seric 93360089Seric 93460089Seric /* 93560089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 93656822Seric */ 93756822Seric 93860089Seric void 93960089Seric db_map_store(map, lhs, rhs) 94060089Seric register MAP *map; 94160089Seric char *lhs; 94260089Seric char *rhs; 94356822Seric { 94460089Seric int stat; 94560089Seric DBT key; 94660089Seric DBT data; 94760089Seric register DB *db = map->map_db2; 94856822Seric 94960537Seric if (tTd(38, 20)) 95068350Seric printf("db_map_store(%s, %s, %s)\n", 95168350Seric map->map_mname, lhs, rhs); 95260089Seric 95360089Seric key.size = strlen(lhs); 95460089Seric key.data = lhs; 95560089Seric 95660089Seric data.size = strlen(rhs); 95760089Seric data.data = rhs; 95860089Seric 95960207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 96056822Seric { 96160089Seric key.size++; 96260089Seric data.size++; 96360089Seric } 96456836Seric 96560089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 96660089Seric if (stat > 0) 96760089Seric { 96868497Seric if (!bitset(MF_APPEND, map->map_mflags)) 96968497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 97068497Seric else 97168497Seric { 97268497Seric static char *buf = NULL; 97368497Seric static int bufsiz = 0; 97468497Seric DBT old; 97568497Seric 97668497Seric old.data = db_map_lookup(map, key.data, NULL, &stat); 97768497Seric if (old.data != NULL) 97868497Seric { 97968497Seric old.size = strlen(old.data); 98068497Seric if (data.size + old.size + 2 > bufsiz) 98168497Seric { 98268497Seric if (buf != NULL) 98368497Seric (void) free(buf); 98468497Seric bufsiz = data.size + old.size + 2; 98568497Seric buf = xalloc(bufsiz); 98668497Seric } 98768497Seric sprintf(buf, "%s,%s", data.data, old.data); 98868497Seric data.size = data.size + old.size + 1; 98968497Seric data.data = buf; 99068497Seric if (tTd(38, 9)) 99168497Seric printf("db_map_store append=%s\n", data.data); 99268497Seric } 99368497Seric } 99460089Seric stat = db->put(db, &key, &data, 0); 99560089Seric } 99660089Seric if (stat != 0) 99760089Seric syserr("readaliases: db put (%s)", lhs); 99860089Seric } 99956836Seric 100056847Seric 100160089Seric /* 100260089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 100360089Seric */ 100460089Seric 100560089Seric void 100660089Seric db_map_close(map) 100760089Seric MAP *map; 100860089Seric { 100960089Seric register DB *db = map->map_db2; 101060089Seric 101160537Seric if (tTd(38, 9)) 101268350Seric printf("db_map_close(%s, %s, %x)\n", 101368350Seric map->map_mname, map->map_file, map->map_mflags); 101460089Seric 101560207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 101658804Seric { 101760089Seric /* write out the distinguished alias */ 101860089Seric db_map_store(map, "@", "@"); 101958804Seric } 102058963Seric 102160089Seric if (db->close(db) != 0) 102260089Seric syserr("readaliases: db close failure"); 102356822Seric } 102457208Seric 102560089Seric #endif 102660089Seric /* 102760089Seric ** NIS Modules 102860089Seric */ 102960089Seric 103060089Seric # ifdef NIS 103160089Seric 103264369Seric # ifndef YPERR_BUSY 103364369Seric # define YPERR_BUSY 16 103464369Seric # endif 103564369Seric 103657208Seric /* 103760089Seric ** NIS_MAP_OPEN -- open DBM map 103857208Seric */ 103957208Seric 104057208Seric bool 104160089Seric nis_map_open(map, mode) 104257208Seric MAP *map; 104360089Seric int mode; 104457208Seric { 104557216Seric int yperr; 104660215Seric register char *p; 104760215Seric auto char *vp; 104860215Seric auto int vsize; 104957216Seric char *master; 105057216Seric 105160537Seric if (tTd(38, 2)) 105268350Seric printf("nis_map_open(%s, %s)\n", 105368350Seric map->map_mname, map->map_file); 105460089Seric 105560207Seric if (mode != O_RDONLY) 105660207Seric { 105764650Seric /* issue a pseudo-error message */ 105864650Seric #ifdef ENOSYS 105964650Seric errno = ENOSYS; 106064650Seric #else 106164650Seric # ifdef EFTYPE 106264650Seric errno = EFTYPE; 106364650Seric # else 106464650Seric errno = ENXIO; 106564650Seric # endif 106664650Seric #endif 106760207Seric return FALSE; 106860207Seric } 106960207Seric 107060089Seric p = strchr(map->map_file, '@'); 107160089Seric if (p != NULL) 107260089Seric { 107360089Seric *p++ = '\0'; 107460089Seric if (*p != '\0') 107560089Seric map->map_domain = p; 107660089Seric } 107760215Seric 107860089Seric if (*map->map_file == '\0') 107960089Seric map->map_file = "mail.aliases"; 108060089Seric 108166157Seric if (map->map_domain == NULL) 108266157Seric { 108366157Seric yperr = yp_get_default_domain(&map->map_domain); 108466157Seric if (yperr != 0) 108566157Seric { 108666744Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 108768350Seric syserr("421 NIS map %s specified, but NIS not running\n", 108866744Seric map->map_file); 108966157Seric return FALSE; 109066157Seric } 109166157Seric } 109266157Seric 109360215Seric /* check to see if this map actually exists */ 109460089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 109560089Seric &vp, &vsize); 109660537Seric if (tTd(38, 10)) 109760089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 109860089Seric map->map_domain, map->map_file, yperr_string(yperr)); 109960089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 110068350Seric { 110168350Seric if (!bitset(MF_ALIAS, map->map_mflags) || 110268350Seric aliaswait(map, NULL, TRUE)) 110368350Seric return TRUE; 110468350Seric } 110560215Seric 110660215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 110768735Seric { 110868735Seric syserr("421 Cannot bind to map %s in domain %s: %s", 110968735Seric map->map_file, map->map_domain, yperr_string(yperr)); 111068735Seric } 111160215Seric 111260089Seric return FALSE; 111360089Seric } 111460089Seric 111560089Seric 111660089Seric /* 111757208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 111857208Seric */ 111957208Seric 112057208Seric char * 112160089Seric nis_map_lookup(map, name, av, statp) 112257208Seric MAP *map; 112360089Seric char *name; 112457208Seric char **av; 112559084Seric int *statp; 112657208Seric { 112757208Seric char *vp; 112857642Seric auto int vsize; 112959274Seric int buflen; 113060215Seric int yperr; 113160089Seric char keybuf[MAXNAME + 1]; 113257208Seric 113360537Seric if (tTd(38, 20)) 113468350Seric printf("nis_map_lookup(%s, %s)\n", 113568350Seric map->map_mname, name); 113660089Seric 113760089Seric buflen = strlen(name); 113860089Seric if (buflen > sizeof keybuf - 1) 113960089Seric buflen = sizeof keybuf - 1; 114060089Seric bcopy(name, keybuf, buflen + 1); 114160207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 114260089Seric makelower(keybuf); 114363753Seric yperr = YPERR_KEY; 114463753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 114563753Seric { 114663753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 114763753Seric &vp, &vsize); 114863753Seric if (yperr == 0) 114963753Seric map->map_mflags &= ~MF_TRY1NULL; 115063753Seric } 115163753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 115263753Seric { 115359274Seric buflen++; 115463753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 115563753Seric &vp, &vsize); 115663753Seric if (yperr == 0) 115763753Seric map->map_mflags &= ~MF_TRY0NULL; 115863753Seric } 115960089Seric if (yperr != 0) 116060089Seric { 116160089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 116260215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 116357208Seric return NULL; 116460089Seric } 116560207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 116663753Seric return map_rewrite(map, name, strlen(name), NULL); 116763753Seric else 116863753Seric return map_rewrite(map, vp, vsize, av); 116957208Seric } 117057208Seric 117169401Seric 117269401Seric /* 117369401Seric ** NIS_GETCANONNAME -- look up canonical name in NIS 117469401Seric */ 117569401Seric 117669401Seric bool 117769401Seric nis_getcanonname(name, hbsize, statp) 117869401Seric char *name; 117969401Seric int hbsize; 118069401Seric int *statp; 118169401Seric { 118269401Seric char *vp; 118369401Seric auto int vsize; 118469401Seric int keylen; 118569401Seric int yperr; 118669401Seric static bool try0null = TRUE; 118769401Seric static bool try1null = TRUE; 118869401Seric static char *yp_domain = NULL; 118969401Seric char *domain, *p; 119069401Seric char host_record[MAXLINE]; 119169401Seric char buf[MAXNAME]; 119269401Seric char *cname; 119369401Seric extern char *get_column(); 119469401Seric 119569401Seric if (tTd(38, 20)) 119669401Seric printf("nis_getcanonname(%s)\n", name); 119769401Seric 119869401Seric shorten_hostname(name); 119969401Seric 120069401Seric /* we only accept single token search key */ 120169401Seric if (strchr(name, '.')) 120269401Seric { 120369401Seric *statp = EX_NOHOST; 120469401Seric return FALSE; 120569401Seric } 120669401Seric 120769401Seric keylen = strlen(name); 120869401Seric 120969401Seric if (yp_domain == NULL) 121069401Seric yp_get_default_domain(&yp_domain); 121169401Seric makelower(name); 121269401Seric yperr = YPERR_KEY; 121369401Seric if (try0null) 121469401Seric { 121569401Seric yperr = yp_match(yp_domain, "hosts.byname", name, keylen, 121669401Seric &vp, &vsize); 121769401Seric if (yperr == 0) 121869401Seric try1null = FALSE; 121969401Seric } 122069401Seric if (yperr == YPERR_KEY && try1null) 122169401Seric { 122269401Seric keylen++; 122369401Seric yperr = yp_match(yp_domain, "hosts.byname", name, keylen, 122469401Seric &vp, &vsize); 122569401Seric if (yperr == 0) 122669401Seric try0null = FALSE; 122769401Seric } 122869401Seric if (yperr != 0) 122969401Seric { 123069401Seric if (yperr == YPERR_KEY) 123169401Seric *statp = EX_NOHOST; 123269401Seric else if (yperr == YPERR_BUSY) 123369401Seric *statp = EX_TEMPFAIL; 123469401Seric else 123569401Seric *statp = EX_UNAVAILABLE; 123669401Seric return FALSE; 123769401Seric } 123869401Seric strncpy(host_record, vp, vsize); 123969401Seric host_record[vsize] = '\0'; 124069663Seric if (tTd(38, 44)) 124169663Seric printf("got record `%s'\n", host_record); 124269663Seric cname = get_column(host_record, 1, '\0', buf); 124369401Seric if (cname == NULL) 124469401Seric { 124569401Seric /* this should not happen, but.... */ 124669401Seric *statp = EX_NOHOST; 124769401Seric return FALSE; 124869401Seric } 124969401Seric 1250*69703Seric if (strchr(cname, '.') != NULL) 125169401Seric { 1252*69703Seric domain = ""; 1253*69703Seric } 1254*69703Seric else 1255*69703Seric { 1256*69703Seric domain = macvalue('m', CurEnv); 1257*69703Seric if (domain == NULL) 1258*69703Seric domain = ""; 1259*69703Seric } 1260*69703Seric if (hbsize >= strlen(cname) + strlen(domain) + 1) 1261*69703Seric { 1262*69703Seric if (domain[0] == '\0') 1263*69703Seric strcpy(name, vp); 1264*69703Seric else 1265*69703Seric sprintf(name, "%s.%s", vp, domain); 126669401Seric *statp = EX_OK; 126769401Seric return TRUE; 126869401Seric } 126969401Seric *statp = EX_UNAVAILABLE; 127069401Seric return FALSE; 127169401Seric } 127269401Seric 127368350Seric #endif 127468350Seric /* 127568350Seric ** NISPLUS Modules 127668350Seric ** 127768350Seric ** This code donated by Sun Microsystems. 127868350Seric */ 127967848Seric 128068350Seric #ifdef NISPLUS 128168350Seric 128268350Seric #undef NIS /* symbol conflict in nis.h */ 128368350Seric #include <rpcsvc/nis.h> 128468350Seric #include <rpcsvc/nislib.h> 128568350Seric 128668350Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 128768350Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 128868350Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 128968350Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 129068350Seric 129167848Seric /* 129268350Seric ** NISPLUS_MAP_OPEN -- open nisplus table 129367848Seric */ 129467848Seric 129568350Seric bool 129668350Seric nisplus_map_open(map, mode) 129767848Seric MAP *map; 129868350Seric int mode; 129967848Seric { 130068350Seric register char *p; 130168350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 130268350Seric nis_result *res = NULL; 130368350Seric u_int objs_len; 130468350Seric nis_object *obj_ptr; 130568350Seric int retry_cnt, max_col, i; 130668350Seric 130768350Seric if (tTd(38, 2)) 130868350Seric printf("nisplus_map_open(%s, %s, %d)\n", 130968350Seric map->map_mname, map->map_file, mode); 131068350Seric 131168350Seric if (mode != O_RDONLY) 131268350Seric { 131368350Seric errno = ENODEV; 131468350Seric return FALSE; 131568350Seric } 131668350Seric 131768350Seric if (*map->map_file == '\0') 131868350Seric map->map_file = "mail_aliases.org_dir"; 131968350Seric 132068350Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 132168350Seric { 132268350Seric /* set default NISPLUS Domain to $m */ 132368350Seric extern char *nisplus_default_domain(); 132468350Seric 132568350Seric map->map_domain = newstr(nisplus_default_domain()); 132668350Seric if (tTd(38, 2)) 132768350Seric printf("nisplus_map_open(%s): using domain %s\n", 132868350Seric map->map_file, map->map_domain); 132968350Seric } 133068350Seric if (!PARTIAL_NAME(map->map_file)) 133168350Seric map->map_domain = newstr(""); 133268350Seric 133368350Seric /* check to see if this map actually exists */ 133468350Seric if (PARTIAL_NAME(map->map_file)) 133568350Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 133668350Seric else 133768350Seric strcpy(qbuf, map->map_file); 133868350Seric 133968350Seric retry_cnt = 0; 134068350Seric while (res == NULL || res->status != NIS_SUCCESS) 134168350Seric { 134268350Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 134368350Seric switch (res->status) 134468350Seric { 134568350Seric case NIS_SUCCESS: 134668350Seric case NIS_TRYAGAIN: 134768350Seric case NIS_RPCERROR: 134868350Seric case NIS_NAMEUNREACHABLE: 134968350Seric break; 135068350Seric 135168350Seric default: /* all other nisplus errors */ 135268350Seric #if 0 135368350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 135468350Seric syserr("421 Cannot find table %s.%s: %s", 135568350Seric map->map_file, map->map_domain, 135668350Seric nis_sperrno(res->status)); 135768350Seric #endif 135868350Seric errno = EBADR; 135968350Seric return FALSE; 136068350Seric } 136168350Seric sleep(2); /* try not to overwhelm hosed server */ 136268350Seric if (retry_cnt++ > 4) 136368350Seric { 136468350Seric errno = EBADR; 136568350Seric return FALSE; 136668350Seric } 136768350Seric } 136868350Seric 136968350Seric if (NIS_RES_NUMOBJ(res) != 1 || 137068350Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 137168350Seric { 137268350Seric if (tTd(38, 10)) 137368350Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 137468350Seric #if 0 137568350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 137668350Seric syserr("421 %s.%s: %s is not a table", 137768350Seric map->map_file, map->map_domain, 137868350Seric nis_sperrno(res->status)); 137968350Seric #endif 138068350Seric errno = EBADR; 138168350Seric return FALSE; 138268350Seric } 138368350Seric /* default key column is column 0 */ 138468350Seric if (map->map_keycolnm == NULL) 138568350Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 138668350Seric 138768350Seric max_col = COL_MAX(res); 138868350Seric 138968350Seric /* verify the key column exist */ 139068350Seric for (i=0; i< max_col; i++) 139168350Seric { 139268350Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 139368350Seric break; 139468350Seric } 139568350Seric if (i == max_col) 139668350Seric { 139768350Seric if (tTd(38, 2)) 139868350Seric printf("nisplus_map_open(%s): can not find key column %s\n", 139968350Seric map->map_file, map->map_keycolnm); 140068350Seric errno = EBADR; 140168350Seric return FALSE; 140268350Seric } 140368350Seric 140468350Seric /* default value column is the last column */ 140568350Seric if (map->map_valcolnm == NULL) 140668350Seric { 140768350Seric map->map_valcolno = max_col - 1; 140868350Seric return TRUE; 140968350Seric } 141068350Seric 141168350Seric for (i=0; i< max_col; i++) 141268350Seric { 141368350Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 141468350Seric { 141568350Seric map->map_valcolno = i; 141668350Seric return TRUE; 141768350Seric } 141868350Seric } 141968350Seric 142068350Seric if (tTd(38, 2)) 142168350Seric printf("nisplus_map_open(%s): can not find column %s\n", 142268350Seric map->map_file, map->map_keycolnm); 142368350Seric errno = EBADR; 142468350Seric return FALSE; 142567848Seric } 142667848Seric 142767848Seric 142867848Seric /* 142968350Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 143067848Seric */ 143167848Seric 143268350Seric char * 143368350Seric nisplus_map_lookup(map, name, av, statp) 143467848Seric MAP *map; 143568350Seric char *name; 143668350Seric char **av; 143768350Seric int *statp; 143867848Seric { 143968350Seric char *vp; 144068350Seric auto int vsize; 144168350Seric int buflen; 144268350Seric char search_key[MAXNAME + 1]; 144368350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 144468350Seric nis_result *result; 144568350Seric 144668350Seric if (tTd(38, 20)) 144768350Seric printf("nisplus_map_lookup(%s, %s)\n", 144868350Seric map->map_mname, name); 144968350Seric 145068350Seric if (!bitset(MF_OPEN, map->map_mflags)) 145168350Seric { 145268350Seric if (nisplus_map_open(map, O_RDONLY)) 145368350Seric map->map_mflags |= MF_OPEN; 145468350Seric else 145568350Seric { 145668350Seric *statp = EX_UNAVAILABLE; 145768350Seric return NULL; 145868350Seric } 145968350Seric } 146068350Seric 146168350Seric buflen = strlen(name); 146268350Seric if (buflen > sizeof search_key - 1) 146368350Seric buflen = sizeof search_key - 1; 146468350Seric bcopy(name, search_key, buflen + 1); 146568350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 146668350Seric makelower(search_key); 146768350Seric 146868350Seric /* construct the query */ 146968350Seric if (PARTIAL_NAME(map->map_file)) 147068350Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 147168350Seric search_key, map->map_file, map->map_domain); 147268350Seric else 147368350Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 147468350Seric search_key, map->map_file); 147568350Seric 147668350Seric if (tTd(38, 20)) 147768350Seric printf("qbuf=%s\n", qbuf); 147868350Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 147968350Seric if (result->status == NIS_SUCCESS) 148068350Seric { 148168350Seric int count; 148268350Seric char *str; 148368350Seric 148468350Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 148568350Seric { 148668350Seric if (LogLevel > 10) 148768350Seric syslog(LOG_WARNING, 148868350Seric "%s:Lookup error, expected 1 entry, got (%d)", 148968350Seric map->map_file, count); 149068350Seric 149168350Seric /* ignore second entry */ 149268350Seric if (tTd(38, 20)) 149368350Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 149468350Seric name, count); 149568350Seric } 149668350Seric 149768350Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 149868350Seric /* set the length of the result */ 149968350Seric if (vp == NULL) 150068350Seric vp = ""; 150168350Seric vsize = strlen(vp); 150268350Seric if (tTd(38, 20)) 150368350Seric printf("nisplus_map_lookup(%s), found %s\n", 150468350Seric name, vp); 150568350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 150668350Seric str = map_rewrite(map, name, strlen(name), NULL); 150768350Seric else 150868350Seric str = map_rewrite(map, vp, vsize, av); 150968350Seric nis_freeresult(result); 151068350Seric #ifdef MAP_EXIT_STAT 151168350Seric *statp = EX_OK; 151268350Seric #endif 151368350Seric return str; 151468350Seric } 151568350Seric else 151668350Seric { 151768350Seric #ifdef MAP_EXIT_STAT 151868350Seric if (result->status == NIS_NOTFOUND) 151968350Seric *statp = EX_NOTFOUND; 152068350Seric else if (result->status == NIS_TRYAGAIN) 152168350Seric *statp = EX_TEMPFAIL; 152268350Seric else 152368350Seric { 152468350Seric *statp = EX_UNAVAILABLE; 152568350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 152668350Seric } 152768350Seric #else 152868350Seric if ((result->status != NIS_NOTFOUND) && 152968350Seric (result->status != NIS_TRYAGAIN)) 153068350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 153168350Seric #endif 153268350Seric } 153368350Seric if (tTd(38, 20)) 153468350Seric printf("nisplus_map_lookup(%s), failed\n", name); 153568350Seric nis_freeresult(result); 153668350Seric return NULL; 153767848Seric } 153867848Seric 153968350Seric 154069401Seric 154169401Seric /* 154269401Seric ** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 154369401Seric */ 154469401Seric 154569401Seric bool 154669401Seric nisplus_getcanonname(name, hbsize, statp) 154769401Seric char *name; 154869401Seric int hbsize; 154969401Seric int *statp; 155069401Seric { 155169401Seric char *vp; 155269401Seric auto int vsize; 155369401Seric int buflen; 155469477Seric char buf[MAXLINE + NIS_MAXNAMELEN]; 155569401Seric nis_result *result; 155669401Seric char *p; 155769401Seric int len; 155869401Seric 155969401Seric shorten_hostname(name); 156069401Seric 156169401Seric p = strchr(name, '.'); 156269401Seric if (p == NULL) 156369401Seric { 156469401Seric /* single token */ 156569477Seric sprintf(buf, "[name=%s],hosts.org_dir", name); 156669401Seric } 156769401Seric else if (p[1] != '\0') 156869401Seric { 156969401Seric /* multi token -- take only first token in name buf */ 157069401Seric *p = '\0'; 157169477Seric sprintf(buf, "[name=%s],hosts.org_dir.%s", name, &p[1]); 157269401Seric } 157369401Seric else 157469401Seric { 157569401Seric *statp = EX_NOHOST; 157669401Seric return FALSE; 157769401Seric } 157869401Seric 157969401Seric if (tTd(38, 20)) 158069478Seric printf("\nnisplus_getcanoname(%s), qbuf=%s\n", 158169478Seric name, buf); 158269401Seric 158369477Seric result = nis_list(buf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 158469401Seric NULL, NULL); 158569401Seric 158669401Seric if (result->status == NIS_SUCCESS) 158769401Seric { 158869401Seric int count; 158969401Seric char *str; 159069401Seric char *domain; 159169401Seric 159269401Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 159369401Seric { 159469401Seric #ifdef LOG 159569401Seric if (LogLevel > 10) 159669401Seric syslog(LOG_WARNING, 159769401Seric "nisplus_getcanonname: Lookup error, expected 1 entry, got (%d)", 159869401Seric count); 159969401Seric #endif 160069401Seric 160169401Seric /* ignore second entry */ 160269401Seric if (tTd(38, 20)) 160369401Seric printf("nisplus_getcanoname(%s), got %d entries, addtional entries ignores\n", name); 160469401Seric } 160569401Seric 160669401Seric if (tTd(38, 20)) 160769401Seric printf("nisplus_getcanoname(%s), found in directory \"%s\"\n", 160869401Seric name, (NIS_RES_OBJECT(result))->zo_domain); 160969401Seric 161069401Seric 161169401Seric vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 161269401Seric vsize = strlen(vp); 161369401Seric if (tTd(38, 20)) 161469401Seric printf("nisplus_getcanonname(%s), found %s\n", 161569401Seric name, vp); 1616*69703Seric if (strchr(vp, '.') != NULL) 1617*69703Seric { 161869636Seric domain = ""; 1619*69703Seric } 1620*69703Seric else 1621*69703Seric { 1622*69703Seric domain = macvalue('m', CurEnv); 1623*69703Seric if (domain == NULL) 1624*69703Seric domain = ""; 1625*69703Seric } 162669636Seric if (hbsize > vsize + (int) strlen(domain) + 1) 162769401Seric { 162869636Seric if (domain[0] == '\0') 162969636Seric strcpy(name, vp); 163069636Seric else 163169636Seric sprintf(name, "%s.%s", vp, domain); 163269401Seric *statp = EX_OK; 163369401Seric } 163469401Seric else 163569401Seric *statp = EX_NOHOST; 163669401Seric nis_freeresult(result); 163769401Seric return TRUE; 163869401Seric } 163969401Seric else 164069401Seric { 164169401Seric if (result->status == NIS_NOTFOUND) 164269401Seric *statp = EX_NOHOST; 164369401Seric else if (result->status == NIS_TRYAGAIN) 164469401Seric *statp = EX_TEMPFAIL; 164569401Seric else 164669401Seric *statp = EX_UNAVAILABLE; 164769401Seric } 164869401Seric if (tTd(38, 20)) 164969401Seric printf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 165069401Seric name, result->status, *statp); 165169401Seric nis_freeresult(result); 165269401Seric return FALSE; 165369401Seric } 165469401Seric 165569401Seric 165668350Seric char * 165768350Seric nisplus_default_domain() 165868350Seric { 165968528Seric static char default_domain[MAXNAME + 1] = ""; 166068350Seric char *p; 166168350Seric 166268350Seric if (default_domain[0] != '\0') 166368350Seric return(default_domain); 166468350Seric 166568458Seric p = nis_local_directory(); 166668350Seric strcpy(default_domain, p); 166768458Seric return default_domain; 166868350Seric } 166968350Seric 167068350Seric #endif /* NISPLUS */ 167167848Seric /* 167268350Seric ** HESIOD Modules 167368350Seric */ 167468350Seric 167568350Seric #ifdef HESIOD 167668350Seric 167768350Seric #include <hesiod.h> 167868350Seric 167968350Seric char * 168068350Seric hes_map_lookup(map, name, av, statp) 168168350Seric MAP *map; 168268350Seric char *name; 168368350Seric char **av; 168468350Seric int *statp; 168568350Seric { 168668350Seric char **hp; 168768350Seric int i; 168868350Seric 168968350Seric if (tTd(38, 20)) 169068350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 169168350Seric 169269688Seric if (name[0] == '\\') 169369688Seric { 169469688Seric char *np; 169569688Seric int nl; 169669688Seric char nbuf[MAXNAME]; 169769688Seric 169869688Seric nl = strlen(name); 169969688Seric if (nl < sizeof nbuf - 1) 170069688Seric np = nbuf; 170169688Seric else 170269688Seric np = xalloc(strlen(name) + 2); 170369688Seric np[0] = '\\'; 170469688Seric strcpy(&np[1], name); 170569688Seric hp = hes_resolve(np, map->map_file); 170669688Seric if (np != nbuf) 170769688Seric free(np); 170869688Seric } 170969688Seric else 171069688Seric { 171169688Seric hp = hes_resolve(name, map->map_file); 171269688Seric } 171369623Seric if (hp == NULL || hp[0] == NULL) 171468350Seric return NULL; 171568350Seric 171669623Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 171769623Seric return map_rewrite(map, name, strlen(name), NULL); 171869623Seric else 171969623Seric return map_rewrite(map, hp[0], strlen(hp[0]), av); 172068350Seric } 172168350Seric 172268350Seric #endif 172368350Seric /* 172468350Seric ** NeXT NETINFO Modules 172568350Seric */ 172668350Seric 172768350Seric #ifdef NETINFO 172868350Seric 172968350Seric #define NETINFO_DEFAULT_DIR "/aliases" 173068350Seric #define NETINFO_DEFAULT_PROPERTY "members" 173168350Seric 173268350Seric 173368350Seric /* 173468350Seric ** NI_MAP_OPEN -- open NetInfo Aliases 173568350Seric */ 173668350Seric 173768350Seric bool 173868350Seric ni_map_open(map, mode) 173968350Seric MAP *map; 174068350Seric int mode; 174168350Seric { 174268350Seric char *p; 174368350Seric 174468350Seric if (tTd(38, 20)) 174568350Seric printf("ni_map_open: %s\n", map->map_file); 174668350Seric 174768350Seric if (*map->map_file == '\0') 174868350Seric map->map_file = NETINFO_DEFAULT_DIR; 174968350Seric 175068350Seric if (map->map_valcolnm == NULL) 175168350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 175268350Seric 175368350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 175468350Seric map->map_coldelim = ','; 175568350Seric 175668350Seric return TRUE; 175768350Seric } 175868350Seric 175968350Seric 176068350Seric /* 176168350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 176268350Seric */ 176368350Seric 176468350Seric char * 176568350Seric ni_map_lookup(map, name, av, statp) 176668350Seric MAP *map; 176768350Seric char *name; 176868350Seric char **av; 176968350Seric int *statp; 177068350Seric { 177168350Seric char *res; 177268350Seric char *propval; 177368350Seric extern char *ni_propval(); 177468350Seric 177568350Seric if (tTd(38, 20)) 177668350Seric printf("ni_map_lookup(%s, %s)\n", 177768350Seric map->map_mname, name); 177868350Seric 177968350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 178068350Seric map->map_valcolnm, map->map_coldelim); 178168350Seric 178268350Seric if (propval == NULL) 178368350Seric return NULL; 178468350Seric 178568350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 178668350Seric res = map_rewrite(map, name, strlen(name), NULL); 178768350Seric else 178868350Seric res = map_rewrite(map, propval, strlen(propval), av); 178968350Seric free(propval); 179068350Seric return res; 179168350Seric } 179268350Seric 179368350Seric #endif 179468350Seric /* 179568350Seric ** TEXT (unindexed text file) Modules 179668350Seric ** 179768350Seric ** This code donated by Sun Microsystems. 179868350Seric */ 179968350Seric 180068350Seric 180168350Seric /* 180268350Seric ** TEXT_MAP_OPEN -- open text table 180368350Seric */ 180468350Seric 180568350Seric bool 180668350Seric text_map_open(map, mode) 180768350Seric MAP *map; 180868350Seric int mode; 180968350Seric { 181068350Seric struct stat sbuf; 181168350Seric 181268350Seric if (tTd(38, 2)) 181368350Seric printf("text_map_open(%s, %s, %d)\n", 181468350Seric map->map_mname, map->map_file, mode); 181568350Seric 181668350Seric if (mode != O_RDONLY) 181768350Seric { 181868350Seric errno = ENODEV; 181968350Seric return FALSE; 182068350Seric } 182168350Seric 182268350Seric if (*map->map_file == '\0') 182368350Seric { 182468350Seric if (tTd(38, 2)) 182568350Seric printf("text_map_open: file name required\n"); 182668350Seric return FALSE; 182768350Seric } 182868350Seric 182968350Seric if (map->map_file[0] != '/') 183068350Seric { 183168350Seric if (tTd(38, 2)) 183268350Seric printf("text_map_open(%s): file name must be fully qualified\n", 183368350Seric map->map_file); 183468350Seric return FALSE; 183568350Seric } 183668350Seric /* check to see if this map actually accessable */ 183768350Seric if (access(map->map_file, R_OK) <0) 183868350Seric return FALSE; 183968350Seric 184068350Seric /* check to see if this map actually exist */ 184168350Seric if (stat(map->map_file, &sbuf) <0) 184268350Seric { 184368350Seric if (tTd(38, 2)) 184468350Seric printf("text_map_open(%s): can not stat %s\n", 184568350Seric map->map_file, map->map_file); 184668350Seric return FALSE; 184768350Seric } 184868350Seric 184968350Seric if (!S_ISREG(sbuf.st_mode)) 185068350Seric { 185168350Seric if (tTd(38, 2)) 185268350Seric printf("text_map_open(%s): %s is not a file\n", 185368350Seric map->map_file, map->map_file); 185468350Seric return FALSE; 185568350Seric } 185668350Seric 185768350Seric if (map->map_keycolnm == NULL) 185868350Seric map->map_keycolno = 0; 185968350Seric else 186068350Seric { 186168350Seric if (!isdigit(*map->map_keycolnm)) 186268350Seric { 186368350Seric if (tTd(38, 2)) 186468350Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 186568350Seric map->map_file, map->map_keycolnm); 186668350Seric return FALSE; 186768350Seric } 186868350Seric map->map_keycolno = atoi(map->map_keycolnm); 186968350Seric } 187068350Seric 187168350Seric if (map->map_valcolnm == NULL) 187268350Seric map->map_valcolno = 0; 187368350Seric else 187468350Seric { 187568350Seric if (!isdigit(*map->map_valcolnm)) 187668350Seric { 187768350Seric if (tTd(38, 2)) 187868350Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 187968350Seric map->map_file, map->map_valcolnm); 188068350Seric return FALSE; 188168350Seric } 188268350Seric map->map_valcolno = atoi(map->map_valcolnm); 188368350Seric } 188468350Seric 188568350Seric if (tTd(38, 2)) 188668350Seric { 188768520Seric printf("text_map_open(%s): delimiter = ", 188868520Seric map->map_file); 188968520Seric if (map->map_coldelim == '\0') 189068520Seric printf("(white space)\n"); 189168520Seric else 189268520Seric printf("%c\n", map->map_coldelim); 189368350Seric } 189468350Seric 189568350Seric return TRUE; 189668350Seric } 189768350Seric 189868350Seric 189968350Seric /* 190068350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 190168350Seric */ 190268350Seric 190368350Seric char * 190468350Seric text_map_lookup(map, name, av, statp) 190568350Seric MAP *map; 190668350Seric char *name; 190768350Seric char **av; 190868350Seric int *statp; 190968350Seric { 191068350Seric char *vp; 191168350Seric auto int vsize; 191268350Seric int buflen; 191368350Seric char search_key[MAXNAME + 1]; 191468350Seric char linebuf[MAXLINE]; 191568350Seric FILE *f; 191668528Seric char buf[MAXNAME + 1]; 191768350Seric char delim; 191868350Seric int key_idx; 191968350Seric bool found_it; 192068350Seric extern char *get_column(); 192168350Seric 192268350Seric 192368350Seric found_it = FALSE; 192468350Seric if (tTd(38, 20)) 192568350Seric printf("text_map_lookup(%s)\n", name); 192668350Seric 192768350Seric buflen = strlen(name); 192868350Seric if (buflen > sizeof search_key - 1) 192968350Seric buflen = sizeof search_key - 1; 193068350Seric bcopy(name, search_key, buflen + 1); 193168350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 193268350Seric makelower(search_key); 193368350Seric 193468350Seric f = fopen(map->map_file, "r"); 193568350Seric if (f == NULL) 193668350Seric { 193768350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 193868350Seric *statp = EX_UNAVAILABLE; 193968350Seric return NULL; 194068350Seric } 194168350Seric key_idx = map->map_keycolno; 194268350Seric delim = map->map_coldelim; 194368350Seric while (fgets(linebuf, MAXLINE, f)) 194468350Seric { 194568350Seric char *lf; 194668350Seric if (linebuf[0] == '#') 194768350Seric continue; /* skip comment line */ 194868350Seric if (lf = strchr(linebuf, '\n')) 194968350Seric *lf = '\0'; 195068350Seric if (!strcasecmp(search_key, 195168350Seric get_column(linebuf, key_idx, delim, buf))) 195268350Seric { 195368350Seric found_it = TRUE; 195468350Seric break; 195568350Seric } 195668350Seric } 195768350Seric fclose(f); 195868350Seric if (!found_it) 195968350Seric { 196068350Seric #ifdef MAP_EXIT_STAT 196168350Seric *statp = EX_NOTFOUND; 196268350Seric #endif 196368350Seric return(NULL); 196468350Seric } 196568350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 196668350Seric vsize = strlen(vp); 196768350Seric #ifdef MAP_EXIT_STAT 196868350Seric *statp = EX_OK; 196968350Seric #endif 197068350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 197168350Seric return map_rewrite(map, name, strlen(name), NULL); 197268350Seric else 197368350Seric return map_rewrite(map, vp, vsize, av); 197468350Seric } 197569401Seric 197669401Seric 197769401Seric /* 197869401Seric ** TEXT_GETCANONNAME -- look up canonical name in hosts file 197969401Seric */ 198069401Seric 198169401Seric bool 198269401Seric text_getcanonname(name, hbsize, statp) 198369401Seric char *name; 198469401Seric int hbsize; 198569401Seric int *statp; 198669401Seric { 198769401Seric int buflen; 198869401Seric int key_idx; 198969401Seric char *cname; 199069401Seric bool found; 199169401Seric char *domain; 199269401Seric FILE *f; 199369401Seric char linebuf[MAXLINE]; 199469401Seric char cbuf[MAXNAME + 1]; 199569401Seric char buf[MAXNAME + 1]; 199669401Seric extern char *get_column(); 199769401Seric 199869401Seric shorten_hostname(name); 199969401Seric 200069401Seric /* we only accept single token search key */ 200169401Seric if (strchr(name, '.') != NULL) 200269401Seric { 200369401Seric *statp = EX_NOHOST; 200469401Seric return FALSE; 200569401Seric } 200669401Seric 200769401Seric found = FALSE; 200869401Seric 200969401Seric f = fopen(HostsFile, "r"); 201069401Seric if (f == NULL) 201169401Seric { 201269401Seric #ifdef MAP_EXIT_STAT 201369401Seric *statp = EX_UNAVAILABLE; 201469401Seric #endif 201569401Seric return FALSE; 201669401Seric } 201769401Seric while (!found && fgets(linebuf, MAXLINE, f) != NULL) 201869401Seric { 201969401Seric char *p; 202069401Seric 202169401Seric if (linebuf[0] == '#') 202269401Seric continue; 202369401Seric if ((p = strchr(linebuf, '\n')) != NULL) 202469401Seric *p = '\0'; 202569663Seric cname = get_column(linebuf, 1, '\0', cbuf); 202669401Seric if (cname != NULL && strcasecmp(name, cname) == 0) 202769401Seric { 202869401Seric found = TRUE; 202969401Seric break; 203069401Seric } 203169401Seric 203269401Seric key_idx = 2; 203369663Seric while ((p = get_column(linebuf, key_idx, '\0', buf)) != NULL) 203469401Seric { 203569401Seric if (strcasecmp(name, p) == 0) 203669401Seric { 203769401Seric found = TRUE; 203869401Seric break; 203969401Seric } 204069401Seric key_idx++; 204169401Seric } 204269401Seric } 204369401Seric fclose(f); 204469401Seric if (!found) 204569401Seric { 204669401Seric *statp = EX_NOHOST; 204769401Seric return FALSE; 204869401Seric } 204969401Seric 205069401Seric if (hbsize >= strlen(cname)) 205169401Seric { 205269401Seric strcpy(name, cname); 205369401Seric *statp = EX_OK; 205469401Seric return TRUE; 205569401Seric } 205669401Seric *statp = EX_UNAVAILABLE; 205769401Seric return FALSE; 205869401Seric } 205968350Seric /* 206060089Seric ** STAB (Symbol Table) Modules 206160089Seric */ 206260089Seric 206360089Seric 206460089Seric /* 206560207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 206660089Seric */ 206760089Seric 206860089Seric char * 206961707Seric stab_map_lookup(map, name, av, pstat) 207060089Seric register MAP *map; 207160089Seric char *name; 207261707Seric char **av; 207361707Seric int *pstat; 207460089Seric { 207560089Seric register STAB *s; 207660089Seric 207760537Seric if (tTd(38, 20)) 207868350Seric printf("stab_lookup(%s, %s)\n", 207968350Seric map->map_mname, name); 208060089Seric 208160089Seric s = stab(name, ST_ALIAS, ST_FIND); 208260089Seric if (s != NULL) 208360089Seric return (s->s_alias); 208460089Seric return (NULL); 208560089Seric } 208660089Seric 208760089Seric 208860089Seric /* 208960207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 209060089Seric */ 209160089Seric 209260089Seric void 209360089Seric stab_map_store(map, lhs, rhs) 209460089Seric register MAP *map; 209560089Seric char *lhs; 209660089Seric char *rhs; 209760089Seric { 209860089Seric register STAB *s; 209960089Seric 210060089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 210160089Seric s->s_alias = newstr(rhs); 210260089Seric } 210360089Seric 210460089Seric 210560089Seric /* 210660207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 210760207Seric ** 210860207Seric ** This is a wierd case -- it is only intended as a fallback for 210960207Seric ** aliases. For this reason, opens for write (only during a 211060207Seric ** "newaliases") always fails, and opens for read open the 211160207Seric ** actual underlying text file instead of the database. 211260089Seric */ 211360089Seric 211460089Seric bool 211560089Seric stab_map_open(map, mode) 211660089Seric register MAP *map; 211760089Seric int mode; 211860089Seric { 211963835Seric FILE *af; 212064284Seric struct stat st; 212163835Seric 212260537Seric if (tTd(38, 2)) 212368350Seric printf("stab_map_open(%s, %s)\n", 212468350Seric map->map_mname, map->map_file); 212560089Seric 212660089Seric if (mode != O_RDONLY) 212760207Seric { 212860207Seric errno = ENODEV; 212960089Seric return FALSE; 213060207Seric } 213160089Seric 213263835Seric af = fopen(map->map_file, "r"); 213363835Seric if (af == NULL) 213463835Seric return FALSE; 213568350Seric readaliases(map, af, FALSE, FALSE); 213664284Seric 213764284Seric if (fstat(fileno(af), &st) >= 0) 213864284Seric map->map_mtime = st.st_mtime; 213963835Seric fclose(af); 214063835Seric 214160089Seric return TRUE; 214260089Seric } 214360089Seric /* 214460089Seric ** Implicit Modules 214556822Seric ** 214660089Seric ** Tries several types. For back compatibility of aliases. 214756822Seric */ 214856822Seric 214960089Seric 215060089Seric /* 215160207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 215260089Seric */ 215360089Seric 215460089Seric char * 215560089Seric impl_map_lookup(map, name, av, pstat) 215660089Seric MAP *map; 215760089Seric char *name; 215856822Seric char **av; 215960089Seric int *pstat; 216056822Seric { 216160537Seric if (tTd(38, 20)) 216268350Seric printf("impl_map_lookup(%s, %s)\n", 216368350Seric map->map_mname, name); 216456822Seric 216560089Seric #ifdef NEWDB 216660207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 216760089Seric return db_map_lookup(map, name, av, pstat); 216860089Seric #endif 216960089Seric #ifdef NDBM 217060207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 217160089Seric return ndbm_map_lookup(map, name, av, pstat); 217260089Seric #endif 217360089Seric return stab_map_lookup(map, name, av, pstat); 217460089Seric } 217560089Seric 217660089Seric /* 217760207Seric ** IMPL_MAP_STORE -- store in open databases 217860089Seric */ 217960089Seric 218060089Seric void 218160089Seric impl_map_store(map, lhs, rhs) 218260089Seric MAP *map; 218360089Seric char *lhs; 218460089Seric char *rhs; 218560089Seric { 218660089Seric #ifdef NEWDB 218760207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 218860089Seric db_map_store(map, lhs, rhs); 218960089Seric #endif 219060089Seric #ifdef NDBM 219160207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 219260089Seric ndbm_map_store(map, lhs, rhs); 219360089Seric #endif 219460089Seric stab_map_store(map, lhs, rhs); 219560089Seric } 219660089Seric 219760089Seric /* 219860089Seric ** IMPL_MAP_OPEN -- implicit database open 219960089Seric */ 220060089Seric 220160089Seric bool 220260089Seric impl_map_open(map, mode) 220360089Seric MAP *map; 220460089Seric int mode; 220560089Seric { 220660089Seric struct stat stb; 220760089Seric 220860537Seric if (tTd(38, 2)) 220968350Seric printf("impl_map_open(%s, %s, %d)\n", 221068350Seric map->map_mname, map->map_file, mode); 221160089Seric 221260089Seric if (stat(map->map_file, &stb) < 0) 221356822Seric { 221460089Seric /* no alias file at all */ 221564718Seric if (tTd(38, 3)) 221664718Seric printf("no map file\n"); 221760089Seric return FALSE; 221856822Seric } 221956822Seric 222060089Seric #ifdef NEWDB 222160207Seric map->map_mflags |= MF_IMPL_HASH; 222260089Seric if (hash_map_open(map, mode)) 222356822Seric { 222464250Seric #if defined(NDBM) && defined(NIS) 222569651Seric if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 222660207Seric #endif 222760207Seric return TRUE; 222860089Seric } 222960207Seric else 223060207Seric map->map_mflags &= ~MF_IMPL_HASH; 223160089Seric #endif 223260089Seric #ifdef NDBM 223360207Seric map->map_mflags |= MF_IMPL_NDBM; 223460089Seric if (ndbm_map_open(map, mode)) 223560089Seric { 223660089Seric return TRUE; 223760089Seric } 223860207Seric else 223960207Seric map->map_mflags &= ~MF_IMPL_NDBM; 224060089Seric #endif 224156822Seric 224264650Seric #if defined(NEWDB) || defined(NDBM) 224360089Seric if (Verbose) 224460089Seric message("WARNING: cannot open alias database %s", map->map_file); 224564964Seric #else 224664964Seric if (mode != O_RDONLY) 224764964Seric usrerr("Cannot rebuild aliases: no database format defined"); 224860207Seric #endif 224960089Seric 225060207Seric return stab_map_open(map, mode); 225156822Seric } 225260089Seric 225360207Seric 225460089Seric /* 225560207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 225660089Seric */ 225760089Seric 225860089Seric void 225960207Seric impl_map_close(map) 226060089Seric MAP *map; 226160089Seric { 226268350Seric if (tTd(38, 20)) 226368350Seric printf("impl_map_close(%s, %s, %x)\n", 226468350Seric map->map_mname, map->map_file, map->map_mflags); 226560089Seric #ifdef NEWDB 226660207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 226760089Seric { 226860207Seric db_map_close(map); 226960207Seric map->map_mflags &= ~MF_IMPL_HASH; 227060089Seric } 227160089Seric #endif 227260089Seric 227360089Seric #ifdef NDBM 227460207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 227560089Seric { 227660207Seric ndbm_map_close(map); 227760207Seric map->map_mflags &= ~MF_IMPL_NDBM; 227860089Seric } 227960089Seric #endif 228060089Seric } 228160207Seric /* 228268350Seric ** User map class. 228368350Seric ** 228468350Seric ** Provides access to the system password file. 228568350Seric */ 228668350Seric 228768350Seric /* 228868350Seric ** USER_MAP_OPEN -- open user map 228968350Seric ** 229068350Seric ** Really just binds field names to field numbers. 229168350Seric */ 229268350Seric 229368350Seric bool 229468350Seric user_map_open(map, mode) 229568350Seric MAP *map; 229668350Seric int mode; 229768350Seric { 229868350Seric if (tTd(38, 2)) 229968350Seric printf("user_map_open(%s)\n", map->map_mname); 230068350Seric 230168350Seric if (mode != O_RDONLY) 230268350Seric { 230368350Seric /* issue a pseudo-error message */ 230468350Seric #ifdef ENOSYS 230568350Seric errno = ENOSYS; 230668350Seric #else 230768350Seric # ifdef EFTYPE 230868350Seric errno = EFTYPE; 230968350Seric # else 231068350Seric errno = ENXIO; 231168350Seric # endif 231268350Seric #endif 231368350Seric return FALSE; 231468350Seric } 231568350Seric if (map->map_valcolnm == NULL) 231668350Seric /* nothing */ ; 231768350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 231868350Seric map->map_valcolno = 1; 231968350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 232068350Seric map->map_valcolno = 2; 232168350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 232268350Seric map->map_valcolno = 3; 232368350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 232468350Seric map->map_valcolno = 4; 232568350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 232668350Seric map->map_valcolno = 5; 232768350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 232868350Seric map->map_valcolno = 6; 232968350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 233068350Seric map->map_valcolno = 7; 233168350Seric else 233268350Seric { 233368350Seric syserr("User map %s: unknown column name %s", 233468350Seric map->map_mname, map->map_valcolnm); 233568350Seric return FALSE; 233668350Seric } 233768350Seric return TRUE; 233868350Seric } 233968350Seric 234068350Seric 234168350Seric /* 234268350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 234368350Seric */ 234468350Seric 234568350Seric char * 234668350Seric user_map_lookup(map, key, av, statp) 234768350Seric MAP *map; 234868350Seric char *key; 234968350Seric char **av; 235068350Seric int *statp; 235168350Seric { 235268350Seric struct passwd *pw; 235368350Seric 235468350Seric if (tTd(38, 20)) 235568350Seric printf("user_map_lookup(%s, %s)\n", 235668350Seric map->map_mname, key); 235768350Seric 235868693Seric pw = sm_getpwnam(key); 235968350Seric if (pw == NULL) 236068350Seric return NULL; 236168350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 236268350Seric return map_rewrite(map, key, strlen(key), NULL); 236368350Seric else 236468350Seric { 236568433Seric char *rwval = NULL; 236668350Seric char buf[30]; 236768350Seric 236868350Seric switch (map->map_valcolno) 236968350Seric { 237068350Seric case 0: 237168350Seric case 1: 237268350Seric rwval = pw->pw_name; 237368350Seric break; 237468350Seric 237568350Seric case 2: 237668350Seric rwval = pw->pw_passwd; 237768350Seric break; 237868350Seric 237968350Seric case 3: 238068350Seric sprintf(buf, "%d", pw->pw_uid); 238168350Seric rwval = buf; 238268350Seric break; 238368350Seric 238468350Seric case 4: 238568350Seric sprintf(buf, "%d", pw->pw_gid); 238668350Seric rwval = buf; 238768350Seric break; 238868350Seric 238968350Seric case 5: 239068350Seric rwval = pw->pw_gecos; 239168350Seric break; 239268350Seric 239368350Seric case 6: 239468350Seric rwval = pw->pw_dir; 239568350Seric break; 239668350Seric 239768350Seric case 7: 239868350Seric rwval = pw->pw_shell; 239968350Seric break; 240068350Seric } 240168350Seric return map_rewrite(map, rwval, strlen(rwval), av); 240268350Seric } 240368350Seric } 240468350Seric /* 240568350Seric ** BESTMX -- find the best MX for a name 240668350Seric ** 240768350Seric ** This is really a hack, but I don't see any obvious way 240868350Seric ** to generalize it at the moment. 240968350Seric */ 241068350Seric 241168350Seric #if NAMED_BIND 241268350Seric 241368350Seric char * 241468350Seric bestmx_map_lookup(map, name, av, statp) 241568350Seric MAP *map; 241668350Seric char *name; 241768350Seric char **av; 241868350Seric int *statp; 241968350Seric { 242068350Seric int nmx; 242168350Seric auto int rcode; 242268350Seric char *mxhosts[MAXMXHOSTS + 1]; 242368350Seric 242468350Seric nmx = getmxrr(name, mxhosts, FALSE, &rcode); 242568350Seric if (nmx <= 0) 242668350Seric return NULL; 242768350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 242868350Seric return map_rewrite(map, name, strlen(name), NULL); 242968350Seric else 243068350Seric return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 243168350Seric } 243268350Seric 243368350Seric #endif 243468350Seric /* 243569453Seric ** Program map type. 243669453Seric ** 243769453Seric ** This provides access to arbitrary programs. It should be used 243869453Seric ** only very sparingly, since there is no way to bound the cost 243969453Seric ** of invoking an arbitrary program. 244069453Seric */ 244169453Seric 244269453Seric char * 244369453Seric prog_map_lookup(map, name, av, statp) 244469453Seric MAP *map; 244569453Seric char *name; 244669453Seric char **av; 244769453Seric int *statp; 244869453Seric { 244969453Seric int i; 245069453Seric register char *p; 245169453Seric int fd; 245269453Seric auto pid_t pid; 245369453Seric char *argv[MAXPV + 1]; 245469453Seric char buf[MAXLINE]; 245569453Seric 245669453Seric if (tTd(38, 20)) 245769453Seric printf("prog_map_lookup(%s, %s) %s\n", 245869453Seric map->map_mname, name, map->map_file); 245969453Seric 246069453Seric i = 0; 246169453Seric argv[i++] = map->map_file; 246269453Seric strcpy(buf, map->map_rebuild); 246369453Seric for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 246469453Seric { 246569453Seric if (i >= MAXPV - 1) 246669453Seric break; 246769453Seric argv[i++] = p; 246869453Seric } 246969453Seric argv[i++] = name; 247069453Seric argv[i] = NULL; 247169453Seric pid = prog_open(argv, &fd, CurEnv); 247269453Seric if (pid < 0) 247369453Seric { 247469453Seric if (tTd(38, 9)) 247569453Seric printf("prog_map_lookup(%s) failed (%s) -- closing", 247669453Seric map->map_mname, errstring(errno)); 247769453Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 247869453Seric return NULL; 247969453Seric } 248069453Seric i = read(fd, buf, sizeof buf - 1); 248169453Seric if (i <= 0 && tTd(38, 2)) 248269453Seric printf("prog_map_lookup(%s): read error %s\n", 248369562Seric map->map_mname, errstring(errno)); 248469453Seric if (i > 0) 248569453Seric { 248669453Seric char *rval; 248769453Seric 248869453Seric buf[i] = '\0'; 248969453Seric p = strchr(buf, '\n'); 249069453Seric if (p != NULL) 249169453Seric *p = '\0'; 249269453Seric 249369453Seric /* collect the return value */ 249469453Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 249569453Seric rval = map_rewrite(map, name, strlen(name), NULL); 249669453Seric else 249769453Seric rval = map_rewrite(map, buf, strlen(buf), NULL); 249869453Seric 249969453Seric /* now flush any additional output */ 250069453Seric while ((i = read(fd, buf, sizeof buf)) > 0) 250169453Seric continue; 250269453Seric close(fd); 250369453Seric 250469453Seric /* and wait for the process to terminate */ 250569453Seric *statp = waitfor(pid); 250669453Seric 250769453Seric return rval; 250869453Seric } 250969453Seric 251069453Seric close(fd); 251169453Seric *statp = waitfor(pid); 251269453Seric return NULL; 251369453Seric } 251469453Seric /* 251568350Seric ** Sequenced map type. 251668350Seric ** 251768350Seric ** Tries each map in order until something matches, much like 251868350Seric ** implicit. Stores go to the first map in the list that can 251968350Seric ** support storing. 252068350Seric ** 252168350Seric ** This is slightly unusual in that there are two interfaces. 252268350Seric ** The "sequence" interface lets you stack maps arbitrarily. 252368350Seric ** The "switch" interface builds a sequence map by looking 252468350Seric ** at a system-dependent configuration file such as 252568350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 252668350Seric ** 252768350Seric ** We don't need an explicit open, since all maps are 252868350Seric ** opened during startup, including underlying maps. 252968350Seric */ 253068350Seric 253168350Seric /* 253268350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 253368350Seric */ 253468350Seric 253568350Seric bool 253668350Seric seq_map_parse(map, ap) 253768350Seric MAP *map; 253868350Seric char *ap; 253968350Seric { 254068350Seric int maxmap; 254168350Seric 254268350Seric if (tTd(38, 2)) 254368350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 254468350Seric maxmap = 0; 254568350Seric while (*ap != '\0') 254668350Seric { 254768350Seric register char *p; 254868350Seric STAB *s; 254968350Seric 255068350Seric /* find beginning of map name */ 255168350Seric while (isascii(*ap) && isspace(*ap)) 255268350Seric ap++; 255368350Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 255468350Seric continue; 255568350Seric if (*p != '\0') 255668350Seric *p++ = '\0'; 255768350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 255868350Seric p++; 255968350Seric if (*ap == '\0') 256068350Seric { 256168350Seric ap = p; 256268350Seric continue; 256368350Seric } 256468350Seric s = stab(ap, ST_MAP, ST_FIND); 256568350Seric if (s == NULL) 256668350Seric { 256768350Seric syserr("Sequence map %s: unknown member map %s", 256868350Seric map->map_mname, ap); 256968350Seric } 257068350Seric else if (maxmap == MAXMAPSTACK) 257168350Seric { 257268350Seric syserr("Sequence map %s: too many member maps (%d max)", 257368350Seric map->map_mname, MAXMAPSTACK); 257468350Seric maxmap++; 257568350Seric } 257668350Seric else if (maxmap < MAXMAPSTACK) 257768350Seric { 257868350Seric map->map_stack[maxmap++] = &s->s_map; 257968350Seric } 258068350Seric ap = p; 258168350Seric } 258268350Seric return TRUE; 258368350Seric } 258468350Seric 258568350Seric 258668350Seric /* 258768350Seric ** SWITCH_MAP_OPEN -- open a switched map 258868350Seric ** 258968350Seric ** This looks at the system-dependent configuration and builds 259068350Seric ** a sequence map that does the same thing. 259168350Seric ** 259268350Seric ** Every system must define a switch_map_find routine in conf.c 259368350Seric ** that will return the list of service types associated with a 259468350Seric ** given service class. 259568350Seric */ 259668350Seric 259768350Seric bool 259868350Seric switch_map_open(map, mode) 259968350Seric MAP *map; 260068350Seric int mode; 260168350Seric { 260268350Seric int mapno; 260368350Seric int nmaps; 260468350Seric char *maptype[MAXMAPSTACK]; 260568350Seric 260668350Seric if (tTd(38, 2)) 260768350Seric printf("switch_map_open(%s, %s, %d)\n", 260868350Seric map->map_mname, map->map_file, mode); 260968350Seric 261068350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 261168350Seric if (tTd(38, 19)) 261268350Seric { 261368350Seric printf("\tswitch_map_find => %d\n", nmaps); 261468350Seric for (mapno = 0; mapno < nmaps; mapno++) 261568350Seric printf("\t\t%s\n", maptype[mapno]); 261668350Seric } 261768350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 261868350Seric return FALSE; 261968350Seric 262068350Seric for (mapno = 0; mapno < nmaps; mapno++) 262168350Seric { 262268350Seric register STAB *s; 262368350Seric char nbuf[MAXNAME + 1]; 262468350Seric 262568350Seric if (maptype[mapno] == NULL) 262668350Seric continue; 262768350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 262868350Seric s = stab(nbuf, ST_MAP, ST_FIND); 262968350Seric if (s == NULL) 263068350Seric { 263168350Seric syserr("Switch map %s: unknown member map %s", 263268350Seric map->map_mname, nbuf); 263368350Seric } 263468350Seric else 263568350Seric { 263668350Seric map->map_stack[mapno] = &s->s_map; 263768350Seric if (tTd(38, 4)) 263868350Seric printf("\tmap_stack[%d] = %s:%s\n", 263968350Seric mapno, s->s_map.map_class->map_cname, 264068350Seric nbuf); 264168350Seric } 264268350Seric } 264368350Seric return TRUE; 264468350Seric } 264568350Seric 264668350Seric 264768350Seric /* 264868350Seric ** SEQ_MAP_CLOSE -- close all underlying maps 264968350Seric */ 265068350Seric 265168350Seric seq_map_close(map) 265268350Seric MAP *map; 265368350Seric { 265468350Seric int mapno; 265568350Seric 265668350Seric if (tTd(38, 20)) 265768350Seric printf("seq_map_close(%s)\n", map->map_mname); 265868350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 265968350Seric { 266068350Seric MAP *mm = map->map_stack[mapno]; 266168350Seric 266268350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 266368350Seric continue; 266468350Seric mm->map_class->map_close(mm); 266568798Seric mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 266668350Seric } 266768350Seric } 266868350Seric 266968350Seric 267068350Seric /* 267168350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 267268350Seric */ 267368350Seric 267468350Seric char * 267568350Seric seq_map_lookup(map, key, args, pstat) 267668350Seric MAP *map; 267768350Seric char *key; 267868350Seric char **args; 267968350Seric int *pstat; 268068350Seric { 268168350Seric int mapno; 268268350Seric int mapbit = 0x01; 268368350Seric 268468350Seric if (tTd(38, 20)) 268568350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 268668350Seric 268768350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 268868350Seric { 268968350Seric MAP *mm = map->map_stack[mapno]; 269068350Seric int stat = 0; 269168350Seric char *rv; 269268350Seric 269368350Seric if (mm == NULL) 269468350Seric continue; 269568350Seric if (!bitset(MF_OPEN, mm->map_mflags)) 269668350Seric { 269768350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 269868350Seric { 269968350Seric *pstat = EX_UNAVAILABLE; 270068350Seric return NULL; 270168350Seric } 270268350Seric continue; 270368350Seric } 270468350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 270568350Seric if (rv != NULL) 270668350Seric return rv; 270768350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 270868350Seric return NULL; 270968350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 271068350Seric { 271168350Seric *pstat = stat; 271268350Seric return NULL; 271368350Seric } 271468350Seric } 271568350Seric return NULL; 271668350Seric } 271768350Seric 271868350Seric 271968350Seric /* 272068350Seric ** SEQ_MAP_STORE -- sequenced map store 272168350Seric */ 272268350Seric 272368350Seric void 272468350Seric seq_map_store(map, key, val) 272568350Seric MAP *map; 272668350Seric char *key; 272768350Seric char *val; 272868350Seric { 272968350Seric int mapno; 273068350Seric 273168350Seric if (tTd(38, 12)) 273268350Seric printf("seq_map_store(%s, %s, %s)\n", 273368350Seric map->map_mname, key, val); 273468350Seric 273568350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 273668350Seric { 273768350Seric MAP *mm = map->map_stack[mapno]; 273868350Seric 273968350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 274068350Seric continue; 274168350Seric 274268350Seric mm->map_class->map_store(mm, key, val); 274368350Seric return; 274468350Seric } 274568350Seric syserr("seq_map_store(%s, %s, %s): no writable map", 274668350Seric map->map_mname, key, val); 274768350Seric } 274868350Seric /* 274969401Seric ** GETCANONNAME -- look up name using service switch 275069401Seric ** 275169401Seric ** Parameters: 275269401Seric ** host -- the host name to look up. 275369401Seric ** hbsize -- the size of the host buffer. 275469401Seric ** trymx -- if set, try MX records. 275569401Seric ** 275669401Seric ** Returns: 275769401Seric ** TRUE -- if the host was found. 275869401Seric ** FALSE -- otherwise. 275969401Seric */ 276069401Seric 276169401Seric bool 276269401Seric getcanonname(host, hbsize, trymx) 276369401Seric char *host; 276469401Seric int hbsize; 276569401Seric bool trymx; 276669401Seric { 276769401Seric int nmaps; 276869401Seric int mapno; 276969401Seric bool found = FALSE; 277069401Seric auto int stat; 277169401Seric char *maptype[MAXMAPSTACK]; 277269401Seric short mapreturn[MAXMAPACTIONS]; 277369401Seric extern int h_errno; 277469401Seric 277569401Seric nmaps = switch_map_find("hosts", maptype, mapreturn); 277669401Seric for (mapno = 0; mapno < nmaps; mapno++) 277769401Seric { 277869401Seric int i; 277969401Seric 278069401Seric if (tTd(38, 20)) 278169401Seric printf("getcanonname(%s), trying %s\n", 278269401Seric host, maptype[mapno]); 278369401Seric if (strcmp("files", maptype[mapno]) == 0) 278469401Seric found = text_getcanonname(host, hbsize, &stat); 278569401Seric #ifdef NIS 278669401Seric else if (strcmp("nis", maptype[mapno]) == 0) 278769401Seric found = nis_getcanonname(host, hbsize, &stat); 278869401Seric #endif 278969401Seric #ifdef NISPLUS 279069401Seric else if (strcmp("nisplus", maptype[mapno]) == 0) 279169401Seric found = nisplus_getcanonname(host, hbsize, &stat); 279269401Seric #endif 279369401Seric #if NAMED_BIND 279469401Seric else if (strcmp("dns", maptype[mapno]) == 0) 279569401Seric found = dns_getcanonname(host, hbsize, trymx, &stat); 279669401Seric #endif 279769401Seric else 279869401Seric { 279969401Seric found = FALSE; 280069401Seric stat = EX_UNAVAILABLE; 280169401Seric } 280269401Seric if (found) 280369401Seric break; 280469401Seric 280569401Seric /* see if we should continue */ 280669401Seric if (stat == EX_TEMPFAIL) 280769401Seric i = MA_TRYAGAIN; 280869401Seric else if (stat == EX_NOHOST) 280969401Seric i = MA_NOTFOUND; 281069401Seric else 281169401Seric i = MA_UNAVAIL; 281269401Seric if (bitset(1 << mapno, mapreturn[i])) 281369401Seric break; 281469401Seric } 281569401Seric 281669401Seric if (found) 281769401Seric { 281869401Seric char *d; 281969401Seric 282069401Seric if (tTd(38, 20)) 282169401Seric printf("getcanonname(%s), found\n", host); 282269401Seric 282369401Seric /* 282469401Seric ** If returned name is still single token, compensate 282569401Seric ** by tagging on $m. This is because some sites set 282669401Seric ** up their DNS or NIS databases wrong. 282769401Seric */ 282869401Seric 282969401Seric if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 283069401Seric { 283169401Seric d = macvalue('m', CurEnv); 283269401Seric if (d != NULL && 283369401Seric hbsize > (int) (strlen(host) + strlen(d) + 1)) 283469401Seric { 283569401Seric if (host[strlen(host) - 1] != '.') 283669401Seric strcat(host, "."); 283769401Seric strcat(host, d); 283869401Seric } 283969401Seric else 284069401Seric { 284169401Seric return FALSE; 284269401Seric } 284369401Seric } 284469401Seric return TRUE; 284569401Seric } 284669401Seric 284769401Seric if (tTd(38, 20)) 284869401Seric printf("getcanonname(%s), failed, stat=%d\n", host, stat); 284969401Seric 285069401Seric #if NAMED_BIND 285169401Seric if (stat == EX_NOHOST) 285269401Seric h_errno = HOST_NOT_FOUND; 285369401Seric else 285469401Seric h_errno = TRY_AGAIN; 285569401Seric #endif 285669401Seric 285769401Seric return FALSE; 285869401Seric } 285969401Seric /* 286060207Seric ** NULL stubs 286160089Seric */ 286260089Seric 286360207Seric bool 286460207Seric null_map_open(map, mode) 286560089Seric MAP *map; 286660207Seric int mode; 286760089Seric { 286860207Seric return TRUE; 286960089Seric } 287060089Seric 287160207Seric void 287260207Seric null_map_close(map) 287360207Seric MAP *map; 287460089Seric { 287560207Seric return; 287660207Seric } 287760089Seric 287860207Seric void 287960207Seric null_map_store(map, key, val) 288060207Seric MAP *map; 288160207Seric char *key; 288260207Seric char *val; 288360089Seric { 288460207Seric return; 288560089Seric } 288668350Seric 288768350Seric 288868350Seric /* 288968350Seric ** BOGUS stubs 289068350Seric */ 289168350Seric 289268350Seric char * 289368350Seric bogus_map_lookup(map, key, args, pstat) 289468350Seric MAP *map; 289568350Seric char *key; 289668350Seric char **args; 289768350Seric int *pstat; 289868350Seric { 289968350Seric *pstat = EX_TEMPFAIL; 290068350Seric return NULL; 290168350Seric } 290268350Seric 290368350Seric MAPCLASS BogusMapClass = 290468350Seric { 290568350Seric "bogus-map", NULL, 0, 290668350Seric NULL, bogus_map_lookup, null_map_store, 290768350Seric null_map_open, null_map_close, 290868350Seric }; 2909