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*69780Seric static char sccsid[] = "@(#)map.c 8.71 (Berkeley) 05/30/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 12769703Seric case 'q': 12869703Seric map->map_mflags |= MF_KEEPQUOTES; 12969703Seric break; 13069703Seric 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 35369748Seric void 35460537Seric initmaps(rebuild, e) 35560537Seric bool rebuild; 35660537Seric register ENVELOPE *e; 35760537Seric { 35860537Seric extern void map_init(); 35960537Seric 36064671Seric #ifdef XDEBUG 36164671Seric checkfd012("entering initmaps"); 36264671Seric #endif 36360537Seric CurEnv = e; 36465085Seric if (rebuild) 36565085Seric { 36665085Seric stabapply(map_init, 1); 36765085Seric stabapply(map_init, 2); 36865085Seric } 36965085Seric else 37065085Seric { 37165085Seric stabapply(map_init, 0); 37265085Seric } 37364671Seric #ifdef XDEBUG 37464671Seric checkfd012("exiting initmaps"); 37564671Seric #endif 37660537Seric } 37760537Seric 37860537Seric void 37960537Seric map_init(s, rebuild) 38060537Seric register STAB *s; 38160537Seric int rebuild; 38260537Seric { 38360537Seric register MAP *map; 38460537Seric 38560537Seric /* has to be a map */ 38660537Seric if (s->s_type != ST_MAP) 38760537Seric return; 38860537Seric 38960537Seric map = &s->s_map; 39060537Seric if (!bitset(MF_VALID, map->map_mflags)) 39160537Seric return; 39260537Seric 39360537Seric if (tTd(38, 2)) 39468350Seric printf("map_init(%s:%s, %s, %d)\n", 39564690Seric map->map_class->map_cname == NULL ? "NULL" : 39664690Seric map->map_class->map_cname, 39768350Seric map->map_mname == NULL ? "NULL" : map->map_mname, 39865085Seric map->map_file == NULL ? "NULL" : map->map_file, 39965085Seric rebuild); 40060537Seric 40165085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && 40265085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) 40365085Seric { 40465085Seric if (tTd(38, 3)) 40565085Seric printf("\twrong pass\n"); 40665085Seric return; 40765085Seric } 40865085Seric 40960537Seric /* if already open, close it (for nested open) */ 41060537Seric if (bitset(MF_OPEN, map->map_mflags)) 41160537Seric { 41260537Seric map->map_class->map_close(map); 41360537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 41460537Seric } 41560537Seric 41665085Seric if (rebuild == 2) 41760537Seric { 41865085Seric rebuildaliases(map, FALSE); 41960537Seric } 42060537Seric else 42160537Seric { 42260537Seric if (map->map_class->map_open(map, O_RDONLY)) 42360537Seric { 42460537Seric if (tTd(38, 4)) 42568350Seric printf("\t%s:%s %s: valid\n", 42664690Seric map->map_class->map_cname == NULL ? "NULL" : 42764690Seric map->map_class->map_cname, 42868350Seric map->map_mname == NULL ? "NULL" : 42968350Seric map->map_mname, 43064690Seric map->map_file == NULL ? "NULL" : 43164690Seric map->map_file); 43260537Seric map->map_mflags |= MF_OPEN; 43360537Seric } 43468350Seric else 43568350Seric { 43668350Seric if (tTd(38, 4)) 43768350Seric printf("\t%s:%s %s: invalid: %s\n", 43868350Seric map->map_class->map_cname == NULL ? "NULL" : 43968350Seric map->map_class->map_cname, 44068350Seric map->map_mname == NULL ? "NULL" : 44168350Seric map->map_mname, 44268350Seric map->map_file == NULL ? "NULL" : 44368350Seric map->map_file, 44468350Seric errstring(errno)); 44568350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 44668350Seric { 44768350Seric extern MAPCLASS BogusMapClass; 44868350Seric 44968350Seric map->map_class = &BogusMapClass; 45068350Seric map->map_mflags |= MF_OPEN; 45168350Seric } 45268350Seric } 45360537Seric } 45460537Seric } 45560537Seric /* 45660089Seric ** NDBM modules 45760089Seric */ 45860089Seric 45960089Seric #ifdef NDBM 46060089Seric 46160089Seric /* 46260089Seric ** DBM_MAP_OPEN -- DBM-style map open 46360089Seric */ 46460089Seric 46560089Seric bool 46660089Seric ndbm_map_open(map, mode) 46760089Seric MAP *map; 46860089Seric int mode; 46960089Seric { 47064284Seric register DBM *dbm; 47164284Seric struct stat st; 47260089Seric 47360537Seric if (tTd(38, 2)) 47468350Seric printf("ndbm_map_open(%s, %s, %d)\n", 47568350Seric map->map_mname, map->map_file, mode); 47660089Seric 47760207Seric if (mode == O_RDWR) 47860207Seric mode |= O_CREAT|O_TRUNC; 47960207Seric 48060089Seric /* open the database */ 48160089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 48256822Seric if (dbm == NULL) 48356822Seric { 48464718Seric if (aliaswait(map, ".pag", FALSE)) 48564718Seric return TRUE; 48660207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 48756836Seric syserr("Cannot open DBM database %s", map->map_file); 48856822Seric return FALSE; 48956822Seric } 49060089Seric map->map_db1 = (void *) dbm; 49164964Seric if (mode == O_RDONLY) 49264964Seric { 49364964Seric if (bitset(MF_ALIAS, map->map_mflags) && 49464964Seric !aliaswait(map, ".pag", TRUE)) 49564718Seric return FALSE; 49664964Seric } 49764964Seric else 49864964Seric { 49964964Seric int fd; 50064964Seric 50164964Seric /* exclusive lock for duration of rebuild */ 50264964Seric fd = dbm_dirfno((DBM *) map->map_db1); 50364964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 50464964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 50564964Seric map->map_mflags |= MF_LOCKED; 50664964Seric } 50764718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 50864284Seric map->map_mtime = st.st_mtime; 50956822Seric return TRUE; 51056822Seric } 51160089Seric 51260089Seric 51360089Seric /* 51456822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 51556822Seric */ 51656822Seric 51756822Seric char * 51860089Seric ndbm_map_lookup(map, name, av, statp) 51956822Seric MAP *map; 52060089Seric char *name; 52156822Seric char **av; 52259084Seric int *statp; 52356822Seric { 52456822Seric datum key, val; 52564373Seric int fd; 52660089Seric char keybuf[MAXNAME + 1]; 52756822Seric 52860537Seric if (tTd(38, 20)) 52968350Seric printf("ndbm_map_lookup(%s, %s)\n", 53068350Seric map->map_mname, name); 53160089Seric 53260089Seric key.dptr = name; 53360089Seric key.dsize = strlen(name); 53460207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 53557014Seric { 53660089Seric if (key.dsize > sizeof keybuf - 1) 53760089Seric key.dsize = sizeof keybuf - 1; 53860089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 53960089Seric makelower(keybuf); 54060089Seric key.dptr = keybuf; 54157014Seric } 54264373Seric fd = dbm_dirfno((DBM *) map->map_db1); 54364388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 54464373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 54563753Seric val.dptr = NULL; 54663753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 54763753Seric { 54863753Seric val = dbm_fetch((DBM *) map->map_db1, key); 54963753Seric if (val.dptr != NULL) 55063753Seric map->map_mflags &= ~MF_TRY1NULL; 55163753Seric } 55263753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 55363753Seric { 55456822Seric key.dsize++; 55563753Seric val = dbm_fetch((DBM *) map->map_db1, key); 55663753Seric if (val.dptr != NULL) 55763753Seric map->map_mflags &= ~MF_TRY0NULL; 55863753Seric } 55964388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 56064373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 56156822Seric if (val.dptr == NULL) 56256822Seric return NULL; 56360207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 56463753Seric return map_rewrite(map, name, strlen(name), NULL); 56563753Seric else 56663753Seric return map_rewrite(map, val.dptr, val.dsize, av); 56756822Seric } 56856822Seric 56956822Seric 57056822Seric /* 57160089Seric ** DBM_MAP_STORE -- store a datum in the database 57256822Seric */ 57356822Seric 57460089Seric void 57560089Seric ndbm_map_store(map, lhs, rhs) 57660089Seric register MAP *map; 57760089Seric char *lhs; 57860089Seric char *rhs; 57960089Seric { 58060089Seric datum key; 58160089Seric datum data; 58260089Seric int stat; 58360089Seric 58460537Seric if (tTd(38, 12)) 58568350Seric printf("ndbm_map_store(%s, %s, %s)\n", 58668350Seric map->map_mname, lhs, rhs); 58760089Seric 58860089Seric key.dsize = strlen(lhs); 58960089Seric key.dptr = lhs; 59060089Seric 59160089Seric data.dsize = strlen(rhs); 59260089Seric data.dptr = rhs; 59360089Seric 59460207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 59560089Seric { 59660089Seric key.dsize++; 59760089Seric data.dsize++; 59860089Seric } 59960089Seric 60060089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 60160089Seric if (stat > 0) 60260089Seric { 60368497Seric if (!bitset(MF_APPEND, map->map_mflags)) 60468497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 60568497Seric else 60668497Seric { 60768497Seric static char *buf = NULL; 60868497Seric static int bufsiz = 0; 60968879Seric auto int xstat; 61068497Seric datum old; 61168497Seric 61268879Seric old.dptr = ndbm_map_lookup(map, key.dptr, NULL, &xstat); 61368497Seric if (old.dptr != NULL && *old.dptr != '\0') 61468497Seric { 61568497Seric old.dsize = strlen(old.dptr); 61668497Seric if (data.dsize + old.dsize + 2 > bufsiz) 61768497Seric { 61868497Seric if (buf != NULL) 61968497Seric (void) free(buf); 62068497Seric bufsiz = data.dsize + old.dsize + 2; 62168497Seric buf = xalloc(bufsiz); 62268497Seric } 62368497Seric sprintf(buf, "%s,%s", data.dptr, old.dptr); 62468497Seric data.dsize = data.dsize + old.dsize + 1; 62568497Seric data.dptr = buf; 62668497Seric if (tTd(38, 9)) 62768497Seric printf("ndbm_map_store append=%s\n", data.dptr); 62868497Seric } 62968497Seric } 63060089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 63160089Seric } 63260089Seric if (stat != 0) 63360089Seric syserr("readaliases: dbm put (%s)", lhs); 63460089Seric } 63560089Seric 63660089Seric 63760089Seric /* 63860207Seric ** NDBM_MAP_CLOSE -- close the database 63960089Seric */ 64060089Seric 64160089Seric void 64260089Seric ndbm_map_close(map) 64360089Seric register MAP *map; 64460089Seric { 64566773Seric if (tTd(38, 9)) 64668350Seric printf("ndbm_map_close(%s, %s, %x)\n", 64768350Seric map->map_mname, map->map_file, map->map_mflags); 64866773Seric 64960207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 65060089Seric { 65164250Seric #ifdef NIS 65264075Seric bool inclnull; 65360089Seric char buf[200]; 65460089Seric 65564075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 65664075Seric map->map_mflags &= ~MF_INCLNULL; 65764075Seric 65869651Seric if (strstr(map->map_file, "/yp/") != NULL) 65969651Seric { 66069651Seric (void) sprintf(buf, "%010ld", curtime()); 66169651Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 66260089Seric 66369651Seric (void) gethostname(buf, sizeof buf); 66469651Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 66569651Seric } 66664075Seric 66764075Seric if (inclnull) 66864075Seric map->map_mflags |= MF_INCLNULL; 66960089Seric #endif 67060089Seric 67160089Seric /* write out the distinguished alias */ 67260089Seric ndbm_map_store(map, "@", "@"); 67360089Seric } 67460089Seric dbm_close((DBM *) map->map_db1); 67560089Seric } 67660089Seric 67760089Seric #endif 67860089Seric /* 67960582Seric ** NEWDB (Hash and BTree) Modules 68060089Seric */ 68160089Seric 68260089Seric #ifdef NEWDB 68360089Seric 68460089Seric /* 68560582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 68660582Seric ** 68760582Seric ** These do rather bizarre locking. If you can lock on open, 68860582Seric ** do that to avoid the condition of opening a database that 68960582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 69060582Seric ** there will be a race condition. If opening for read-only, 69160582Seric ** we immediately release the lock to avoid freezing things up. 69260582Seric ** We really ought to hold the lock, but guarantee that we won't 69360582Seric ** be pokey about it. That's hard to do. 69460089Seric */ 69560089Seric 69656822Seric bool 69760089Seric bt_map_open(map, mode) 69856822Seric MAP *map; 69960089Seric int mode; 70056822Seric { 70156822Seric DB *db; 70260228Seric int i; 70360582Seric int omode; 70464373Seric int fd; 70564284Seric struct stat st; 70668528Seric char buf[MAXNAME + 1]; 70756822Seric 70860537Seric if (tTd(38, 2)) 70968350Seric printf("bt_map_open(%s, %s, %d)\n", 71068350Seric map->map_mname, map->map_file, mode); 71160089Seric 71260582Seric omode = mode; 71360582Seric if (omode == O_RDWR) 71460582Seric { 71560582Seric omode |= O_CREAT|O_TRUNC; 71665830Seric #if defined(O_EXLOCK) && HASFLOCK 71760582Seric omode |= O_EXLOCK; 71866843Seric # if !OLD_NEWDB 71960582Seric } 72060582Seric else 72160582Seric { 72260582Seric omode |= O_SHLOCK; 72360582Seric # endif 72460582Seric #endif 72560582Seric } 72660207Seric 72760228Seric (void) strcpy(buf, map->map_file); 72860228Seric i = strlen(buf); 72960228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 73060228Seric (void) strcat(buf, ".db"); 73160582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 73256822Seric if (db == NULL) 73356822Seric { 73464718Seric #ifdef MAYBENEXTRELEASE 73564718Seric if (aliaswait(map, ".db", FALSE)) 73664718Seric return TRUE; 73764718Seric #endif 73860207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 73956836Seric syserr("Cannot open BTREE database %s", map->map_file); 74056822Seric return FALSE; 74156822Seric } 74268350Seric #if !OLD_NEWDB 74364373Seric fd = db->fd(db); 74468778Seric # if defined(O_EXLOCK) && HASFLOCK 74568778Seric if (fd >= 0) 74668778Seric { 74768778Seric if (mode == O_RDONLY) 74868778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 74968778Seric else 75068778Seric map->map_mflags |= MF_LOCKED; 75168778Seric } 75268778Seric # else 75364373Seric if (mode == O_RDWR && fd >= 0) 75464388Seric { 75564388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 75664388Seric map->map_mflags |= MF_LOCKED; 75764388Seric } 75860582Seric # endif 75960582Seric #endif 76060585Seric 76160585Seric /* try to make sure that at least the database header is on disk */ 76260585Seric if (mode == O_RDWR) 76366843Seric #if OLD_NEWDB 76464373Seric (void) db->sync(db); 76564373Seric #else 76660585Seric (void) db->sync(db, 0); 76760585Seric 76864373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 76964284Seric map->map_mtime = st.st_mtime; 77064284Seric #endif 77164284Seric 77260089Seric map->map_db2 = (void *) db; 77360207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 77464718Seric if (!aliaswait(map, ".db", TRUE)) 77564718Seric return FALSE; 77656822Seric return TRUE; 77756822Seric } 77856822Seric 77956822Seric 78056822Seric /* 78156822Seric ** HASH_MAP_INIT -- HASH-style map initialization 78256822Seric */ 78356822Seric 78456822Seric bool 78560089Seric hash_map_open(map, mode) 78656822Seric MAP *map; 78760089Seric int mode; 78856822Seric { 78956822Seric DB *db; 79060228Seric int i; 79160582Seric int omode; 79264373Seric int fd; 79364284Seric struct stat st; 79468528Seric char buf[MAXNAME + 1]; 79556822Seric 79660537Seric if (tTd(38, 2)) 79768350Seric printf("hash_map_open(%s, %s, %d)\n", 79868350Seric map->map_mname, map->map_file, mode); 79960089Seric 80060582Seric omode = mode; 80160582Seric if (omode == O_RDWR) 80260582Seric { 80360582Seric omode |= O_CREAT|O_TRUNC; 80465830Seric #if defined(O_EXLOCK) && HASFLOCK 80560582Seric omode |= O_EXLOCK; 80666843Seric # if !OLD_NEWDB 80760582Seric } 80860582Seric else 80960582Seric { 81060582Seric omode |= O_SHLOCK; 81160582Seric # endif 81260582Seric #endif 81360582Seric } 81460207Seric 81560228Seric (void) strcpy(buf, map->map_file); 81660228Seric i = strlen(buf); 81760228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 81860228Seric (void) strcat(buf, ".db"); 81960582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 82056822Seric if (db == NULL) 82156822Seric { 82264718Seric #ifdef MAYBENEXTRELEASE 82364718Seric if (aliaswait(map, ".db", FALSE)) 82464718Seric return TRUE; 82564718Seric #endif 82660207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 82756836Seric syserr("Cannot open HASH database %s", map->map_file); 82856822Seric return FALSE; 82956822Seric } 83068350Seric #if !OLD_NEWDB 83164373Seric fd = db->fd(db); 83268778Seric # if defined(O_EXLOCK) && HASFLOCK 83368778Seric if (fd >= 0) 83468778Seric { 83568778Seric if (mode == O_RDONLY) 83668778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 83768778Seric else 83868778Seric map->map_mflags |= MF_LOCKED; 83968778Seric } 84068778Seric # else 84164373Seric if (mode == O_RDWR && fd >= 0) 84264388Seric { 84364388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 84464388Seric map->map_mflags |= MF_LOCKED; 84564388Seric } 84660582Seric # endif 84760582Seric #endif 84860585Seric 84960585Seric /* try to make sure that at least the database header is on disk */ 85060585Seric if (mode == O_RDWR) 85166843Seric #if OLD_NEWDB 85264373Seric (void) db->sync(db); 85364373Seric #else 85460585Seric (void) db->sync(db, 0); 85560585Seric 85664373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 85764284Seric map->map_mtime = st.st_mtime; 85864284Seric #endif 85964284Seric 86060089Seric map->map_db2 = (void *) db; 86160207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 86264718Seric if (!aliaswait(map, ".db", TRUE)) 86364718Seric return FALSE; 86456822Seric return TRUE; 86556822Seric } 86656822Seric 86756822Seric 86856822Seric /* 86956822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 87056822Seric */ 87156822Seric 87256822Seric char * 87360089Seric db_map_lookup(map, name, av, statp) 87456822Seric MAP *map; 87560089Seric char *name; 87656822Seric char **av; 87759084Seric int *statp; 87856822Seric { 87956822Seric DBT key, val; 88060422Seric register DB *db = (DB *) map->map_db2; 88160422Seric int st; 88260422Seric int saveerrno; 88364373Seric int fd; 88460089Seric char keybuf[MAXNAME + 1]; 88556822Seric 88660537Seric if (tTd(38, 20)) 88768350Seric printf("db_map_lookup(%s, %s)\n", 88868350Seric map->map_mname, name); 88960089Seric 89060089Seric key.size = strlen(name); 89160089Seric if (key.size > sizeof keybuf - 1) 89260089Seric key.size = sizeof keybuf - 1; 89360089Seric key.data = keybuf; 89460089Seric bcopy(name, keybuf, key.size + 1); 89560207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 89660089Seric makelower(keybuf); 89766843Seric #if !OLD_NEWDB 89864388Seric fd = db->fd(db); 89964388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 90064388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 90160422Seric #endif 90263753Seric st = 1; 90363753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 90463753Seric { 90563753Seric st = db->get(db, &key, &val, 0); 90663753Seric if (st == 0) 90763753Seric map->map_mflags &= ~MF_TRY1NULL; 90863753Seric } 90963753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 91063753Seric { 91163753Seric key.size++; 91263753Seric st = db->get(db, &key, &val, 0); 91363753Seric if (st == 0) 91463753Seric map->map_mflags &= ~MF_TRY0NULL; 91563753Seric } 91660422Seric saveerrno = errno; 91766843Seric #if !OLD_NEWDB 91864388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 91964373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 92060422Seric #endif 92160422Seric if (st != 0) 92260422Seric { 92360422Seric errno = saveerrno; 92460422Seric if (st < 0) 92560422Seric syserr("db_map_lookup: get (%s)", name); 92656822Seric return NULL; 92760422Seric } 92860207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 92963753Seric return map_rewrite(map, name, strlen(name), NULL); 93063753Seric else 93163753Seric return map_rewrite(map, val.data, val.size, av); 93256822Seric } 93356822Seric 93460089Seric 93560089Seric /* 93660089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 93756822Seric */ 93856822Seric 93960089Seric void 94060089Seric db_map_store(map, lhs, rhs) 94160089Seric register MAP *map; 94260089Seric char *lhs; 94360089Seric char *rhs; 94456822Seric { 94560089Seric int stat; 94660089Seric DBT key; 94760089Seric DBT data; 94860089Seric register DB *db = map->map_db2; 94956822Seric 95060537Seric if (tTd(38, 20)) 95168350Seric printf("db_map_store(%s, %s, %s)\n", 95268350Seric map->map_mname, lhs, rhs); 95360089Seric 95460089Seric key.size = strlen(lhs); 95560089Seric key.data = lhs; 95660089Seric 95760089Seric data.size = strlen(rhs); 95860089Seric data.data = rhs; 95960089Seric 96060207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 96156822Seric { 96260089Seric key.size++; 96360089Seric data.size++; 96460089Seric } 96556836Seric 96660089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 96760089Seric if (stat > 0) 96860089Seric { 96968497Seric if (!bitset(MF_APPEND, map->map_mflags)) 97068497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 97168497Seric else 97268497Seric { 97368497Seric static char *buf = NULL; 97468497Seric static int bufsiz = 0; 97568497Seric DBT old; 97668497Seric 97768497Seric old.data = db_map_lookup(map, key.data, NULL, &stat); 97868497Seric if (old.data != NULL) 97968497Seric { 98068497Seric old.size = strlen(old.data); 98168497Seric if (data.size + old.size + 2 > bufsiz) 98268497Seric { 98368497Seric if (buf != NULL) 98468497Seric (void) free(buf); 98568497Seric bufsiz = data.size + old.size + 2; 98668497Seric buf = xalloc(bufsiz); 98768497Seric } 98868497Seric sprintf(buf, "%s,%s", data.data, old.data); 98968497Seric data.size = data.size + old.size + 1; 99068497Seric data.data = buf; 99168497Seric if (tTd(38, 9)) 99268497Seric printf("db_map_store append=%s\n", data.data); 99368497Seric } 99468497Seric } 99560089Seric stat = db->put(db, &key, &data, 0); 99660089Seric } 99760089Seric if (stat != 0) 99860089Seric syserr("readaliases: db put (%s)", lhs); 99960089Seric } 100056836Seric 100156847Seric 100260089Seric /* 100360089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 100460089Seric */ 100560089Seric 100660089Seric void 100760089Seric db_map_close(map) 100860089Seric MAP *map; 100960089Seric { 101060089Seric register DB *db = map->map_db2; 101160089Seric 101260537Seric if (tTd(38, 9)) 101368350Seric printf("db_map_close(%s, %s, %x)\n", 101468350Seric map->map_mname, map->map_file, map->map_mflags); 101560089Seric 101660207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 101758804Seric { 101860089Seric /* write out the distinguished alias */ 101960089Seric db_map_store(map, "@", "@"); 102058804Seric } 102158963Seric 102260089Seric if (db->close(db) != 0) 102360089Seric syserr("readaliases: db close failure"); 102456822Seric } 102557208Seric 102660089Seric #endif 102760089Seric /* 102860089Seric ** NIS Modules 102960089Seric */ 103060089Seric 103160089Seric # ifdef NIS 103260089Seric 103364369Seric # ifndef YPERR_BUSY 103464369Seric # define YPERR_BUSY 16 103564369Seric # endif 103664369Seric 103757208Seric /* 103860089Seric ** NIS_MAP_OPEN -- open DBM map 103957208Seric */ 104057208Seric 104157208Seric bool 104260089Seric nis_map_open(map, mode) 104357208Seric MAP *map; 104460089Seric int mode; 104557208Seric { 104657216Seric int yperr; 104760215Seric register char *p; 104860215Seric auto char *vp; 104960215Seric auto int vsize; 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; 118969748Seric char *domain; 1190*69780Seric char *cname; 119169401Seric char host_record[MAXLINE]; 1192*69780Seric char fbuf[MAXNAME]; 1193*69780Seric char nbuf[MAXNAME + 1]; 119469401Seric extern char *get_column(); 119569401Seric 119669401Seric if (tTd(38, 20)) 119769401Seric printf("nis_getcanonname(%s)\n", name); 119869401Seric 1199*69780Seric if (strlen(name) >= sizeof nbuf) 1200*69780Seric { 1201*69780Seric *statp = EX_UNAVAILABLE; 1202*69780Seric return FALSE; 1203*69780Seric } 1204*69780Seric (void) strcpy(nbuf, name); 1205*69780Seric shorten_hostname(nbuf); 120669401Seric 120769401Seric /* we only accept single token search key */ 1208*69780Seric if (strchr(nbuf, '.')) 120969401Seric { 121069401Seric *statp = EX_NOHOST; 121169401Seric return FALSE; 121269401Seric } 121369401Seric 1214*69780Seric keylen = strlen(nbuf); 121569401Seric 121669401Seric if (yp_domain == NULL) 121769401Seric yp_get_default_domain(&yp_domain); 1218*69780Seric makelower(nbuf); 121969401Seric yperr = YPERR_KEY; 122069401Seric if (try0null) 122169401Seric { 1222*69780Seric yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 122369401Seric &vp, &vsize); 122469401Seric if (yperr == 0) 122569401Seric try1null = FALSE; 122669401Seric } 122769401Seric if (yperr == YPERR_KEY && try1null) 122869401Seric { 122969401Seric keylen++; 1230*69780Seric yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 123169401Seric &vp, &vsize); 123269401Seric if (yperr == 0) 123369401Seric try0null = FALSE; 123469401Seric } 123569401Seric if (yperr != 0) 123669401Seric { 123769401Seric if (yperr == YPERR_KEY) 123869401Seric *statp = EX_NOHOST; 123969401Seric else if (yperr == YPERR_BUSY) 124069401Seric *statp = EX_TEMPFAIL; 124169401Seric else 124269401Seric *statp = EX_UNAVAILABLE; 124369401Seric return FALSE; 124469401Seric } 124569401Seric strncpy(host_record, vp, vsize); 124669401Seric host_record[vsize] = '\0'; 124769663Seric if (tTd(38, 44)) 124869663Seric printf("got record `%s'\n", host_record); 1249*69780Seric cname = get_column(host_record, 1, '\0', fbuf); 125069401Seric if (cname == NULL) 125169401Seric { 125269401Seric /* this should not happen, but.... */ 125369401Seric *statp = EX_NOHOST; 125469401Seric return FALSE; 125569401Seric } 125669401Seric 125769703Seric if (strchr(cname, '.') != NULL) 125869401Seric { 125969703Seric domain = ""; 126069703Seric } 126169703Seric else 126269703Seric { 126369703Seric domain = macvalue('m', CurEnv); 126469703Seric if (domain == NULL) 126569703Seric domain = ""; 126669703Seric } 126769703Seric if (hbsize >= strlen(cname) + strlen(domain) + 1) 126869703Seric { 126969703Seric if (domain[0] == '\0') 127069703Seric strcpy(name, vp); 127169703Seric else 127269703Seric sprintf(name, "%s.%s", vp, domain); 127369401Seric *statp = EX_OK; 127469401Seric return TRUE; 127569401Seric } 127669401Seric *statp = EX_UNAVAILABLE; 127769401Seric return FALSE; 127869401Seric } 127969401Seric 128068350Seric #endif 128168350Seric /* 128268350Seric ** NISPLUS Modules 128368350Seric ** 128468350Seric ** This code donated by Sun Microsystems. 128568350Seric */ 128667848Seric 128768350Seric #ifdef NISPLUS 128868350Seric 128968350Seric #undef NIS /* symbol conflict in nis.h */ 129068350Seric #include <rpcsvc/nis.h> 129168350Seric #include <rpcsvc/nislib.h> 129268350Seric 129368350Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 129468350Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 129568350Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 129668350Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 129768350Seric 129867848Seric /* 129968350Seric ** NISPLUS_MAP_OPEN -- open nisplus table 130067848Seric */ 130167848Seric 130268350Seric bool 130368350Seric nisplus_map_open(map, mode) 130467848Seric MAP *map; 130568350Seric int mode; 130667848Seric { 130768350Seric register char *p; 130868350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 130968350Seric nis_result *res = NULL; 131068350Seric u_int objs_len; 131168350Seric nis_object *obj_ptr; 131268350Seric int retry_cnt, max_col, i; 131368350Seric 131468350Seric if (tTd(38, 2)) 131568350Seric printf("nisplus_map_open(%s, %s, %d)\n", 131668350Seric map->map_mname, map->map_file, mode); 131768350Seric 131868350Seric if (mode != O_RDONLY) 131968350Seric { 132068350Seric errno = ENODEV; 132168350Seric return FALSE; 132268350Seric } 132368350Seric 132468350Seric if (*map->map_file == '\0') 132568350Seric map->map_file = "mail_aliases.org_dir"; 132668350Seric 132768350Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 132868350Seric { 132968350Seric /* set default NISPLUS Domain to $m */ 133068350Seric extern char *nisplus_default_domain(); 133168350Seric 133268350Seric map->map_domain = newstr(nisplus_default_domain()); 133368350Seric if (tTd(38, 2)) 133468350Seric printf("nisplus_map_open(%s): using domain %s\n", 133568350Seric map->map_file, map->map_domain); 133668350Seric } 133768350Seric if (!PARTIAL_NAME(map->map_file)) 133868350Seric map->map_domain = newstr(""); 133968350Seric 134068350Seric /* check to see if this map actually exists */ 134168350Seric if (PARTIAL_NAME(map->map_file)) 134268350Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 134368350Seric else 134468350Seric strcpy(qbuf, map->map_file); 134568350Seric 134668350Seric retry_cnt = 0; 134768350Seric while (res == NULL || res->status != NIS_SUCCESS) 134868350Seric { 134968350Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 135068350Seric switch (res->status) 135168350Seric { 135268350Seric case NIS_SUCCESS: 135368350Seric case NIS_TRYAGAIN: 135468350Seric case NIS_RPCERROR: 135568350Seric case NIS_NAMEUNREACHABLE: 135668350Seric break; 135768350Seric 135868350Seric default: /* all other nisplus errors */ 135968350Seric #if 0 136068350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 136168350Seric syserr("421 Cannot find table %s.%s: %s", 136268350Seric map->map_file, map->map_domain, 136368350Seric nis_sperrno(res->status)); 136468350Seric #endif 136568350Seric errno = EBADR; 136668350Seric return FALSE; 136768350Seric } 136868350Seric sleep(2); /* try not to overwhelm hosed server */ 136968350Seric if (retry_cnt++ > 4) 137068350Seric { 137168350Seric errno = EBADR; 137268350Seric return FALSE; 137368350Seric } 137468350Seric } 137568350Seric 137668350Seric if (NIS_RES_NUMOBJ(res) != 1 || 137768350Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 137868350Seric { 137968350Seric if (tTd(38, 10)) 138068350Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 138168350Seric #if 0 138268350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 138368350Seric syserr("421 %s.%s: %s is not a table", 138468350Seric map->map_file, map->map_domain, 138568350Seric nis_sperrno(res->status)); 138668350Seric #endif 138768350Seric errno = EBADR; 138868350Seric return FALSE; 138968350Seric } 139068350Seric /* default key column is column 0 */ 139168350Seric if (map->map_keycolnm == NULL) 139268350Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 139368350Seric 139468350Seric max_col = COL_MAX(res); 139568350Seric 139668350Seric /* verify the key column exist */ 139768350Seric for (i=0; i< max_col; i++) 139868350Seric { 139968350Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 140068350Seric break; 140168350Seric } 140268350Seric if (i == max_col) 140368350Seric { 140468350Seric if (tTd(38, 2)) 140568350Seric printf("nisplus_map_open(%s): can not find key column %s\n", 140668350Seric map->map_file, map->map_keycolnm); 140768350Seric errno = EBADR; 140868350Seric return FALSE; 140968350Seric } 141068350Seric 141168350Seric /* default value column is the last column */ 141268350Seric if (map->map_valcolnm == NULL) 141368350Seric { 141468350Seric map->map_valcolno = max_col - 1; 141568350Seric return TRUE; 141668350Seric } 141768350Seric 141868350Seric for (i=0; i< max_col; i++) 141968350Seric { 142068350Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 142168350Seric { 142268350Seric map->map_valcolno = i; 142368350Seric return TRUE; 142468350Seric } 142568350Seric } 142668350Seric 142768350Seric if (tTd(38, 2)) 142868350Seric printf("nisplus_map_open(%s): can not find column %s\n", 142968350Seric map->map_file, map->map_keycolnm); 143068350Seric errno = EBADR; 143168350Seric return FALSE; 143267848Seric } 143367848Seric 143467848Seric 143567848Seric /* 143668350Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 143767848Seric */ 143867848Seric 143968350Seric char * 144068350Seric nisplus_map_lookup(map, name, av, statp) 144167848Seric MAP *map; 144268350Seric char *name; 144368350Seric char **av; 144468350Seric int *statp; 144567848Seric { 144668350Seric char *vp; 144768350Seric auto int vsize; 144868350Seric int buflen; 144968350Seric char search_key[MAXNAME + 1]; 145068350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 145168350Seric nis_result *result; 145268350Seric 145368350Seric if (tTd(38, 20)) 145468350Seric printf("nisplus_map_lookup(%s, %s)\n", 145568350Seric map->map_mname, name); 145668350Seric 145768350Seric if (!bitset(MF_OPEN, map->map_mflags)) 145868350Seric { 145968350Seric if (nisplus_map_open(map, O_RDONLY)) 146068350Seric map->map_mflags |= MF_OPEN; 146168350Seric else 146268350Seric { 146368350Seric *statp = EX_UNAVAILABLE; 146468350Seric return NULL; 146568350Seric } 146668350Seric } 146768350Seric 146868350Seric buflen = strlen(name); 146968350Seric if (buflen > sizeof search_key - 1) 147068350Seric buflen = sizeof search_key - 1; 147168350Seric bcopy(name, search_key, buflen + 1); 147268350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 147368350Seric makelower(search_key); 147468350Seric 147568350Seric /* construct the query */ 147668350Seric if (PARTIAL_NAME(map->map_file)) 147768350Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 147868350Seric search_key, map->map_file, map->map_domain); 147968350Seric else 148068350Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 148168350Seric search_key, map->map_file); 148268350Seric 148368350Seric if (tTd(38, 20)) 148468350Seric printf("qbuf=%s\n", qbuf); 148568350Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 148668350Seric if (result->status == NIS_SUCCESS) 148768350Seric { 148868350Seric int count; 148968350Seric char *str; 149068350Seric 149168350Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 149268350Seric { 149368350Seric if (LogLevel > 10) 149468350Seric syslog(LOG_WARNING, 149568350Seric "%s:Lookup error, expected 1 entry, got (%d)", 149668350Seric map->map_file, count); 149768350Seric 149868350Seric /* ignore second entry */ 149968350Seric if (tTd(38, 20)) 150068350Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 150168350Seric name, count); 150268350Seric } 150368350Seric 150468350Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 150568350Seric /* set the length of the result */ 150668350Seric if (vp == NULL) 150768350Seric vp = ""; 150868350Seric vsize = strlen(vp); 150968350Seric if (tTd(38, 20)) 151068350Seric printf("nisplus_map_lookup(%s), found %s\n", 151168350Seric name, vp); 151268350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 151368350Seric str = map_rewrite(map, name, strlen(name), NULL); 151468350Seric else 151568350Seric str = map_rewrite(map, vp, vsize, av); 151668350Seric nis_freeresult(result); 151768350Seric #ifdef MAP_EXIT_STAT 151868350Seric *statp = EX_OK; 151968350Seric #endif 152068350Seric return str; 152168350Seric } 152268350Seric else 152368350Seric { 152468350Seric #ifdef MAP_EXIT_STAT 152568350Seric if (result->status == NIS_NOTFOUND) 152668350Seric *statp = EX_NOTFOUND; 152768350Seric else if (result->status == NIS_TRYAGAIN) 152868350Seric *statp = EX_TEMPFAIL; 152968350Seric else 153068350Seric { 153168350Seric *statp = EX_UNAVAILABLE; 153268350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 153368350Seric } 153468350Seric #else 153568350Seric if ((result->status != NIS_NOTFOUND) && 153668350Seric (result->status != NIS_TRYAGAIN)) 153768350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 153868350Seric #endif 153968350Seric } 154068350Seric if (tTd(38, 20)) 154168350Seric printf("nisplus_map_lookup(%s), failed\n", name); 154268350Seric nis_freeresult(result); 154368350Seric return NULL; 154467848Seric } 154567848Seric 154668350Seric 154769401Seric 154869401Seric /* 154969401Seric ** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 155069401Seric */ 155169401Seric 155269401Seric bool 155369401Seric nisplus_getcanonname(name, hbsize, statp) 155469401Seric char *name; 155569401Seric int hbsize; 155669401Seric int *statp; 155769401Seric { 155869401Seric char *vp; 155969401Seric auto int vsize; 156069401Seric int buflen; 156169401Seric nis_result *result; 156269401Seric char *p; 156369401Seric int len; 1564*69780Seric char nbuf[MAXNAME + 1]; 1565*69780Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 156669401Seric 1567*69780Seric if (strlen(name) >= sizeof nbuf) 1568*69780Seric { 1569*69780Seric *statp = EX_UNAVAILABLE; 1570*69780Seric return FALSE; 1571*69780Seric } 1572*69780Seric (void) strcpy(nbuf, name); 1573*69780Seric shorten_hostname(nbuf); 157469401Seric 1575*69780Seric p = strchr(nbuf, '.'); 157669401Seric if (p == NULL) 157769401Seric { 157869401Seric /* single token */ 1579*69780Seric sprintf(qbuf, "[name=%s],hosts.org_dir", nbuf); 158069401Seric } 158169401Seric else if (p[1] != '\0') 158269401Seric { 1583*69780Seric /* multi token -- take only first token in nbuf */ 158469401Seric *p = '\0'; 1585*69780Seric sprintf(qbuf, "[name=%s],hosts.org_dir.%s", nbuf, &p[1]); 158669401Seric } 158769401Seric else 158869401Seric { 158969401Seric *statp = EX_NOHOST; 159069401Seric return FALSE; 159169401Seric } 159269401Seric 159369401Seric if (tTd(38, 20)) 159469478Seric printf("\nnisplus_getcanoname(%s), qbuf=%s\n", 1595*69780Seric name, qbuf); 159669401Seric 1597*69780Seric result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 159869401Seric NULL, NULL); 159969401Seric 160069401Seric if (result->status == NIS_SUCCESS) 160169401Seric { 160269401Seric int count; 160369401Seric char *str; 160469401Seric char *domain; 160569401Seric 160669401Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 160769401Seric { 160869401Seric #ifdef LOG 160969401Seric if (LogLevel > 10) 161069401Seric syslog(LOG_WARNING, 161169401Seric "nisplus_getcanonname: Lookup error, expected 1 entry, got (%d)", 161269401Seric count); 161369401Seric #endif 161469401Seric 161569401Seric /* ignore second entry */ 161669401Seric if (tTd(38, 20)) 161769401Seric printf("nisplus_getcanoname(%s), got %d entries, addtional entries ignores\n", name); 161869401Seric } 161969401Seric 162069401Seric if (tTd(38, 20)) 162169401Seric printf("nisplus_getcanoname(%s), found in directory \"%s\"\n", 162269401Seric name, (NIS_RES_OBJECT(result))->zo_domain); 162369401Seric 162469401Seric 162569401Seric vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 162669401Seric vsize = strlen(vp); 162769401Seric if (tTd(38, 20)) 162869401Seric printf("nisplus_getcanonname(%s), found %s\n", 162969401Seric name, vp); 163069703Seric if (strchr(vp, '.') != NULL) 163169703Seric { 163269636Seric domain = ""; 163369703Seric } 163469703Seric else 163569703Seric { 163669703Seric domain = macvalue('m', CurEnv); 163769703Seric if (domain == NULL) 163869703Seric domain = ""; 163969703Seric } 164069636Seric if (hbsize > vsize + (int) strlen(domain) + 1) 164169401Seric { 164269636Seric if (domain[0] == '\0') 164369636Seric strcpy(name, vp); 164469636Seric else 164569636Seric sprintf(name, "%s.%s", vp, domain); 164669401Seric *statp = EX_OK; 164769401Seric } 164869401Seric else 164969401Seric *statp = EX_NOHOST; 165069401Seric nis_freeresult(result); 165169401Seric return TRUE; 165269401Seric } 165369401Seric else 165469401Seric { 165569401Seric if (result->status == NIS_NOTFOUND) 165669401Seric *statp = EX_NOHOST; 165769401Seric else if (result->status == NIS_TRYAGAIN) 165869401Seric *statp = EX_TEMPFAIL; 165969401Seric else 166069401Seric *statp = EX_UNAVAILABLE; 166169401Seric } 166269401Seric if (tTd(38, 20)) 166369401Seric printf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 166469401Seric name, result->status, *statp); 166569401Seric nis_freeresult(result); 166669401Seric return FALSE; 166769401Seric } 166869401Seric 166969401Seric 167068350Seric char * 167168350Seric nisplus_default_domain() 167268350Seric { 167368528Seric static char default_domain[MAXNAME + 1] = ""; 167468350Seric char *p; 167568350Seric 167668350Seric if (default_domain[0] != '\0') 167768350Seric return(default_domain); 167868350Seric 167968458Seric p = nis_local_directory(); 168068350Seric strcpy(default_domain, p); 168168458Seric return default_domain; 168268350Seric } 168368350Seric 168468350Seric #endif /* NISPLUS */ 168567848Seric /* 168668350Seric ** HESIOD Modules 168768350Seric */ 168868350Seric 168968350Seric #ifdef HESIOD 169068350Seric 169168350Seric #include <hesiod.h> 169268350Seric 169368350Seric char * 169468350Seric hes_map_lookup(map, name, av, statp) 169568350Seric MAP *map; 169668350Seric char *name; 169768350Seric char **av; 169868350Seric int *statp; 169968350Seric { 170068350Seric char **hp; 170168350Seric 170268350Seric if (tTd(38, 20)) 170368350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 170468350Seric 170569688Seric if (name[0] == '\\') 170669688Seric { 170769688Seric char *np; 170869688Seric int nl; 170969688Seric char nbuf[MAXNAME]; 171069688Seric 171169688Seric nl = strlen(name); 171269688Seric if (nl < sizeof nbuf - 1) 171369688Seric np = nbuf; 171469688Seric else 171569688Seric np = xalloc(strlen(name) + 2); 171669688Seric np[0] = '\\'; 171769688Seric strcpy(&np[1], name); 171869688Seric hp = hes_resolve(np, map->map_file); 171969688Seric if (np != nbuf) 172069688Seric free(np); 172169688Seric } 172269688Seric else 172369688Seric { 172469688Seric hp = hes_resolve(name, map->map_file); 172569688Seric } 172669623Seric if (hp == NULL || hp[0] == NULL) 172768350Seric return NULL; 172868350Seric 172969623Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 173069623Seric return map_rewrite(map, name, strlen(name), NULL); 173169623Seric else 173269623Seric return map_rewrite(map, hp[0], strlen(hp[0]), av); 173368350Seric } 173468350Seric 173568350Seric #endif 173668350Seric /* 173768350Seric ** NeXT NETINFO Modules 173868350Seric */ 173968350Seric 174068350Seric #ifdef NETINFO 174168350Seric 174268350Seric #define NETINFO_DEFAULT_DIR "/aliases" 174368350Seric #define NETINFO_DEFAULT_PROPERTY "members" 174468350Seric 174568350Seric 174668350Seric /* 174768350Seric ** NI_MAP_OPEN -- open NetInfo Aliases 174868350Seric */ 174968350Seric 175068350Seric bool 175168350Seric ni_map_open(map, mode) 175268350Seric MAP *map; 175368350Seric int mode; 175468350Seric { 175568350Seric char *p; 175668350Seric 175768350Seric if (tTd(38, 20)) 175868350Seric printf("ni_map_open: %s\n", map->map_file); 175968350Seric 176068350Seric if (*map->map_file == '\0') 176168350Seric map->map_file = NETINFO_DEFAULT_DIR; 176268350Seric 176368350Seric if (map->map_valcolnm == NULL) 176468350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 176568350Seric 176668350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 176768350Seric map->map_coldelim = ','; 176868350Seric 176968350Seric return TRUE; 177068350Seric } 177168350Seric 177268350Seric 177368350Seric /* 177468350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 177568350Seric */ 177668350Seric 177768350Seric char * 177868350Seric ni_map_lookup(map, name, av, statp) 177968350Seric MAP *map; 178068350Seric char *name; 178168350Seric char **av; 178268350Seric int *statp; 178368350Seric { 178468350Seric char *res; 178568350Seric char *propval; 178668350Seric extern char *ni_propval(); 178768350Seric 178868350Seric if (tTd(38, 20)) 178968350Seric printf("ni_map_lookup(%s, %s)\n", 179068350Seric map->map_mname, name); 179168350Seric 179268350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 179368350Seric map->map_valcolnm, map->map_coldelim); 179468350Seric 179568350Seric if (propval == NULL) 179668350Seric return NULL; 179768350Seric 179868350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 179968350Seric res = map_rewrite(map, name, strlen(name), NULL); 180068350Seric else 180168350Seric res = map_rewrite(map, propval, strlen(propval), av); 180268350Seric free(propval); 180368350Seric return res; 180468350Seric } 180568350Seric 180668350Seric #endif 180768350Seric /* 180868350Seric ** TEXT (unindexed text file) Modules 180968350Seric ** 181068350Seric ** This code donated by Sun Microsystems. 181168350Seric */ 181268350Seric 181368350Seric 181468350Seric /* 181568350Seric ** TEXT_MAP_OPEN -- open text table 181668350Seric */ 181768350Seric 181868350Seric bool 181968350Seric text_map_open(map, mode) 182068350Seric MAP *map; 182168350Seric int mode; 182268350Seric { 182368350Seric struct stat sbuf; 182468350Seric 182568350Seric if (tTd(38, 2)) 182668350Seric printf("text_map_open(%s, %s, %d)\n", 182768350Seric map->map_mname, map->map_file, mode); 182868350Seric 182968350Seric if (mode != O_RDONLY) 183068350Seric { 183168350Seric errno = ENODEV; 183268350Seric return FALSE; 183368350Seric } 183468350Seric 183568350Seric if (*map->map_file == '\0') 183668350Seric { 183768350Seric if (tTd(38, 2)) 183868350Seric printf("text_map_open: file name required\n"); 183968350Seric return FALSE; 184068350Seric } 184168350Seric 184268350Seric if (map->map_file[0] != '/') 184368350Seric { 184468350Seric if (tTd(38, 2)) 184568350Seric printf("text_map_open(%s): file name must be fully qualified\n", 184668350Seric map->map_file); 184768350Seric return FALSE; 184868350Seric } 184968350Seric /* check to see if this map actually accessable */ 185068350Seric if (access(map->map_file, R_OK) <0) 185168350Seric return FALSE; 185268350Seric 185368350Seric /* check to see if this map actually exist */ 185468350Seric if (stat(map->map_file, &sbuf) <0) 185568350Seric { 185668350Seric if (tTd(38, 2)) 185768350Seric printf("text_map_open(%s): can not stat %s\n", 185868350Seric map->map_file, map->map_file); 185968350Seric return FALSE; 186068350Seric } 186168350Seric 186268350Seric if (!S_ISREG(sbuf.st_mode)) 186368350Seric { 186468350Seric if (tTd(38, 2)) 186568350Seric printf("text_map_open(%s): %s is not a file\n", 186668350Seric map->map_file, map->map_file); 186768350Seric return FALSE; 186868350Seric } 186968350Seric 187068350Seric if (map->map_keycolnm == NULL) 187168350Seric map->map_keycolno = 0; 187268350Seric else 187368350Seric { 187468350Seric if (!isdigit(*map->map_keycolnm)) 187568350Seric { 187668350Seric if (tTd(38, 2)) 187768350Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 187868350Seric map->map_file, map->map_keycolnm); 187968350Seric return FALSE; 188068350Seric } 188168350Seric map->map_keycolno = atoi(map->map_keycolnm); 188268350Seric } 188368350Seric 188468350Seric if (map->map_valcolnm == NULL) 188568350Seric map->map_valcolno = 0; 188668350Seric else 188768350Seric { 188868350Seric if (!isdigit(*map->map_valcolnm)) 188968350Seric { 189068350Seric if (tTd(38, 2)) 189168350Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 189268350Seric map->map_file, map->map_valcolnm); 189368350Seric return FALSE; 189468350Seric } 189568350Seric map->map_valcolno = atoi(map->map_valcolnm); 189668350Seric } 189768350Seric 189868350Seric if (tTd(38, 2)) 189968350Seric { 190068520Seric printf("text_map_open(%s): delimiter = ", 190168520Seric map->map_file); 190268520Seric if (map->map_coldelim == '\0') 190368520Seric printf("(white space)\n"); 190468520Seric else 190568520Seric printf("%c\n", map->map_coldelim); 190668350Seric } 190768350Seric 190868350Seric return TRUE; 190968350Seric } 191068350Seric 191168350Seric 191268350Seric /* 191368350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 191468350Seric */ 191568350Seric 191668350Seric char * 191768350Seric text_map_lookup(map, name, av, statp) 191868350Seric MAP *map; 191968350Seric char *name; 192068350Seric char **av; 192168350Seric int *statp; 192268350Seric { 192368350Seric char *vp; 192468350Seric auto int vsize; 192568350Seric int buflen; 192668350Seric char search_key[MAXNAME + 1]; 192768350Seric char linebuf[MAXLINE]; 192868350Seric FILE *f; 192968528Seric char buf[MAXNAME + 1]; 193068350Seric char delim; 193168350Seric int key_idx; 193268350Seric bool found_it; 193368350Seric extern char *get_column(); 193468350Seric 193568350Seric 193668350Seric found_it = FALSE; 193768350Seric if (tTd(38, 20)) 193868350Seric printf("text_map_lookup(%s)\n", name); 193968350Seric 194068350Seric buflen = strlen(name); 194168350Seric if (buflen > sizeof search_key - 1) 194268350Seric buflen = sizeof search_key - 1; 194368350Seric bcopy(name, search_key, buflen + 1); 194468350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 194568350Seric makelower(search_key); 194668350Seric 194768350Seric f = fopen(map->map_file, "r"); 194868350Seric if (f == NULL) 194968350Seric { 195068350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 195168350Seric *statp = EX_UNAVAILABLE; 195268350Seric return NULL; 195368350Seric } 195468350Seric key_idx = map->map_keycolno; 195568350Seric delim = map->map_coldelim; 195668350Seric while (fgets(linebuf, MAXLINE, f)) 195768350Seric { 195868350Seric char *lf; 195968350Seric if (linebuf[0] == '#') 196068350Seric continue; /* skip comment line */ 196168350Seric if (lf = strchr(linebuf, '\n')) 196268350Seric *lf = '\0'; 196368350Seric if (!strcasecmp(search_key, 196468350Seric get_column(linebuf, key_idx, delim, buf))) 196568350Seric { 196668350Seric found_it = TRUE; 196768350Seric break; 196868350Seric } 196968350Seric } 197068350Seric fclose(f); 197168350Seric if (!found_it) 197268350Seric { 197368350Seric #ifdef MAP_EXIT_STAT 197468350Seric *statp = EX_NOTFOUND; 197568350Seric #endif 197668350Seric return(NULL); 197768350Seric } 197868350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 197968350Seric vsize = strlen(vp); 198068350Seric #ifdef MAP_EXIT_STAT 198168350Seric *statp = EX_OK; 198268350Seric #endif 198368350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 198468350Seric return map_rewrite(map, name, strlen(name), NULL); 198568350Seric else 198668350Seric return map_rewrite(map, vp, vsize, av); 198768350Seric } 198869401Seric 198969401Seric 199069401Seric /* 199169401Seric ** TEXT_GETCANONNAME -- look up canonical name in hosts file 199269401Seric */ 199369401Seric 199469401Seric bool 199569401Seric text_getcanonname(name, hbsize, statp) 199669401Seric char *name; 199769401Seric int hbsize; 199869401Seric int *statp; 199969401Seric { 200069401Seric int key_idx; 200169401Seric char *cname; 200269401Seric bool found; 200369401Seric FILE *f; 200469401Seric char linebuf[MAXLINE]; 200569401Seric char cbuf[MAXNAME + 1]; 2006*69780Seric char fbuf[MAXNAME + 1]; 2007*69780Seric char nbuf[MAXNAME + 1]; 200869401Seric extern char *get_column(); 200969401Seric 2010*69780Seric if (strlen(name) >= sizeof nbuf) 2011*69780Seric { 2012*69780Seric *statp = EX_UNAVAILABLE; 2013*69780Seric return FALSE; 2014*69780Seric } 2015*69780Seric (void) strcpy(nbuf, name); 2016*69780Seric shorten_hostname(nbuf); 201769401Seric 201869401Seric /* we only accept single token search key */ 2019*69780Seric if (strchr(nbuf, '.') != NULL) 202069401Seric { 202169401Seric *statp = EX_NOHOST; 202269401Seric return FALSE; 202369401Seric } 202469401Seric 202569401Seric found = FALSE; 202669401Seric 202769401Seric f = fopen(HostsFile, "r"); 202869401Seric if (f == NULL) 202969401Seric { 203069401Seric #ifdef MAP_EXIT_STAT 203169401Seric *statp = EX_UNAVAILABLE; 203269401Seric #endif 203369401Seric return FALSE; 203469401Seric } 203569401Seric while (!found && fgets(linebuf, MAXLINE, f) != NULL) 203669401Seric { 203769401Seric char *p; 203869401Seric 203969401Seric if (linebuf[0] == '#') 204069401Seric continue; 204169401Seric if ((p = strchr(linebuf, '\n')) != NULL) 204269401Seric *p = '\0'; 204369663Seric cname = get_column(linebuf, 1, '\0', cbuf); 2044*69780Seric if (cname != NULL && strcasecmp(nbuf, cname) == 0) 204569401Seric { 204669401Seric found = TRUE; 204769401Seric break; 204869401Seric } 204969401Seric 205069401Seric key_idx = 2; 2051*69780Seric while ((p = get_column(linebuf, key_idx, '\0', fbuf)) != NULL) 205269401Seric { 2053*69780Seric if (strcasecmp(nbuf, p) == 0) 205469401Seric { 205569401Seric found = TRUE; 205669401Seric break; 205769401Seric } 205869401Seric key_idx++; 205969401Seric } 206069401Seric } 206169401Seric fclose(f); 206269401Seric if (!found) 206369401Seric { 206469401Seric *statp = EX_NOHOST; 206569401Seric return FALSE; 206669401Seric } 206769401Seric 206869401Seric if (hbsize >= strlen(cname)) 206969401Seric { 207069401Seric strcpy(name, cname); 207169401Seric *statp = EX_OK; 207269401Seric return TRUE; 207369401Seric } 207469401Seric *statp = EX_UNAVAILABLE; 207569401Seric return FALSE; 207669401Seric } 207768350Seric /* 207860089Seric ** STAB (Symbol Table) Modules 207960089Seric */ 208060089Seric 208160089Seric 208260089Seric /* 208360207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 208460089Seric */ 208560089Seric 208660089Seric char * 208761707Seric stab_map_lookup(map, name, av, pstat) 208860089Seric register MAP *map; 208960089Seric char *name; 209061707Seric char **av; 209161707Seric int *pstat; 209260089Seric { 209360089Seric register STAB *s; 209460089Seric 209560537Seric if (tTd(38, 20)) 209668350Seric printf("stab_lookup(%s, %s)\n", 209768350Seric map->map_mname, name); 209860089Seric 209960089Seric s = stab(name, ST_ALIAS, ST_FIND); 210060089Seric if (s != NULL) 210160089Seric return (s->s_alias); 210260089Seric return (NULL); 210360089Seric } 210460089Seric 210560089Seric 210660089Seric /* 210760207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 210860089Seric */ 210960089Seric 211060089Seric void 211160089Seric stab_map_store(map, lhs, rhs) 211260089Seric register MAP *map; 211360089Seric char *lhs; 211460089Seric char *rhs; 211560089Seric { 211660089Seric register STAB *s; 211760089Seric 211860089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 211960089Seric s->s_alias = newstr(rhs); 212060089Seric } 212160089Seric 212260089Seric 212360089Seric /* 212460207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 212560207Seric ** 212660207Seric ** This is a wierd case -- it is only intended as a fallback for 212760207Seric ** aliases. For this reason, opens for write (only during a 212860207Seric ** "newaliases") always fails, and opens for read open the 212960207Seric ** actual underlying text file instead of the database. 213060089Seric */ 213160089Seric 213260089Seric bool 213360089Seric stab_map_open(map, mode) 213460089Seric register MAP *map; 213560089Seric int mode; 213660089Seric { 213763835Seric FILE *af; 213864284Seric struct stat st; 213963835Seric 214060537Seric if (tTd(38, 2)) 214168350Seric printf("stab_map_open(%s, %s)\n", 214268350Seric map->map_mname, map->map_file); 214360089Seric 214460089Seric if (mode != O_RDONLY) 214560207Seric { 214660207Seric errno = ENODEV; 214760089Seric return FALSE; 214860207Seric } 214960089Seric 215063835Seric af = fopen(map->map_file, "r"); 215163835Seric if (af == NULL) 215263835Seric return FALSE; 215368350Seric readaliases(map, af, FALSE, FALSE); 215464284Seric 215564284Seric if (fstat(fileno(af), &st) >= 0) 215664284Seric map->map_mtime = st.st_mtime; 215763835Seric fclose(af); 215863835Seric 215960089Seric return TRUE; 216060089Seric } 216160089Seric /* 216260089Seric ** Implicit Modules 216356822Seric ** 216460089Seric ** Tries several types. For back compatibility of aliases. 216556822Seric */ 216656822Seric 216760089Seric 216860089Seric /* 216960207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 217060089Seric */ 217160089Seric 217260089Seric char * 217360089Seric impl_map_lookup(map, name, av, pstat) 217460089Seric MAP *map; 217560089Seric char *name; 217656822Seric char **av; 217760089Seric int *pstat; 217856822Seric { 217960537Seric if (tTd(38, 20)) 218068350Seric printf("impl_map_lookup(%s, %s)\n", 218168350Seric map->map_mname, name); 218256822Seric 218360089Seric #ifdef NEWDB 218460207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 218560089Seric return db_map_lookup(map, name, av, pstat); 218660089Seric #endif 218760089Seric #ifdef NDBM 218860207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 218960089Seric return ndbm_map_lookup(map, name, av, pstat); 219060089Seric #endif 219160089Seric return stab_map_lookup(map, name, av, pstat); 219260089Seric } 219360089Seric 219460089Seric /* 219560207Seric ** IMPL_MAP_STORE -- store in open databases 219660089Seric */ 219760089Seric 219860089Seric void 219960089Seric impl_map_store(map, lhs, rhs) 220060089Seric MAP *map; 220160089Seric char *lhs; 220260089Seric char *rhs; 220360089Seric { 220460089Seric #ifdef NEWDB 220560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 220660089Seric db_map_store(map, lhs, rhs); 220760089Seric #endif 220860089Seric #ifdef NDBM 220960207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 221060089Seric ndbm_map_store(map, lhs, rhs); 221160089Seric #endif 221260089Seric stab_map_store(map, lhs, rhs); 221360089Seric } 221460089Seric 221560089Seric /* 221660089Seric ** IMPL_MAP_OPEN -- implicit database open 221760089Seric */ 221860089Seric 221960089Seric bool 222060089Seric impl_map_open(map, mode) 222160089Seric MAP *map; 222260089Seric int mode; 222360089Seric { 222460089Seric struct stat stb; 222560089Seric 222660537Seric if (tTd(38, 2)) 222768350Seric printf("impl_map_open(%s, %s, %d)\n", 222868350Seric map->map_mname, map->map_file, mode); 222960089Seric 223060089Seric if (stat(map->map_file, &stb) < 0) 223156822Seric { 223260089Seric /* no alias file at all */ 223364718Seric if (tTd(38, 3)) 223464718Seric printf("no map file\n"); 223560089Seric return FALSE; 223656822Seric } 223756822Seric 223860089Seric #ifdef NEWDB 223960207Seric map->map_mflags |= MF_IMPL_HASH; 224060089Seric if (hash_map_open(map, mode)) 224156822Seric { 224264250Seric #if defined(NDBM) && defined(NIS) 224369651Seric if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 224460207Seric #endif 224560207Seric return TRUE; 224660089Seric } 224760207Seric else 224860207Seric map->map_mflags &= ~MF_IMPL_HASH; 224960089Seric #endif 225060089Seric #ifdef NDBM 225160207Seric map->map_mflags |= MF_IMPL_NDBM; 225260089Seric if (ndbm_map_open(map, mode)) 225360089Seric { 225460089Seric return TRUE; 225560089Seric } 225660207Seric else 225760207Seric map->map_mflags &= ~MF_IMPL_NDBM; 225860089Seric #endif 225956822Seric 226064650Seric #if defined(NEWDB) || defined(NDBM) 226160089Seric if (Verbose) 226260089Seric message("WARNING: cannot open alias database %s", map->map_file); 226364964Seric #else 226464964Seric if (mode != O_RDONLY) 226564964Seric usrerr("Cannot rebuild aliases: no database format defined"); 226660207Seric #endif 226760089Seric 226860207Seric return stab_map_open(map, mode); 226956822Seric } 227060089Seric 227160207Seric 227260089Seric /* 227360207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 227460089Seric */ 227560089Seric 227660089Seric void 227760207Seric impl_map_close(map) 227860089Seric MAP *map; 227960089Seric { 228068350Seric if (tTd(38, 20)) 228168350Seric printf("impl_map_close(%s, %s, %x)\n", 228268350Seric map->map_mname, map->map_file, map->map_mflags); 228360089Seric #ifdef NEWDB 228460207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 228560089Seric { 228660207Seric db_map_close(map); 228760207Seric map->map_mflags &= ~MF_IMPL_HASH; 228860089Seric } 228960089Seric #endif 229060089Seric 229160089Seric #ifdef NDBM 229260207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 229360089Seric { 229460207Seric ndbm_map_close(map); 229560207Seric map->map_mflags &= ~MF_IMPL_NDBM; 229660089Seric } 229760089Seric #endif 229860089Seric } 229960207Seric /* 230068350Seric ** User map class. 230168350Seric ** 230268350Seric ** Provides access to the system password file. 230368350Seric */ 230468350Seric 230568350Seric /* 230668350Seric ** USER_MAP_OPEN -- open user map 230768350Seric ** 230868350Seric ** Really just binds field names to field numbers. 230968350Seric */ 231068350Seric 231168350Seric bool 231268350Seric user_map_open(map, mode) 231368350Seric MAP *map; 231468350Seric int mode; 231568350Seric { 231668350Seric if (tTd(38, 2)) 231768350Seric printf("user_map_open(%s)\n", map->map_mname); 231868350Seric 231968350Seric if (mode != O_RDONLY) 232068350Seric { 232168350Seric /* issue a pseudo-error message */ 232268350Seric #ifdef ENOSYS 232368350Seric errno = ENOSYS; 232468350Seric #else 232568350Seric # ifdef EFTYPE 232668350Seric errno = EFTYPE; 232768350Seric # else 232868350Seric errno = ENXIO; 232968350Seric # endif 233068350Seric #endif 233168350Seric return FALSE; 233268350Seric } 233368350Seric if (map->map_valcolnm == NULL) 233468350Seric /* nothing */ ; 233568350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 233668350Seric map->map_valcolno = 1; 233768350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 233868350Seric map->map_valcolno = 2; 233968350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 234068350Seric map->map_valcolno = 3; 234168350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 234268350Seric map->map_valcolno = 4; 234368350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 234468350Seric map->map_valcolno = 5; 234568350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 234668350Seric map->map_valcolno = 6; 234768350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 234868350Seric map->map_valcolno = 7; 234968350Seric else 235068350Seric { 235168350Seric syserr("User map %s: unknown column name %s", 235268350Seric map->map_mname, map->map_valcolnm); 235368350Seric return FALSE; 235468350Seric } 235568350Seric return TRUE; 235668350Seric } 235768350Seric 235868350Seric 235968350Seric /* 236068350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 236168350Seric */ 236268350Seric 236368350Seric char * 236468350Seric user_map_lookup(map, key, av, statp) 236568350Seric MAP *map; 236668350Seric char *key; 236768350Seric char **av; 236868350Seric int *statp; 236968350Seric { 237068350Seric struct passwd *pw; 237168350Seric 237268350Seric if (tTd(38, 20)) 237368350Seric printf("user_map_lookup(%s, %s)\n", 237468350Seric map->map_mname, key); 237568350Seric 237668693Seric pw = sm_getpwnam(key); 237768350Seric if (pw == NULL) 237868350Seric return NULL; 237968350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 238068350Seric return map_rewrite(map, key, strlen(key), NULL); 238168350Seric else 238268350Seric { 238368433Seric char *rwval = NULL; 238468350Seric char buf[30]; 238568350Seric 238668350Seric switch (map->map_valcolno) 238768350Seric { 238868350Seric case 0: 238968350Seric case 1: 239068350Seric rwval = pw->pw_name; 239168350Seric break; 239268350Seric 239368350Seric case 2: 239468350Seric rwval = pw->pw_passwd; 239568350Seric break; 239668350Seric 239768350Seric case 3: 239868350Seric sprintf(buf, "%d", pw->pw_uid); 239968350Seric rwval = buf; 240068350Seric break; 240168350Seric 240268350Seric case 4: 240368350Seric sprintf(buf, "%d", pw->pw_gid); 240468350Seric rwval = buf; 240568350Seric break; 240668350Seric 240768350Seric case 5: 240868350Seric rwval = pw->pw_gecos; 240968350Seric break; 241068350Seric 241168350Seric case 6: 241268350Seric rwval = pw->pw_dir; 241368350Seric break; 241468350Seric 241568350Seric case 7: 241668350Seric rwval = pw->pw_shell; 241768350Seric break; 241868350Seric } 241968350Seric return map_rewrite(map, rwval, strlen(rwval), av); 242068350Seric } 242168350Seric } 242268350Seric /* 242368350Seric ** BESTMX -- find the best MX for a name 242468350Seric ** 242568350Seric ** This is really a hack, but I don't see any obvious way 242668350Seric ** to generalize it at the moment. 242768350Seric */ 242868350Seric 242968350Seric #if NAMED_BIND 243068350Seric 243168350Seric char * 243268350Seric bestmx_map_lookup(map, name, av, statp) 243368350Seric MAP *map; 243468350Seric char *name; 243568350Seric char **av; 243668350Seric int *statp; 243768350Seric { 243868350Seric int nmx; 243968350Seric auto int rcode; 244068350Seric char *mxhosts[MAXMXHOSTS + 1]; 244168350Seric 244268350Seric nmx = getmxrr(name, mxhosts, FALSE, &rcode); 244368350Seric if (nmx <= 0) 244468350Seric return NULL; 244568350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 244668350Seric return map_rewrite(map, name, strlen(name), NULL); 244768350Seric else 244868350Seric return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 244968350Seric } 245068350Seric 245168350Seric #endif 245268350Seric /* 245369453Seric ** Program map type. 245469453Seric ** 245569453Seric ** This provides access to arbitrary programs. It should be used 245669453Seric ** only very sparingly, since there is no way to bound the cost 245769453Seric ** of invoking an arbitrary program. 245869453Seric */ 245969453Seric 246069453Seric char * 246169453Seric prog_map_lookup(map, name, av, statp) 246269453Seric MAP *map; 246369453Seric char *name; 246469453Seric char **av; 246569453Seric int *statp; 246669453Seric { 246769453Seric int i; 246869453Seric register char *p; 246969453Seric int fd; 247069453Seric auto pid_t pid; 247169453Seric char *argv[MAXPV + 1]; 247269453Seric char buf[MAXLINE]; 247369453Seric 247469453Seric if (tTd(38, 20)) 247569453Seric printf("prog_map_lookup(%s, %s) %s\n", 247669453Seric map->map_mname, name, map->map_file); 247769453Seric 247869453Seric i = 0; 247969453Seric argv[i++] = map->map_file; 248069453Seric strcpy(buf, map->map_rebuild); 248169453Seric for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 248269453Seric { 248369453Seric if (i >= MAXPV - 1) 248469453Seric break; 248569453Seric argv[i++] = p; 248669453Seric } 248769453Seric argv[i++] = name; 248869453Seric argv[i] = NULL; 248969453Seric pid = prog_open(argv, &fd, CurEnv); 249069453Seric if (pid < 0) 249169453Seric { 249269453Seric if (tTd(38, 9)) 249369453Seric printf("prog_map_lookup(%s) failed (%s) -- closing", 249469453Seric map->map_mname, errstring(errno)); 249569453Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 249669453Seric return NULL; 249769453Seric } 249869453Seric i = read(fd, buf, sizeof buf - 1); 249969453Seric if (i <= 0 && tTd(38, 2)) 250069453Seric printf("prog_map_lookup(%s): read error %s\n", 250169562Seric map->map_mname, errstring(errno)); 250269453Seric if (i > 0) 250369453Seric { 250469453Seric char *rval; 250569453Seric 250669453Seric buf[i] = '\0'; 250769453Seric p = strchr(buf, '\n'); 250869453Seric if (p != NULL) 250969453Seric *p = '\0'; 251069453Seric 251169453Seric /* collect the return value */ 251269453Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 251369453Seric rval = map_rewrite(map, name, strlen(name), NULL); 251469453Seric else 251569453Seric rval = map_rewrite(map, buf, strlen(buf), NULL); 251669453Seric 251769453Seric /* now flush any additional output */ 251869453Seric while ((i = read(fd, buf, sizeof buf)) > 0) 251969453Seric continue; 252069453Seric close(fd); 252169453Seric 252269453Seric /* and wait for the process to terminate */ 252369453Seric *statp = waitfor(pid); 252469453Seric 252569453Seric return rval; 252669453Seric } 252769453Seric 252869453Seric close(fd); 252969453Seric *statp = waitfor(pid); 253069453Seric return NULL; 253169453Seric } 253269453Seric /* 253368350Seric ** Sequenced map type. 253468350Seric ** 253568350Seric ** Tries each map in order until something matches, much like 253668350Seric ** implicit. Stores go to the first map in the list that can 253768350Seric ** support storing. 253868350Seric ** 253968350Seric ** This is slightly unusual in that there are two interfaces. 254068350Seric ** The "sequence" interface lets you stack maps arbitrarily. 254168350Seric ** The "switch" interface builds a sequence map by looking 254268350Seric ** at a system-dependent configuration file such as 254368350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 254468350Seric ** 254568350Seric ** We don't need an explicit open, since all maps are 254668350Seric ** opened during startup, including underlying maps. 254768350Seric */ 254868350Seric 254968350Seric /* 255068350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 255168350Seric */ 255268350Seric 255368350Seric bool 255468350Seric seq_map_parse(map, ap) 255568350Seric MAP *map; 255668350Seric char *ap; 255768350Seric { 255868350Seric int maxmap; 255968350Seric 256068350Seric if (tTd(38, 2)) 256168350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 256268350Seric maxmap = 0; 256368350Seric while (*ap != '\0') 256468350Seric { 256568350Seric register char *p; 256668350Seric STAB *s; 256768350Seric 256868350Seric /* find beginning of map name */ 256968350Seric while (isascii(*ap) && isspace(*ap)) 257068350Seric ap++; 257168350Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 257268350Seric continue; 257368350Seric if (*p != '\0') 257468350Seric *p++ = '\0'; 257568350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 257668350Seric p++; 257768350Seric if (*ap == '\0') 257868350Seric { 257968350Seric ap = p; 258068350Seric continue; 258168350Seric } 258268350Seric s = stab(ap, ST_MAP, ST_FIND); 258368350Seric if (s == NULL) 258468350Seric { 258568350Seric syserr("Sequence map %s: unknown member map %s", 258668350Seric map->map_mname, ap); 258768350Seric } 258868350Seric else if (maxmap == MAXMAPSTACK) 258968350Seric { 259068350Seric syserr("Sequence map %s: too many member maps (%d max)", 259168350Seric map->map_mname, MAXMAPSTACK); 259268350Seric maxmap++; 259368350Seric } 259468350Seric else if (maxmap < MAXMAPSTACK) 259568350Seric { 259668350Seric map->map_stack[maxmap++] = &s->s_map; 259768350Seric } 259868350Seric ap = p; 259968350Seric } 260068350Seric return TRUE; 260168350Seric } 260268350Seric 260368350Seric 260468350Seric /* 260568350Seric ** SWITCH_MAP_OPEN -- open a switched map 260668350Seric ** 260768350Seric ** This looks at the system-dependent configuration and builds 260868350Seric ** a sequence map that does the same thing. 260968350Seric ** 261068350Seric ** Every system must define a switch_map_find routine in conf.c 261168350Seric ** that will return the list of service types associated with a 261268350Seric ** given service class. 261368350Seric */ 261468350Seric 261568350Seric bool 261668350Seric switch_map_open(map, mode) 261768350Seric MAP *map; 261868350Seric int mode; 261968350Seric { 262068350Seric int mapno; 262168350Seric int nmaps; 262268350Seric char *maptype[MAXMAPSTACK]; 262368350Seric 262468350Seric if (tTd(38, 2)) 262568350Seric printf("switch_map_open(%s, %s, %d)\n", 262668350Seric map->map_mname, map->map_file, mode); 262768350Seric 262868350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 262968350Seric if (tTd(38, 19)) 263068350Seric { 263168350Seric printf("\tswitch_map_find => %d\n", nmaps); 263268350Seric for (mapno = 0; mapno < nmaps; mapno++) 263368350Seric printf("\t\t%s\n", maptype[mapno]); 263468350Seric } 263568350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 263668350Seric return FALSE; 263768350Seric 263868350Seric for (mapno = 0; mapno < nmaps; mapno++) 263968350Seric { 264068350Seric register STAB *s; 264168350Seric char nbuf[MAXNAME + 1]; 264268350Seric 264368350Seric if (maptype[mapno] == NULL) 264468350Seric continue; 264568350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 264668350Seric s = stab(nbuf, ST_MAP, ST_FIND); 264768350Seric if (s == NULL) 264868350Seric { 264968350Seric syserr("Switch map %s: unknown member map %s", 265068350Seric map->map_mname, nbuf); 265168350Seric } 265268350Seric else 265368350Seric { 265468350Seric map->map_stack[mapno] = &s->s_map; 265568350Seric if (tTd(38, 4)) 265668350Seric printf("\tmap_stack[%d] = %s:%s\n", 265768350Seric mapno, s->s_map.map_class->map_cname, 265868350Seric nbuf); 265968350Seric } 266068350Seric } 266168350Seric return TRUE; 266268350Seric } 266368350Seric 266468350Seric 266568350Seric /* 266668350Seric ** SEQ_MAP_CLOSE -- close all underlying maps 266768350Seric */ 266868350Seric 266969748Seric void 267068350Seric seq_map_close(map) 267168350Seric MAP *map; 267268350Seric { 267368350Seric int mapno; 267468350Seric 267568350Seric if (tTd(38, 20)) 267668350Seric printf("seq_map_close(%s)\n", map->map_mname); 267768350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 267868350Seric { 267968350Seric MAP *mm = map->map_stack[mapno]; 268068350Seric 268168350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 268268350Seric continue; 268368350Seric mm->map_class->map_close(mm); 268468798Seric mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 268568350Seric } 268668350Seric } 268768350Seric 268868350Seric 268968350Seric /* 269068350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 269168350Seric */ 269268350Seric 269368350Seric char * 269468350Seric seq_map_lookup(map, key, args, pstat) 269568350Seric MAP *map; 269668350Seric char *key; 269768350Seric char **args; 269868350Seric int *pstat; 269968350Seric { 270068350Seric int mapno; 270168350Seric int mapbit = 0x01; 270268350Seric 270368350Seric if (tTd(38, 20)) 270468350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 270568350Seric 270668350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 270768350Seric { 270868350Seric MAP *mm = map->map_stack[mapno]; 270968350Seric int stat = 0; 271068350Seric char *rv; 271168350Seric 271268350Seric if (mm == NULL) 271368350Seric continue; 271468350Seric if (!bitset(MF_OPEN, mm->map_mflags)) 271568350Seric { 271668350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 271768350Seric { 271868350Seric *pstat = EX_UNAVAILABLE; 271968350Seric return NULL; 272068350Seric } 272168350Seric continue; 272268350Seric } 272368350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 272468350Seric if (rv != NULL) 272568350Seric return rv; 272668350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 272768350Seric return NULL; 272868350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 272968350Seric { 273068350Seric *pstat = stat; 273168350Seric return NULL; 273268350Seric } 273368350Seric } 273468350Seric return NULL; 273568350Seric } 273668350Seric 273768350Seric 273868350Seric /* 273968350Seric ** SEQ_MAP_STORE -- sequenced map store 274068350Seric */ 274168350Seric 274268350Seric void 274368350Seric seq_map_store(map, key, val) 274468350Seric MAP *map; 274568350Seric char *key; 274668350Seric char *val; 274768350Seric { 274868350Seric int mapno; 274968350Seric 275068350Seric if (tTd(38, 12)) 275168350Seric printf("seq_map_store(%s, %s, %s)\n", 275268350Seric map->map_mname, key, val); 275368350Seric 275468350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 275568350Seric { 275668350Seric MAP *mm = map->map_stack[mapno]; 275768350Seric 275868350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 275968350Seric continue; 276068350Seric 276168350Seric mm->map_class->map_store(mm, key, val); 276268350Seric return; 276368350Seric } 276468350Seric syserr("seq_map_store(%s, %s, %s): no writable map", 276568350Seric map->map_mname, key, val); 276668350Seric } 276768350Seric /* 276869401Seric ** GETCANONNAME -- look up name using service switch 276969401Seric ** 277069401Seric ** Parameters: 277169401Seric ** host -- the host name to look up. 277269401Seric ** hbsize -- the size of the host buffer. 277369401Seric ** trymx -- if set, try MX records. 277469401Seric ** 277569401Seric ** Returns: 277669401Seric ** TRUE -- if the host was found. 277769401Seric ** FALSE -- otherwise. 277869401Seric */ 277969401Seric 278069401Seric bool 278169401Seric getcanonname(host, hbsize, trymx) 278269401Seric char *host; 278369401Seric int hbsize; 278469401Seric bool trymx; 278569401Seric { 278669401Seric int nmaps; 278769401Seric int mapno; 278869401Seric bool found = FALSE; 278969401Seric auto int stat; 279069401Seric char *maptype[MAXMAPSTACK]; 279169401Seric short mapreturn[MAXMAPACTIONS]; 279269401Seric extern int h_errno; 279369401Seric 279469401Seric nmaps = switch_map_find("hosts", maptype, mapreturn); 279569401Seric for (mapno = 0; mapno < nmaps; mapno++) 279669401Seric { 279769401Seric int i; 279869401Seric 279969401Seric if (tTd(38, 20)) 280069401Seric printf("getcanonname(%s), trying %s\n", 280169401Seric host, maptype[mapno]); 280269401Seric if (strcmp("files", maptype[mapno]) == 0) 280369401Seric found = text_getcanonname(host, hbsize, &stat); 280469401Seric #ifdef NIS 280569401Seric else if (strcmp("nis", maptype[mapno]) == 0) 280669401Seric found = nis_getcanonname(host, hbsize, &stat); 280769401Seric #endif 280869401Seric #ifdef NISPLUS 280969401Seric else if (strcmp("nisplus", maptype[mapno]) == 0) 281069401Seric found = nisplus_getcanonname(host, hbsize, &stat); 281169401Seric #endif 281269401Seric #if NAMED_BIND 281369401Seric else if (strcmp("dns", maptype[mapno]) == 0) 281469401Seric found = dns_getcanonname(host, hbsize, trymx, &stat); 281569401Seric #endif 281669401Seric else 281769401Seric { 281869401Seric found = FALSE; 281969401Seric stat = EX_UNAVAILABLE; 282069401Seric } 282169401Seric if (found) 282269401Seric break; 282369401Seric 282469401Seric /* see if we should continue */ 282569401Seric if (stat == EX_TEMPFAIL) 282669401Seric i = MA_TRYAGAIN; 282769401Seric else if (stat == EX_NOHOST) 282869401Seric i = MA_NOTFOUND; 282969401Seric else 283069401Seric i = MA_UNAVAIL; 283169401Seric if (bitset(1 << mapno, mapreturn[i])) 283269401Seric break; 283369401Seric } 283469401Seric 283569401Seric if (found) 283669401Seric { 283769401Seric char *d; 283869401Seric 283969401Seric if (tTd(38, 20)) 284069401Seric printf("getcanonname(%s), found\n", host); 284169401Seric 284269401Seric /* 284369401Seric ** If returned name is still single token, compensate 284469401Seric ** by tagging on $m. This is because some sites set 284569401Seric ** up their DNS or NIS databases wrong. 284669401Seric */ 284769401Seric 284869401Seric if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 284969401Seric { 285069401Seric d = macvalue('m', CurEnv); 285169401Seric if (d != NULL && 285269401Seric hbsize > (int) (strlen(host) + strlen(d) + 1)) 285369401Seric { 285469401Seric if (host[strlen(host) - 1] != '.') 285569401Seric strcat(host, "."); 285669401Seric strcat(host, d); 285769401Seric } 285869401Seric else 285969401Seric { 286069401Seric return FALSE; 286169401Seric } 286269401Seric } 286369401Seric return TRUE; 286469401Seric } 286569401Seric 286669401Seric if (tTd(38, 20)) 286769401Seric printf("getcanonname(%s), failed, stat=%d\n", host, stat); 286869401Seric 286969401Seric #if NAMED_BIND 287069401Seric if (stat == EX_NOHOST) 287169401Seric h_errno = HOST_NOT_FOUND; 287269401Seric else 287369401Seric h_errno = TRY_AGAIN; 287469401Seric #endif 287569401Seric 287669401Seric return FALSE; 287769401Seric } 287869401Seric /* 287960207Seric ** NULL stubs 288060089Seric */ 288160089Seric 288260207Seric bool 288360207Seric null_map_open(map, mode) 288460089Seric MAP *map; 288560207Seric int mode; 288660089Seric { 288760207Seric return TRUE; 288860089Seric } 288960089Seric 289060207Seric void 289160207Seric null_map_close(map) 289260207Seric MAP *map; 289360089Seric { 289460207Seric return; 289560207Seric } 289660089Seric 289760207Seric void 289860207Seric null_map_store(map, key, val) 289960207Seric MAP *map; 290060207Seric char *key; 290160207Seric char *val; 290260089Seric { 290360207Seric return; 290460089Seric } 290568350Seric 290668350Seric 290768350Seric /* 290868350Seric ** BOGUS stubs 290968350Seric */ 291068350Seric 291168350Seric char * 291268350Seric bogus_map_lookup(map, key, args, pstat) 291368350Seric MAP *map; 291468350Seric char *key; 291568350Seric char **args; 291668350Seric int *pstat; 291768350Seric { 291868350Seric *pstat = EX_TEMPFAIL; 291968350Seric return NULL; 292068350Seric } 292168350Seric 292268350Seric MAPCLASS BogusMapClass = 292368350Seric { 292468350Seric "bogus-map", NULL, 0, 292568350Seric NULL, bogus_map_lookup, null_map_store, 292668350Seric null_map_open, null_map_close, 292768350Seric }; 2928