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*69748Seric static char sccsid[] = "@(#)map.c 8.69 (Berkeley) 05/28/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 353*69748Seric 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; 1189*69748Seric char *domain; 119069401Seric char host_record[MAXLINE]; 119169401Seric char buf[MAXNAME]; 119269401Seric char *cname; 119369401Seric extern char *get_column(); 119469401Seric 119569401Seric if (tTd(38, 20)) 119669401Seric printf("nis_getcanonname(%s)\n", name); 119769401Seric 119869401Seric shorten_hostname(name); 119969401Seric 120069401Seric /* we only accept single token search key */ 120169401Seric if (strchr(name, '.')) 120269401Seric { 120369401Seric *statp = EX_NOHOST; 120469401Seric return FALSE; 120569401Seric } 120669401Seric 120769401Seric keylen = strlen(name); 120869401Seric 120969401Seric if (yp_domain == NULL) 121069401Seric yp_get_default_domain(&yp_domain); 121169401Seric makelower(name); 121269401Seric yperr = YPERR_KEY; 121369401Seric if (try0null) 121469401Seric { 121569401Seric yperr = yp_match(yp_domain, "hosts.byname", name, keylen, 121669401Seric &vp, &vsize); 121769401Seric if (yperr == 0) 121869401Seric try1null = FALSE; 121969401Seric } 122069401Seric if (yperr == YPERR_KEY && try1null) 122169401Seric { 122269401Seric keylen++; 122369401Seric yperr = yp_match(yp_domain, "hosts.byname", name, keylen, 122469401Seric &vp, &vsize); 122569401Seric if (yperr == 0) 122669401Seric try0null = FALSE; 122769401Seric } 122869401Seric if (yperr != 0) 122969401Seric { 123069401Seric if (yperr == YPERR_KEY) 123169401Seric *statp = EX_NOHOST; 123269401Seric else if (yperr == YPERR_BUSY) 123369401Seric *statp = EX_TEMPFAIL; 123469401Seric else 123569401Seric *statp = EX_UNAVAILABLE; 123669401Seric return FALSE; 123769401Seric } 123869401Seric strncpy(host_record, vp, vsize); 123969401Seric host_record[vsize] = '\0'; 124069663Seric if (tTd(38, 44)) 124169663Seric printf("got record `%s'\n", host_record); 124269663Seric cname = get_column(host_record, 1, '\0', buf); 124369401Seric if (cname == NULL) 124469401Seric { 124569401Seric /* this should not happen, but.... */ 124669401Seric *statp = EX_NOHOST; 124769401Seric return FALSE; 124869401Seric } 124969401Seric 125069703Seric if (strchr(cname, '.') != NULL) 125169401Seric { 125269703Seric domain = ""; 125369703Seric } 125469703Seric else 125569703Seric { 125669703Seric domain = macvalue('m', CurEnv); 125769703Seric if (domain == NULL) 125869703Seric domain = ""; 125969703Seric } 126069703Seric if (hbsize >= strlen(cname) + strlen(domain) + 1) 126169703Seric { 126269703Seric if (domain[0] == '\0') 126369703Seric strcpy(name, vp); 126469703Seric else 126569703Seric sprintf(name, "%s.%s", vp, domain); 126669401Seric *statp = EX_OK; 126769401Seric return TRUE; 126869401Seric } 126969401Seric *statp = EX_UNAVAILABLE; 127069401Seric return FALSE; 127169401Seric } 127269401Seric 127368350Seric #endif 127468350Seric /* 127568350Seric ** NISPLUS Modules 127668350Seric ** 127768350Seric ** This code donated by Sun Microsystems. 127868350Seric */ 127967848Seric 128068350Seric #ifdef NISPLUS 128168350Seric 128268350Seric #undef NIS /* symbol conflict in nis.h */ 128368350Seric #include <rpcsvc/nis.h> 128468350Seric #include <rpcsvc/nislib.h> 128568350Seric 128668350Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 128768350Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 128868350Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 128968350Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 129068350Seric 129167848Seric /* 129268350Seric ** NISPLUS_MAP_OPEN -- open nisplus table 129367848Seric */ 129467848Seric 129568350Seric bool 129668350Seric nisplus_map_open(map, mode) 129767848Seric MAP *map; 129868350Seric int mode; 129967848Seric { 130068350Seric register char *p; 130168350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 130268350Seric nis_result *res = NULL; 130368350Seric u_int objs_len; 130468350Seric nis_object *obj_ptr; 130568350Seric int retry_cnt, max_col, i; 130668350Seric 130768350Seric if (tTd(38, 2)) 130868350Seric printf("nisplus_map_open(%s, %s, %d)\n", 130968350Seric map->map_mname, map->map_file, mode); 131068350Seric 131168350Seric if (mode != O_RDONLY) 131268350Seric { 131368350Seric errno = ENODEV; 131468350Seric return FALSE; 131568350Seric } 131668350Seric 131768350Seric if (*map->map_file == '\0') 131868350Seric map->map_file = "mail_aliases.org_dir"; 131968350Seric 132068350Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 132168350Seric { 132268350Seric /* set default NISPLUS Domain to $m */ 132368350Seric extern char *nisplus_default_domain(); 132468350Seric 132568350Seric map->map_domain = newstr(nisplus_default_domain()); 132668350Seric if (tTd(38, 2)) 132768350Seric printf("nisplus_map_open(%s): using domain %s\n", 132868350Seric map->map_file, map->map_domain); 132968350Seric } 133068350Seric if (!PARTIAL_NAME(map->map_file)) 133168350Seric map->map_domain = newstr(""); 133268350Seric 133368350Seric /* check to see if this map actually exists */ 133468350Seric if (PARTIAL_NAME(map->map_file)) 133568350Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 133668350Seric else 133768350Seric strcpy(qbuf, map->map_file); 133868350Seric 133968350Seric retry_cnt = 0; 134068350Seric while (res == NULL || res->status != NIS_SUCCESS) 134168350Seric { 134268350Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 134368350Seric switch (res->status) 134468350Seric { 134568350Seric case NIS_SUCCESS: 134668350Seric case NIS_TRYAGAIN: 134768350Seric case NIS_RPCERROR: 134868350Seric case NIS_NAMEUNREACHABLE: 134968350Seric break; 135068350Seric 135168350Seric default: /* all other nisplus errors */ 135268350Seric #if 0 135368350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 135468350Seric syserr("421 Cannot find table %s.%s: %s", 135568350Seric map->map_file, map->map_domain, 135668350Seric nis_sperrno(res->status)); 135768350Seric #endif 135868350Seric errno = EBADR; 135968350Seric return FALSE; 136068350Seric } 136168350Seric sleep(2); /* try not to overwhelm hosed server */ 136268350Seric if (retry_cnt++ > 4) 136368350Seric { 136468350Seric errno = EBADR; 136568350Seric return FALSE; 136668350Seric } 136768350Seric } 136868350Seric 136968350Seric if (NIS_RES_NUMOBJ(res) != 1 || 137068350Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 137168350Seric { 137268350Seric if (tTd(38, 10)) 137368350Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 137468350Seric #if 0 137568350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 137668350Seric syserr("421 %s.%s: %s is not a table", 137768350Seric map->map_file, map->map_domain, 137868350Seric nis_sperrno(res->status)); 137968350Seric #endif 138068350Seric errno = EBADR; 138168350Seric return FALSE; 138268350Seric } 138368350Seric /* default key column is column 0 */ 138468350Seric if (map->map_keycolnm == NULL) 138568350Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 138668350Seric 138768350Seric max_col = COL_MAX(res); 138868350Seric 138968350Seric /* verify the key column exist */ 139068350Seric for (i=0; i< max_col; i++) 139168350Seric { 139268350Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 139368350Seric break; 139468350Seric } 139568350Seric if (i == max_col) 139668350Seric { 139768350Seric if (tTd(38, 2)) 139868350Seric printf("nisplus_map_open(%s): can not find key column %s\n", 139968350Seric map->map_file, map->map_keycolnm); 140068350Seric errno = EBADR; 140168350Seric return FALSE; 140268350Seric } 140368350Seric 140468350Seric /* default value column is the last column */ 140568350Seric if (map->map_valcolnm == NULL) 140668350Seric { 140768350Seric map->map_valcolno = max_col - 1; 140868350Seric return TRUE; 140968350Seric } 141068350Seric 141168350Seric for (i=0; i< max_col; i++) 141268350Seric { 141368350Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 141468350Seric { 141568350Seric map->map_valcolno = i; 141668350Seric return TRUE; 141768350Seric } 141868350Seric } 141968350Seric 142068350Seric if (tTd(38, 2)) 142168350Seric printf("nisplus_map_open(%s): can not find column %s\n", 142268350Seric map->map_file, map->map_keycolnm); 142368350Seric errno = EBADR; 142468350Seric return FALSE; 142567848Seric } 142667848Seric 142767848Seric 142867848Seric /* 142968350Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 143067848Seric */ 143167848Seric 143268350Seric char * 143368350Seric nisplus_map_lookup(map, name, av, statp) 143467848Seric MAP *map; 143568350Seric char *name; 143668350Seric char **av; 143768350Seric int *statp; 143867848Seric { 143968350Seric char *vp; 144068350Seric auto int vsize; 144168350Seric int buflen; 144268350Seric char search_key[MAXNAME + 1]; 144368350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 144468350Seric nis_result *result; 144568350Seric 144668350Seric if (tTd(38, 20)) 144768350Seric printf("nisplus_map_lookup(%s, %s)\n", 144868350Seric map->map_mname, name); 144968350Seric 145068350Seric if (!bitset(MF_OPEN, map->map_mflags)) 145168350Seric { 145268350Seric if (nisplus_map_open(map, O_RDONLY)) 145368350Seric map->map_mflags |= MF_OPEN; 145468350Seric else 145568350Seric { 145668350Seric *statp = EX_UNAVAILABLE; 145768350Seric return NULL; 145868350Seric } 145968350Seric } 146068350Seric 146168350Seric buflen = strlen(name); 146268350Seric if (buflen > sizeof search_key - 1) 146368350Seric buflen = sizeof search_key - 1; 146468350Seric bcopy(name, search_key, buflen + 1); 146568350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 146668350Seric makelower(search_key); 146768350Seric 146868350Seric /* construct the query */ 146968350Seric if (PARTIAL_NAME(map->map_file)) 147068350Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 147168350Seric search_key, map->map_file, map->map_domain); 147268350Seric else 147368350Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 147468350Seric search_key, map->map_file); 147568350Seric 147668350Seric if (tTd(38, 20)) 147768350Seric printf("qbuf=%s\n", qbuf); 147868350Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 147968350Seric if (result->status == NIS_SUCCESS) 148068350Seric { 148168350Seric int count; 148268350Seric char *str; 148368350Seric 148468350Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 148568350Seric { 148668350Seric if (LogLevel > 10) 148768350Seric syslog(LOG_WARNING, 148868350Seric "%s:Lookup error, expected 1 entry, got (%d)", 148968350Seric map->map_file, count); 149068350Seric 149168350Seric /* ignore second entry */ 149268350Seric if (tTd(38, 20)) 149368350Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 149468350Seric name, count); 149568350Seric } 149668350Seric 149768350Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 149868350Seric /* set the length of the result */ 149968350Seric if (vp == NULL) 150068350Seric vp = ""; 150168350Seric vsize = strlen(vp); 150268350Seric if (tTd(38, 20)) 150368350Seric printf("nisplus_map_lookup(%s), found %s\n", 150468350Seric name, vp); 150568350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 150668350Seric str = map_rewrite(map, name, strlen(name), NULL); 150768350Seric else 150868350Seric str = map_rewrite(map, vp, vsize, av); 150968350Seric nis_freeresult(result); 151068350Seric #ifdef MAP_EXIT_STAT 151168350Seric *statp = EX_OK; 151268350Seric #endif 151368350Seric return str; 151468350Seric } 151568350Seric else 151668350Seric { 151768350Seric #ifdef MAP_EXIT_STAT 151868350Seric if (result->status == NIS_NOTFOUND) 151968350Seric *statp = EX_NOTFOUND; 152068350Seric else if (result->status == NIS_TRYAGAIN) 152168350Seric *statp = EX_TEMPFAIL; 152268350Seric else 152368350Seric { 152468350Seric *statp = EX_UNAVAILABLE; 152568350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 152668350Seric } 152768350Seric #else 152868350Seric if ((result->status != NIS_NOTFOUND) && 152968350Seric (result->status != NIS_TRYAGAIN)) 153068350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 153168350Seric #endif 153268350Seric } 153368350Seric if (tTd(38, 20)) 153468350Seric printf("nisplus_map_lookup(%s), failed\n", name); 153568350Seric nis_freeresult(result); 153668350Seric return NULL; 153767848Seric } 153867848Seric 153968350Seric 154069401Seric 154169401Seric /* 154269401Seric ** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 154369401Seric */ 154469401Seric 154569401Seric bool 154669401Seric nisplus_getcanonname(name, hbsize, statp) 154769401Seric char *name; 154869401Seric int hbsize; 154969401Seric int *statp; 155069401Seric { 155169401Seric char *vp; 155269401Seric auto int vsize; 155369401Seric int buflen; 155469477Seric char buf[MAXLINE + NIS_MAXNAMELEN]; 155569401Seric nis_result *result; 155669401Seric char *p; 155769401Seric int len; 155869401Seric 155969401Seric shorten_hostname(name); 156069401Seric 156169401Seric p = strchr(name, '.'); 156269401Seric if (p == NULL) 156369401Seric { 156469401Seric /* single token */ 156569477Seric sprintf(buf, "[name=%s],hosts.org_dir", name); 156669401Seric } 156769401Seric else if (p[1] != '\0') 156869401Seric { 156969401Seric /* multi token -- take only first token in name buf */ 157069401Seric *p = '\0'; 157169477Seric sprintf(buf, "[name=%s],hosts.org_dir.%s", name, &p[1]); 157269401Seric } 157369401Seric else 157469401Seric { 157569401Seric *statp = EX_NOHOST; 157669401Seric return FALSE; 157769401Seric } 157869401Seric 157969401Seric if (tTd(38, 20)) 158069478Seric printf("\nnisplus_getcanoname(%s), qbuf=%s\n", 158169478Seric name, buf); 158269401Seric 158369477Seric result = nis_list(buf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 158469401Seric NULL, NULL); 158569401Seric 158669401Seric if (result->status == NIS_SUCCESS) 158769401Seric { 158869401Seric int count; 158969401Seric char *str; 159069401Seric char *domain; 159169401Seric 159269401Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 159369401Seric { 159469401Seric #ifdef LOG 159569401Seric if (LogLevel > 10) 159669401Seric syslog(LOG_WARNING, 159769401Seric "nisplus_getcanonname: Lookup error, expected 1 entry, got (%d)", 159869401Seric count); 159969401Seric #endif 160069401Seric 160169401Seric /* ignore second entry */ 160269401Seric if (tTd(38, 20)) 160369401Seric printf("nisplus_getcanoname(%s), got %d entries, addtional entries ignores\n", name); 160469401Seric } 160569401Seric 160669401Seric if (tTd(38, 20)) 160769401Seric printf("nisplus_getcanoname(%s), found in directory \"%s\"\n", 160869401Seric name, (NIS_RES_OBJECT(result))->zo_domain); 160969401Seric 161069401Seric 161169401Seric vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 161269401Seric vsize = strlen(vp); 161369401Seric if (tTd(38, 20)) 161469401Seric printf("nisplus_getcanonname(%s), found %s\n", 161569401Seric name, vp); 161669703Seric if (strchr(vp, '.') != NULL) 161769703Seric { 161869636Seric domain = ""; 161969703Seric } 162069703Seric else 162169703Seric { 162269703Seric domain = macvalue('m', CurEnv); 162369703Seric if (domain == NULL) 162469703Seric domain = ""; 162569703Seric } 162669636Seric if (hbsize > vsize + (int) strlen(domain) + 1) 162769401Seric { 162869636Seric if (domain[0] == '\0') 162969636Seric strcpy(name, vp); 163069636Seric else 163169636Seric sprintf(name, "%s.%s", vp, domain); 163269401Seric *statp = EX_OK; 163369401Seric } 163469401Seric else 163569401Seric *statp = EX_NOHOST; 163669401Seric nis_freeresult(result); 163769401Seric return TRUE; 163869401Seric } 163969401Seric else 164069401Seric { 164169401Seric if (result->status == NIS_NOTFOUND) 164269401Seric *statp = EX_NOHOST; 164369401Seric else if (result->status == NIS_TRYAGAIN) 164469401Seric *statp = EX_TEMPFAIL; 164569401Seric else 164669401Seric *statp = EX_UNAVAILABLE; 164769401Seric } 164869401Seric if (tTd(38, 20)) 164969401Seric printf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 165069401Seric name, result->status, *statp); 165169401Seric nis_freeresult(result); 165269401Seric return FALSE; 165369401Seric } 165469401Seric 165569401Seric 165668350Seric char * 165768350Seric nisplus_default_domain() 165868350Seric { 165968528Seric static char default_domain[MAXNAME + 1] = ""; 166068350Seric char *p; 166168350Seric 166268350Seric if (default_domain[0] != '\0') 166368350Seric return(default_domain); 166468350Seric 166568458Seric p = nis_local_directory(); 166668350Seric strcpy(default_domain, p); 166768458Seric return default_domain; 166868350Seric } 166968350Seric 167068350Seric #endif /* NISPLUS */ 167167848Seric /* 167268350Seric ** HESIOD Modules 167368350Seric */ 167468350Seric 167568350Seric #ifdef HESIOD 167668350Seric 167768350Seric #include <hesiod.h> 167868350Seric 167968350Seric char * 168068350Seric hes_map_lookup(map, name, av, statp) 168168350Seric MAP *map; 168268350Seric char *name; 168368350Seric char **av; 168468350Seric int *statp; 168568350Seric { 168668350Seric char **hp; 168768350Seric int i; 168868350Seric 168968350Seric if (tTd(38, 20)) 169068350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 169168350Seric 169269688Seric if (name[0] == '\\') 169369688Seric { 169469688Seric char *np; 169569688Seric int nl; 169669688Seric char nbuf[MAXNAME]; 169769688Seric 169869688Seric nl = strlen(name); 169969688Seric if (nl < sizeof nbuf - 1) 170069688Seric np = nbuf; 170169688Seric else 170269688Seric np = xalloc(strlen(name) + 2); 170369688Seric np[0] = '\\'; 170469688Seric strcpy(&np[1], name); 170569688Seric hp = hes_resolve(np, map->map_file); 170669688Seric if (np != nbuf) 170769688Seric free(np); 170869688Seric } 170969688Seric else 171069688Seric { 171169688Seric hp = hes_resolve(name, map->map_file); 171269688Seric } 171369623Seric if (hp == NULL || hp[0] == NULL) 171468350Seric return NULL; 171568350Seric 171669623Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 171769623Seric return map_rewrite(map, name, strlen(name), NULL); 171869623Seric else 171969623Seric return map_rewrite(map, hp[0], strlen(hp[0]), av); 172068350Seric } 172168350Seric 172268350Seric #endif 172368350Seric /* 172468350Seric ** NeXT NETINFO Modules 172568350Seric */ 172668350Seric 172768350Seric #ifdef NETINFO 172868350Seric 172968350Seric #define NETINFO_DEFAULT_DIR "/aliases" 173068350Seric #define NETINFO_DEFAULT_PROPERTY "members" 173168350Seric 173268350Seric 173368350Seric /* 173468350Seric ** NI_MAP_OPEN -- open NetInfo Aliases 173568350Seric */ 173668350Seric 173768350Seric bool 173868350Seric ni_map_open(map, mode) 173968350Seric MAP *map; 174068350Seric int mode; 174168350Seric { 174268350Seric char *p; 174368350Seric 174468350Seric if (tTd(38, 20)) 174568350Seric printf("ni_map_open: %s\n", map->map_file); 174668350Seric 174768350Seric if (*map->map_file == '\0') 174868350Seric map->map_file = NETINFO_DEFAULT_DIR; 174968350Seric 175068350Seric if (map->map_valcolnm == NULL) 175168350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 175268350Seric 175368350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 175468350Seric map->map_coldelim = ','; 175568350Seric 175668350Seric return TRUE; 175768350Seric } 175868350Seric 175968350Seric 176068350Seric /* 176168350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 176268350Seric */ 176368350Seric 176468350Seric char * 176568350Seric ni_map_lookup(map, name, av, statp) 176668350Seric MAP *map; 176768350Seric char *name; 176868350Seric char **av; 176968350Seric int *statp; 177068350Seric { 177168350Seric char *res; 177268350Seric char *propval; 177368350Seric extern char *ni_propval(); 177468350Seric 177568350Seric if (tTd(38, 20)) 177668350Seric printf("ni_map_lookup(%s, %s)\n", 177768350Seric map->map_mname, name); 177868350Seric 177968350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 178068350Seric map->map_valcolnm, map->map_coldelim); 178168350Seric 178268350Seric if (propval == NULL) 178368350Seric return NULL; 178468350Seric 178568350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 178668350Seric res = map_rewrite(map, name, strlen(name), NULL); 178768350Seric else 178868350Seric res = map_rewrite(map, propval, strlen(propval), av); 178968350Seric free(propval); 179068350Seric return res; 179168350Seric } 179268350Seric 179368350Seric #endif 179468350Seric /* 179568350Seric ** TEXT (unindexed text file) Modules 179668350Seric ** 179768350Seric ** This code donated by Sun Microsystems. 179868350Seric */ 179968350Seric 180068350Seric 180168350Seric /* 180268350Seric ** TEXT_MAP_OPEN -- open text table 180368350Seric */ 180468350Seric 180568350Seric bool 180668350Seric text_map_open(map, mode) 180768350Seric MAP *map; 180868350Seric int mode; 180968350Seric { 181068350Seric struct stat sbuf; 181168350Seric 181268350Seric if (tTd(38, 2)) 181368350Seric printf("text_map_open(%s, %s, %d)\n", 181468350Seric map->map_mname, map->map_file, mode); 181568350Seric 181668350Seric if (mode != O_RDONLY) 181768350Seric { 181868350Seric errno = ENODEV; 181968350Seric return FALSE; 182068350Seric } 182168350Seric 182268350Seric if (*map->map_file == '\0') 182368350Seric { 182468350Seric if (tTd(38, 2)) 182568350Seric printf("text_map_open: file name required\n"); 182668350Seric return FALSE; 182768350Seric } 182868350Seric 182968350Seric if (map->map_file[0] != '/') 183068350Seric { 183168350Seric if (tTd(38, 2)) 183268350Seric printf("text_map_open(%s): file name must be fully qualified\n", 183368350Seric map->map_file); 183468350Seric return FALSE; 183568350Seric } 183668350Seric /* check to see if this map actually accessable */ 183768350Seric if (access(map->map_file, R_OK) <0) 183868350Seric return FALSE; 183968350Seric 184068350Seric /* check to see if this map actually exist */ 184168350Seric if (stat(map->map_file, &sbuf) <0) 184268350Seric { 184368350Seric if (tTd(38, 2)) 184468350Seric printf("text_map_open(%s): can not stat %s\n", 184568350Seric map->map_file, map->map_file); 184668350Seric return FALSE; 184768350Seric } 184868350Seric 184968350Seric if (!S_ISREG(sbuf.st_mode)) 185068350Seric { 185168350Seric if (tTd(38, 2)) 185268350Seric printf("text_map_open(%s): %s is not a file\n", 185368350Seric map->map_file, map->map_file); 185468350Seric return FALSE; 185568350Seric } 185668350Seric 185768350Seric if (map->map_keycolnm == NULL) 185868350Seric map->map_keycolno = 0; 185968350Seric else 186068350Seric { 186168350Seric if (!isdigit(*map->map_keycolnm)) 186268350Seric { 186368350Seric if (tTd(38, 2)) 186468350Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 186568350Seric map->map_file, map->map_keycolnm); 186668350Seric return FALSE; 186768350Seric } 186868350Seric map->map_keycolno = atoi(map->map_keycolnm); 186968350Seric } 187068350Seric 187168350Seric if (map->map_valcolnm == NULL) 187268350Seric map->map_valcolno = 0; 187368350Seric else 187468350Seric { 187568350Seric if (!isdigit(*map->map_valcolnm)) 187668350Seric { 187768350Seric if (tTd(38, 2)) 187868350Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 187968350Seric map->map_file, map->map_valcolnm); 188068350Seric return FALSE; 188168350Seric } 188268350Seric map->map_valcolno = atoi(map->map_valcolnm); 188368350Seric } 188468350Seric 188568350Seric if (tTd(38, 2)) 188668350Seric { 188768520Seric printf("text_map_open(%s): delimiter = ", 188868520Seric map->map_file); 188968520Seric if (map->map_coldelim == '\0') 189068520Seric printf("(white space)\n"); 189168520Seric else 189268520Seric printf("%c\n", map->map_coldelim); 189368350Seric } 189468350Seric 189568350Seric return TRUE; 189668350Seric } 189768350Seric 189868350Seric 189968350Seric /* 190068350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 190168350Seric */ 190268350Seric 190368350Seric char * 190468350Seric text_map_lookup(map, name, av, statp) 190568350Seric MAP *map; 190668350Seric char *name; 190768350Seric char **av; 190868350Seric int *statp; 190968350Seric { 191068350Seric char *vp; 191168350Seric auto int vsize; 191268350Seric int buflen; 191368350Seric char search_key[MAXNAME + 1]; 191468350Seric char linebuf[MAXLINE]; 191568350Seric FILE *f; 191668528Seric char buf[MAXNAME + 1]; 191768350Seric char delim; 191868350Seric int key_idx; 191968350Seric bool found_it; 192068350Seric extern char *get_column(); 192168350Seric 192268350Seric 192368350Seric found_it = FALSE; 192468350Seric if (tTd(38, 20)) 192568350Seric printf("text_map_lookup(%s)\n", name); 192668350Seric 192768350Seric buflen = strlen(name); 192868350Seric if (buflen > sizeof search_key - 1) 192968350Seric buflen = sizeof search_key - 1; 193068350Seric bcopy(name, search_key, buflen + 1); 193168350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 193268350Seric makelower(search_key); 193368350Seric 193468350Seric f = fopen(map->map_file, "r"); 193568350Seric if (f == NULL) 193668350Seric { 193768350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 193868350Seric *statp = EX_UNAVAILABLE; 193968350Seric return NULL; 194068350Seric } 194168350Seric key_idx = map->map_keycolno; 194268350Seric delim = map->map_coldelim; 194368350Seric while (fgets(linebuf, MAXLINE, f)) 194468350Seric { 194568350Seric char *lf; 194668350Seric if (linebuf[0] == '#') 194768350Seric continue; /* skip comment line */ 194868350Seric if (lf = strchr(linebuf, '\n')) 194968350Seric *lf = '\0'; 195068350Seric if (!strcasecmp(search_key, 195168350Seric get_column(linebuf, key_idx, delim, buf))) 195268350Seric { 195368350Seric found_it = TRUE; 195468350Seric break; 195568350Seric } 195668350Seric } 195768350Seric fclose(f); 195868350Seric if (!found_it) 195968350Seric { 196068350Seric #ifdef MAP_EXIT_STAT 196168350Seric *statp = EX_NOTFOUND; 196268350Seric #endif 196368350Seric return(NULL); 196468350Seric } 196568350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 196668350Seric vsize = strlen(vp); 196768350Seric #ifdef MAP_EXIT_STAT 196868350Seric *statp = EX_OK; 196968350Seric #endif 197068350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 197168350Seric return map_rewrite(map, name, strlen(name), NULL); 197268350Seric else 197368350Seric return map_rewrite(map, vp, vsize, av); 197468350Seric } 197569401Seric 197669401Seric 197769401Seric /* 197869401Seric ** TEXT_GETCANONNAME -- look up canonical name in hosts file 197969401Seric */ 198069401Seric 198169401Seric bool 198269401Seric text_getcanonname(name, hbsize, statp) 198369401Seric char *name; 198469401Seric int hbsize; 198569401Seric int *statp; 198669401Seric { 198769401Seric int key_idx; 198869401Seric char *cname; 198969401Seric bool found; 199069401Seric FILE *f; 199169401Seric char linebuf[MAXLINE]; 199269401Seric char cbuf[MAXNAME + 1]; 199369401Seric char buf[MAXNAME + 1]; 199469401Seric extern char *get_column(); 199569401Seric 199669401Seric shorten_hostname(name); 199769401Seric 199869401Seric /* we only accept single token search key */ 199969401Seric if (strchr(name, '.') != NULL) 200069401Seric { 200169401Seric *statp = EX_NOHOST; 200269401Seric return FALSE; 200369401Seric } 200469401Seric 200569401Seric found = FALSE; 200669401Seric 200769401Seric f = fopen(HostsFile, "r"); 200869401Seric if (f == NULL) 200969401Seric { 201069401Seric #ifdef MAP_EXIT_STAT 201169401Seric *statp = EX_UNAVAILABLE; 201269401Seric #endif 201369401Seric return FALSE; 201469401Seric } 201569401Seric while (!found && fgets(linebuf, MAXLINE, f) != NULL) 201669401Seric { 201769401Seric char *p; 201869401Seric 201969401Seric if (linebuf[0] == '#') 202069401Seric continue; 202169401Seric if ((p = strchr(linebuf, '\n')) != NULL) 202269401Seric *p = '\0'; 202369663Seric cname = get_column(linebuf, 1, '\0', cbuf); 202469401Seric if (cname != NULL && strcasecmp(name, cname) == 0) 202569401Seric { 202669401Seric found = TRUE; 202769401Seric break; 202869401Seric } 202969401Seric 203069401Seric key_idx = 2; 203169663Seric while ((p = get_column(linebuf, key_idx, '\0', buf)) != NULL) 203269401Seric { 203369401Seric if (strcasecmp(name, p) == 0) 203469401Seric { 203569401Seric found = TRUE; 203669401Seric break; 203769401Seric } 203869401Seric key_idx++; 203969401Seric } 204069401Seric } 204169401Seric fclose(f); 204269401Seric if (!found) 204369401Seric { 204469401Seric *statp = EX_NOHOST; 204569401Seric return FALSE; 204669401Seric } 204769401Seric 204869401Seric if (hbsize >= strlen(cname)) 204969401Seric { 205069401Seric strcpy(name, cname); 205169401Seric *statp = EX_OK; 205269401Seric return TRUE; 205369401Seric } 205469401Seric *statp = EX_UNAVAILABLE; 205569401Seric return FALSE; 205669401Seric } 205768350Seric /* 205860089Seric ** STAB (Symbol Table) Modules 205960089Seric */ 206060089Seric 206160089Seric 206260089Seric /* 206360207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 206460089Seric */ 206560089Seric 206660089Seric char * 206761707Seric stab_map_lookup(map, name, av, pstat) 206860089Seric register MAP *map; 206960089Seric char *name; 207061707Seric char **av; 207161707Seric int *pstat; 207260089Seric { 207360089Seric register STAB *s; 207460089Seric 207560537Seric if (tTd(38, 20)) 207668350Seric printf("stab_lookup(%s, %s)\n", 207768350Seric map->map_mname, name); 207860089Seric 207960089Seric s = stab(name, ST_ALIAS, ST_FIND); 208060089Seric if (s != NULL) 208160089Seric return (s->s_alias); 208260089Seric return (NULL); 208360089Seric } 208460089Seric 208560089Seric 208660089Seric /* 208760207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 208860089Seric */ 208960089Seric 209060089Seric void 209160089Seric stab_map_store(map, lhs, rhs) 209260089Seric register MAP *map; 209360089Seric char *lhs; 209460089Seric char *rhs; 209560089Seric { 209660089Seric register STAB *s; 209760089Seric 209860089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 209960089Seric s->s_alias = newstr(rhs); 210060089Seric } 210160089Seric 210260089Seric 210360089Seric /* 210460207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 210560207Seric ** 210660207Seric ** This is a wierd case -- it is only intended as a fallback for 210760207Seric ** aliases. For this reason, opens for write (only during a 210860207Seric ** "newaliases") always fails, and opens for read open the 210960207Seric ** actual underlying text file instead of the database. 211060089Seric */ 211160089Seric 211260089Seric bool 211360089Seric stab_map_open(map, mode) 211460089Seric register MAP *map; 211560089Seric int mode; 211660089Seric { 211763835Seric FILE *af; 211864284Seric struct stat st; 211963835Seric 212060537Seric if (tTd(38, 2)) 212168350Seric printf("stab_map_open(%s, %s)\n", 212268350Seric map->map_mname, map->map_file); 212360089Seric 212460089Seric if (mode != O_RDONLY) 212560207Seric { 212660207Seric errno = ENODEV; 212760089Seric return FALSE; 212860207Seric } 212960089Seric 213063835Seric af = fopen(map->map_file, "r"); 213163835Seric if (af == NULL) 213263835Seric return FALSE; 213368350Seric readaliases(map, af, FALSE, FALSE); 213464284Seric 213564284Seric if (fstat(fileno(af), &st) >= 0) 213664284Seric map->map_mtime = st.st_mtime; 213763835Seric fclose(af); 213863835Seric 213960089Seric return TRUE; 214060089Seric } 214160089Seric /* 214260089Seric ** Implicit Modules 214356822Seric ** 214460089Seric ** Tries several types. For back compatibility of aliases. 214556822Seric */ 214656822Seric 214760089Seric 214860089Seric /* 214960207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 215060089Seric */ 215160089Seric 215260089Seric char * 215360089Seric impl_map_lookup(map, name, av, pstat) 215460089Seric MAP *map; 215560089Seric char *name; 215656822Seric char **av; 215760089Seric int *pstat; 215856822Seric { 215960537Seric if (tTd(38, 20)) 216068350Seric printf("impl_map_lookup(%s, %s)\n", 216168350Seric map->map_mname, name); 216256822Seric 216360089Seric #ifdef NEWDB 216460207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 216560089Seric return db_map_lookup(map, name, av, pstat); 216660089Seric #endif 216760089Seric #ifdef NDBM 216860207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 216960089Seric return ndbm_map_lookup(map, name, av, pstat); 217060089Seric #endif 217160089Seric return stab_map_lookup(map, name, av, pstat); 217260089Seric } 217360089Seric 217460089Seric /* 217560207Seric ** IMPL_MAP_STORE -- store in open databases 217660089Seric */ 217760089Seric 217860089Seric void 217960089Seric impl_map_store(map, lhs, rhs) 218060089Seric MAP *map; 218160089Seric char *lhs; 218260089Seric char *rhs; 218360089Seric { 218460089Seric #ifdef NEWDB 218560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 218660089Seric db_map_store(map, lhs, rhs); 218760089Seric #endif 218860089Seric #ifdef NDBM 218960207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 219060089Seric ndbm_map_store(map, lhs, rhs); 219160089Seric #endif 219260089Seric stab_map_store(map, lhs, rhs); 219360089Seric } 219460089Seric 219560089Seric /* 219660089Seric ** IMPL_MAP_OPEN -- implicit database open 219760089Seric */ 219860089Seric 219960089Seric bool 220060089Seric impl_map_open(map, mode) 220160089Seric MAP *map; 220260089Seric int mode; 220360089Seric { 220460089Seric struct stat stb; 220560089Seric 220660537Seric if (tTd(38, 2)) 220768350Seric printf("impl_map_open(%s, %s, %d)\n", 220868350Seric map->map_mname, map->map_file, mode); 220960089Seric 221060089Seric if (stat(map->map_file, &stb) < 0) 221156822Seric { 221260089Seric /* no alias file at all */ 221364718Seric if (tTd(38, 3)) 221464718Seric printf("no map file\n"); 221560089Seric return FALSE; 221656822Seric } 221756822Seric 221860089Seric #ifdef NEWDB 221960207Seric map->map_mflags |= MF_IMPL_HASH; 222060089Seric if (hash_map_open(map, mode)) 222156822Seric { 222264250Seric #if defined(NDBM) && defined(NIS) 222369651Seric if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 222460207Seric #endif 222560207Seric return TRUE; 222660089Seric } 222760207Seric else 222860207Seric map->map_mflags &= ~MF_IMPL_HASH; 222960089Seric #endif 223060089Seric #ifdef NDBM 223160207Seric map->map_mflags |= MF_IMPL_NDBM; 223260089Seric if (ndbm_map_open(map, mode)) 223360089Seric { 223460089Seric return TRUE; 223560089Seric } 223660207Seric else 223760207Seric map->map_mflags &= ~MF_IMPL_NDBM; 223860089Seric #endif 223956822Seric 224064650Seric #if defined(NEWDB) || defined(NDBM) 224160089Seric if (Verbose) 224260089Seric message("WARNING: cannot open alias database %s", map->map_file); 224364964Seric #else 224464964Seric if (mode != O_RDONLY) 224564964Seric usrerr("Cannot rebuild aliases: no database format defined"); 224660207Seric #endif 224760089Seric 224860207Seric return stab_map_open(map, mode); 224956822Seric } 225060089Seric 225160207Seric 225260089Seric /* 225360207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 225460089Seric */ 225560089Seric 225660089Seric void 225760207Seric impl_map_close(map) 225860089Seric MAP *map; 225960089Seric { 226068350Seric if (tTd(38, 20)) 226168350Seric printf("impl_map_close(%s, %s, %x)\n", 226268350Seric map->map_mname, map->map_file, map->map_mflags); 226360089Seric #ifdef NEWDB 226460207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 226560089Seric { 226660207Seric db_map_close(map); 226760207Seric map->map_mflags &= ~MF_IMPL_HASH; 226860089Seric } 226960089Seric #endif 227060089Seric 227160089Seric #ifdef NDBM 227260207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 227360089Seric { 227460207Seric ndbm_map_close(map); 227560207Seric map->map_mflags &= ~MF_IMPL_NDBM; 227660089Seric } 227760089Seric #endif 227860089Seric } 227960207Seric /* 228068350Seric ** User map class. 228168350Seric ** 228268350Seric ** Provides access to the system password file. 228368350Seric */ 228468350Seric 228568350Seric /* 228668350Seric ** USER_MAP_OPEN -- open user map 228768350Seric ** 228868350Seric ** Really just binds field names to field numbers. 228968350Seric */ 229068350Seric 229168350Seric bool 229268350Seric user_map_open(map, mode) 229368350Seric MAP *map; 229468350Seric int mode; 229568350Seric { 229668350Seric if (tTd(38, 2)) 229768350Seric printf("user_map_open(%s)\n", map->map_mname); 229868350Seric 229968350Seric if (mode != O_RDONLY) 230068350Seric { 230168350Seric /* issue a pseudo-error message */ 230268350Seric #ifdef ENOSYS 230368350Seric errno = ENOSYS; 230468350Seric #else 230568350Seric # ifdef EFTYPE 230668350Seric errno = EFTYPE; 230768350Seric # else 230868350Seric errno = ENXIO; 230968350Seric # endif 231068350Seric #endif 231168350Seric return FALSE; 231268350Seric } 231368350Seric if (map->map_valcolnm == NULL) 231468350Seric /* nothing */ ; 231568350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 231668350Seric map->map_valcolno = 1; 231768350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 231868350Seric map->map_valcolno = 2; 231968350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 232068350Seric map->map_valcolno = 3; 232168350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 232268350Seric map->map_valcolno = 4; 232368350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 232468350Seric map->map_valcolno = 5; 232568350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 232668350Seric map->map_valcolno = 6; 232768350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 232868350Seric map->map_valcolno = 7; 232968350Seric else 233068350Seric { 233168350Seric syserr("User map %s: unknown column name %s", 233268350Seric map->map_mname, map->map_valcolnm); 233368350Seric return FALSE; 233468350Seric } 233568350Seric return TRUE; 233668350Seric } 233768350Seric 233868350Seric 233968350Seric /* 234068350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 234168350Seric */ 234268350Seric 234368350Seric char * 234468350Seric user_map_lookup(map, key, av, statp) 234568350Seric MAP *map; 234668350Seric char *key; 234768350Seric char **av; 234868350Seric int *statp; 234968350Seric { 235068350Seric struct passwd *pw; 235168350Seric 235268350Seric if (tTd(38, 20)) 235368350Seric printf("user_map_lookup(%s, %s)\n", 235468350Seric map->map_mname, key); 235568350Seric 235668693Seric pw = sm_getpwnam(key); 235768350Seric if (pw == NULL) 235868350Seric return NULL; 235968350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 236068350Seric return map_rewrite(map, key, strlen(key), NULL); 236168350Seric else 236268350Seric { 236368433Seric char *rwval = NULL; 236468350Seric char buf[30]; 236568350Seric 236668350Seric switch (map->map_valcolno) 236768350Seric { 236868350Seric case 0: 236968350Seric case 1: 237068350Seric rwval = pw->pw_name; 237168350Seric break; 237268350Seric 237368350Seric case 2: 237468350Seric rwval = pw->pw_passwd; 237568350Seric break; 237668350Seric 237768350Seric case 3: 237868350Seric sprintf(buf, "%d", pw->pw_uid); 237968350Seric rwval = buf; 238068350Seric break; 238168350Seric 238268350Seric case 4: 238368350Seric sprintf(buf, "%d", pw->pw_gid); 238468350Seric rwval = buf; 238568350Seric break; 238668350Seric 238768350Seric case 5: 238868350Seric rwval = pw->pw_gecos; 238968350Seric break; 239068350Seric 239168350Seric case 6: 239268350Seric rwval = pw->pw_dir; 239368350Seric break; 239468350Seric 239568350Seric case 7: 239668350Seric rwval = pw->pw_shell; 239768350Seric break; 239868350Seric } 239968350Seric return map_rewrite(map, rwval, strlen(rwval), av); 240068350Seric } 240168350Seric } 240268350Seric /* 240368350Seric ** BESTMX -- find the best MX for a name 240468350Seric ** 240568350Seric ** This is really a hack, but I don't see any obvious way 240668350Seric ** to generalize it at the moment. 240768350Seric */ 240868350Seric 240968350Seric #if NAMED_BIND 241068350Seric 241168350Seric char * 241268350Seric bestmx_map_lookup(map, name, av, statp) 241368350Seric MAP *map; 241468350Seric char *name; 241568350Seric char **av; 241668350Seric int *statp; 241768350Seric { 241868350Seric int nmx; 241968350Seric auto int rcode; 242068350Seric char *mxhosts[MAXMXHOSTS + 1]; 242168350Seric 242268350Seric nmx = getmxrr(name, mxhosts, FALSE, &rcode); 242368350Seric if (nmx <= 0) 242468350Seric return NULL; 242568350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 242668350Seric return map_rewrite(map, name, strlen(name), NULL); 242768350Seric else 242868350Seric return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 242968350Seric } 243068350Seric 243168350Seric #endif 243268350Seric /* 243369453Seric ** Program map type. 243469453Seric ** 243569453Seric ** This provides access to arbitrary programs. It should be used 243669453Seric ** only very sparingly, since there is no way to bound the cost 243769453Seric ** of invoking an arbitrary program. 243869453Seric */ 243969453Seric 244069453Seric char * 244169453Seric prog_map_lookup(map, name, av, statp) 244269453Seric MAP *map; 244369453Seric char *name; 244469453Seric char **av; 244569453Seric int *statp; 244669453Seric { 244769453Seric int i; 244869453Seric register char *p; 244969453Seric int fd; 245069453Seric auto pid_t pid; 245169453Seric char *argv[MAXPV + 1]; 245269453Seric char buf[MAXLINE]; 245369453Seric 245469453Seric if (tTd(38, 20)) 245569453Seric printf("prog_map_lookup(%s, %s) %s\n", 245669453Seric map->map_mname, name, map->map_file); 245769453Seric 245869453Seric i = 0; 245969453Seric argv[i++] = map->map_file; 246069453Seric strcpy(buf, map->map_rebuild); 246169453Seric for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 246269453Seric { 246369453Seric if (i >= MAXPV - 1) 246469453Seric break; 246569453Seric argv[i++] = p; 246669453Seric } 246769453Seric argv[i++] = name; 246869453Seric argv[i] = NULL; 246969453Seric pid = prog_open(argv, &fd, CurEnv); 247069453Seric if (pid < 0) 247169453Seric { 247269453Seric if (tTd(38, 9)) 247369453Seric printf("prog_map_lookup(%s) failed (%s) -- closing", 247469453Seric map->map_mname, errstring(errno)); 247569453Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 247669453Seric return NULL; 247769453Seric } 247869453Seric i = read(fd, buf, sizeof buf - 1); 247969453Seric if (i <= 0 && tTd(38, 2)) 248069453Seric printf("prog_map_lookup(%s): read error %s\n", 248169562Seric map->map_mname, errstring(errno)); 248269453Seric if (i > 0) 248369453Seric { 248469453Seric char *rval; 248569453Seric 248669453Seric buf[i] = '\0'; 248769453Seric p = strchr(buf, '\n'); 248869453Seric if (p != NULL) 248969453Seric *p = '\0'; 249069453Seric 249169453Seric /* collect the return value */ 249269453Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 249369453Seric rval = map_rewrite(map, name, strlen(name), NULL); 249469453Seric else 249569453Seric rval = map_rewrite(map, buf, strlen(buf), NULL); 249669453Seric 249769453Seric /* now flush any additional output */ 249869453Seric while ((i = read(fd, buf, sizeof buf)) > 0) 249969453Seric continue; 250069453Seric close(fd); 250169453Seric 250269453Seric /* and wait for the process to terminate */ 250369453Seric *statp = waitfor(pid); 250469453Seric 250569453Seric return rval; 250669453Seric } 250769453Seric 250869453Seric close(fd); 250969453Seric *statp = waitfor(pid); 251069453Seric return NULL; 251169453Seric } 251269453Seric /* 251368350Seric ** Sequenced map type. 251468350Seric ** 251568350Seric ** Tries each map in order until something matches, much like 251668350Seric ** implicit. Stores go to the first map in the list that can 251768350Seric ** support storing. 251868350Seric ** 251968350Seric ** This is slightly unusual in that there are two interfaces. 252068350Seric ** The "sequence" interface lets you stack maps arbitrarily. 252168350Seric ** The "switch" interface builds a sequence map by looking 252268350Seric ** at a system-dependent configuration file such as 252368350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 252468350Seric ** 252568350Seric ** We don't need an explicit open, since all maps are 252668350Seric ** opened during startup, including underlying maps. 252768350Seric */ 252868350Seric 252968350Seric /* 253068350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 253168350Seric */ 253268350Seric 253368350Seric bool 253468350Seric seq_map_parse(map, ap) 253568350Seric MAP *map; 253668350Seric char *ap; 253768350Seric { 253868350Seric int maxmap; 253968350Seric 254068350Seric if (tTd(38, 2)) 254168350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 254268350Seric maxmap = 0; 254368350Seric while (*ap != '\0') 254468350Seric { 254568350Seric register char *p; 254668350Seric STAB *s; 254768350Seric 254868350Seric /* find beginning of map name */ 254968350Seric while (isascii(*ap) && isspace(*ap)) 255068350Seric ap++; 255168350Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 255268350Seric continue; 255368350Seric if (*p != '\0') 255468350Seric *p++ = '\0'; 255568350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 255668350Seric p++; 255768350Seric if (*ap == '\0') 255868350Seric { 255968350Seric ap = p; 256068350Seric continue; 256168350Seric } 256268350Seric s = stab(ap, ST_MAP, ST_FIND); 256368350Seric if (s == NULL) 256468350Seric { 256568350Seric syserr("Sequence map %s: unknown member map %s", 256668350Seric map->map_mname, ap); 256768350Seric } 256868350Seric else if (maxmap == MAXMAPSTACK) 256968350Seric { 257068350Seric syserr("Sequence map %s: too many member maps (%d max)", 257168350Seric map->map_mname, MAXMAPSTACK); 257268350Seric maxmap++; 257368350Seric } 257468350Seric else if (maxmap < MAXMAPSTACK) 257568350Seric { 257668350Seric map->map_stack[maxmap++] = &s->s_map; 257768350Seric } 257868350Seric ap = p; 257968350Seric } 258068350Seric return TRUE; 258168350Seric } 258268350Seric 258368350Seric 258468350Seric /* 258568350Seric ** SWITCH_MAP_OPEN -- open a switched map 258668350Seric ** 258768350Seric ** This looks at the system-dependent configuration and builds 258868350Seric ** a sequence map that does the same thing. 258968350Seric ** 259068350Seric ** Every system must define a switch_map_find routine in conf.c 259168350Seric ** that will return the list of service types associated with a 259268350Seric ** given service class. 259368350Seric */ 259468350Seric 259568350Seric bool 259668350Seric switch_map_open(map, mode) 259768350Seric MAP *map; 259868350Seric int mode; 259968350Seric { 260068350Seric int mapno; 260168350Seric int nmaps; 260268350Seric char *maptype[MAXMAPSTACK]; 260368350Seric 260468350Seric if (tTd(38, 2)) 260568350Seric printf("switch_map_open(%s, %s, %d)\n", 260668350Seric map->map_mname, map->map_file, mode); 260768350Seric 260868350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 260968350Seric if (tTd(38, 19)) 261068350Seric { 261168350Seric printf("\tswitch_map_find => %d\n", nmaps); 261268350Seric for (mapno = 0; mapno < nmaps; mapno++) 261368350Seric printf("\t\t%s\n", maptype[mapno]); 261468350Seric } 261568350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 261668350Seric return FALSE; 261768350Seric 261868350Seric for (mapno = 0; mapno < nmaps; mapno++) 261968350Seric { 262068350Seric register STAB *s; 262168350Seric char nbuf[MAXNAME + 1]; 262268350Seric 262368350Seric if (maptype[mapno] == NULL) 262468350Seric continue; 262568350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 262668350Seric s = stab(nbuf, ST_MAP, ST_FIND); 262768350Seric if (s == NULL) 262868350Seric { 262968350Seric syserr("Switch map %s: unknown member map %s", 263068350Seric map->map_mname, nbuf); 263168350Seric } 263268350Seric else 263368350Seric { 263468350Seric map->map_stack[mapno] = &s->s_map; 263568350Seric if (tTd(38, 4)) 263668350Seric printf("\tmap_stack[%d] = %s:%s\n", 263768350Seric mapno, s->s_map.map_class->map_cname, 263868350Seric nbuf); 263968350Seric } 264068350Seric } 264168350Seric return TRUE; 264268350Seric } 264368350Seric 264468350Seric 264568350Seric /* 264668350Seric ** SEQ_MAP_CLOSE -- close all underlying maps 264768350Seric */ 264868350Seric 2649*69748Seric void 265068350Seric seq_map_close(map) 265168350Seric MAP *map; 265268350Seric { 265368350Seric int mapno; 265468350Seric 265568350Seric if (tTd(38, 20)) 265668350Seric printf("seq_map_close(%s)\n", map->map_mname); 265768350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 265868350Seric { 265968350Seric MAP *mm = map->map_stack[mapno]; 266068350Seric 266168350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 266268350Seric continue; 266368350Seric mm->map_class->map_close(mm); 266468798Seric mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 266568350Seric } 266668350Seric } 266768350Seric 266868350Seric 266968350Seric /* 267068350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 267168350Seric */ 267268350Seric 267368350Seric char * 267468350Seric seq_map_lookup(map, key, args, pstat) 267568350Seric MAP *map; 267668350Seric char *key; 267768350Seric char **args; 267868350Seric int *pstat; 267968350Seric { 268068350Seric int mapno; 268168350Seric int mapbit = 0x01; 268268350Seric 268368350Seric if (tTd(38, 20)) 268468350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 268568350Seric 268668350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 268768350Seric { 268868350Seric MAP *mm = map->map_stack[mapno]; 268968350Seric int stat = 0; 269068350Seric char *rv; 269168350Seric 269268350Seric if (mm == NULL) 269368350Seric continue; 269468350Seric if (!bitset(MF_OPEN, mm->map_mflags)) 269568350Seric { 269668350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 269768350Seric { 269868350Seric *pstat = EX_UNAVAILABLE; 269968350Seric return NULL; 270068350Seric } 270168350Seric continue; 270268350Seric } 270368350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 270468350Seric if (rv != NULL) 270568350Seric return rv; 270668350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 270768350Seric return NULL; 270868350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 270968350Seric { 271068350Seric *pstat = stat; 271168350Seric return NULL; 271268350Seric } 271368350Seric } 271468350Seric return NULL; 271568350Seric } 271668350Seric 271768350Seric 271868350Seric /* 271968350Seric ** SEQ_MAP_STORE -- sequenced map store 272068350Seric */ 272168350Seric 272268350Seric void 272368350Seric seq_map_store(map, key, val) 272468350Seric MAP *map; 272568350Seric char *key; 272668350Seric char *val; 272768350Seric { 272868350Seric int mapno; 272968350Seric 273068350Seric if (tTd(38, 12)) 273168350Seric printf("seq_map_store(%s, %s, %s)\n", 273268350Seric map->map_mname, key, val); 273368350Seric 273468350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 273568350Seric { 273668350Seric MAP *mm = map->map_stack[mapno]; 273768350Seric 273868350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 273968350Seric continue; 274068350Seric 274168350Seric mm->map_class->map_store(mm, key, val); 274268350Seric return; 274368350Seric } 274468350Seric syserr("seq_map_store(%s, %s, %s): no writable map", 274568350Seric map->map_mname, key, val); 274668350Seric } 274768350Seric /* 274869401Seric ** GETCANONNAME -- look up name using service switch 274969401Seric ** 275069401Seric ** Parameters: 275169401Seric ** host -- the host name to look up. 275269401Seric ** hbsize -- the size of the host buffer. 275369401Seric ** trymx -- if set, try MX records. 275469401Seric ** 275569401Seric ** Returns: 275669401Seric ** TRUE -- if the host was found. 275769401Seric ** FALSE -- otherwise. 275869401Seric */ 275969401Seric 276069401Seric bool 276169401Seric getcanonname(host, hbsize, trymx) 276269401Seric char *host; 276369401Seric int hbsize; 276469401Seric bool trymx; 276569401Seric { 276669401Seric int nmaps; 276769401Seric int mapno; 276869401Seric bool found = FALSE; 276969401Seric auto int stat; 277069401Seric char *maptype[MAXMAPSTACK]; 277169401Seric short mapreturn[MAXMAPACTIONS]; 277269401Seric extern int h_errno; 277369401Seric 277469401Seric nmaps = switch_map_find("hosts", maptype, mapreturn); 277569401Seric for (mapno = 0; mapno < nmaps; mapno++) 277669401Seric { 277769401Seric int i; 277869401Seric 277969401Seric if (tTd(38, 20)) 278069401Seric printf("getcanonname(%s), trying %s\n", 278169401Seric host, maptype[mapno]); 278269401Seric if (strcmp("files", maptype[mapno]) == 0) 278369401Seric found = text_getcanonname(host, hbsize, &stat); 278469401Seric #ifdef NIS 278569401Seric else if (strcmp("nis", maptype[mapno]) == 0) 278669401Seric found = nis_getcanonname(host, hbsize, &stat); 278769401Seric #endif 278869401Seric #ifdef NISPLUS 278969401Seric else if (strcmp("nisplus", maptype[mapno]) == 0) 279069401Seric found = nisplus_getcanonname(host, hbsize, &stat); 279169401Seric #endif 279269401Seric #if NAMED_BIND 279369401Seric else if (strcmp("dns", maptype[mapno]) == 0) 279469401Seric found = dns_getcanonname(host, hbsize, trymx, &stat); 279569401Seric #endif 279669401Seric else 279769401Seric { 279869401Seric found = FALSE; 279969401Seric stat = EX_UNAVAILABLE; 280069401Seric } 280169401Seric if (found) 280269401Seric break; 280369401Seric 280469401Seric /* see if we should continue */ 280569401Seric if (stat == EX_TEMPFAIL) 280669401Seric i = MA_TRYAGAIN; 280769401Seric else if (stat == EX_NOHOST) 280869401Seric i = MA_NOTFOUND; 280969401Seric else 281069401Seric i = MA_UNAVAIL; 281169401Seric if (bitset(1 << mapno, mapreturn[i])) 281269401Seric break; 281369401Seric } 281469401Seric 281569401Seric if (found) 281669401Seric { 281769401Seric char *d; 281869401Seric 281969401Seric if (tTd(38, 20)) 282069401Seric printf("getcanonname(%s), found\n", host); 282169401Seric 282269401Seric /* 282369401Seric ** If returned name is still single token, compensate 282469401Seric ** by tagging on $m. This is because some sites set 282569401Seric ** up their DNS or NIS databases wrong. 282669401Seric */ 282769401Seric 282869401Seric if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 282969401Seric { 283069401Seric d = macvalue('m', CurEnv); 283169401Seric if (d != NULL && 283269401Seric hbsize > (int) (strlen(host) + strlen(d) + 1)) 283369401Seric { 283469401Seric if (host[strlen(host) - 1] != '.') 283569401Seric strcat(host, "."); 283669401Seric strcat(host, d); 283769401Seric } 283869401Seric else 283969401Seric { 284069401Seric return FALSE; 284169401Seric } 284269401Seric } 284369401Seric return TRUE; 284469401Seric } 284569401Seric 284669401Seric if (tTd(38, 20)) 284769401Seric printf("getcanonname(%s), failed, stat=%d\n", host, stat); 284869401Seric 284969401Seric #if NAMED_BIND 285069401Seric if (stat == EX_NOHOST) 285169401Seric h_errno = HOST_NOT_FOUND; 285269401Seric else 285369401Seric h_errno = TRY_AGAIN; 285469401Seric #endif 285569401Seric 285669401Seric return FALSE; 285769401Seric } 285869401Seric /* 285960207Seric ** NULL stubs 286060089Seric */ 286160089Seric 286260207Seric bool 286360207Seric null_map_open(map, mode) 286460089Seric MAP *map; 286560207Seric int mode; 286660089Seric { 286760207Seric return TRUE; 286860089Seric } 286960089Seric 287060207Seric void 287160207Seric null_map_close(map) 287260207Seric MAP *map; 287360089Seric { 287460207Seric return; 287560207Seric } 287660089Seric 287760207Seric void 287860207Seric null_map_store(map, key, val) 287960207Seric MAP *map; 288060207Seric char *key; 288160207Seric char *val; 288260089Seric { 288360207Seric return; 288460089Seric } 288568350Seric 288668350Seric 288768350Seric /* 288868350Seric ** BOGUS stubs 288968350Seric */ 289068350Seric 289168350Seric char * 289268350Seric bogus_map_lookup(map, key, args, pstat) 289368350Seric MAP *map; 289468350Seric char *key; 289568350Seric char **args; 289668350Seric int *pstat; 289768350Seric { 289868350Seric *pstat = EX_TEMPFAIL; 289968350Seric return NULL; 290068350Seric } 290168350Seric 290268350Seric MAPCLASS BogusMapClass = 290368350Seric { 290468350Seric "bogus-map", NULL, 0, 290568350Seric NULL, bogus_map_lookup, null_map_store, 290668350Seric null_map_open, null_map_close, 290768350Seric }; 2908