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*69827Seric static char sccsid[] = "@(#)map.c 8.73 (Berkeley) 06/10/95"; 1156822Seric #endif /* not lint */ 1256822Seric 1356822Seric #include "sendmail.h" 1456822Seric 1560089Seric #ifdef NDBM 1668509Seric # include <ndbm.h> 1756822Seric #endif 1860089Seric #ifdef NEWDB 1968509Seric # include <db.h> 2056822Seric #endif 2160089Seric #ifdef NIS 2269651Seric struct dom_binding; /* forward reference needed on IRIX */ 2368509Seric # include <rpcsvc/ypclnt.h> 2457208Seric #endif 2556822Seric 2656822Seric /* 2760089Seric ** MAP.C -- implementations for various map classes. 2856822Seric ** 2960089Seric ** Each map class implements a series of functions: 3060089Seric ** 3160089Seric ** bool map_parse(MAP *map, char *args) 3260089Seric ** Parse the arguments from the config file. Return TRUE 3360089Seric ** if they were ok, FALSE otherwise. Fill in map with the 3460089Seric ** values. 3560089Seric ** 3660222Seric ** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 3760222Seric ** Look up the key in the given map. If found, do any 3860222Seric ** rewriting the map wants (including "args" if desired) 3960089Seric ** and return the value. Set *pstat to the appropriate status 4060222Seric ** on error and return NULL. Args will be NULL if called 4160222Seric ** from the alias routines, although this should probably 4260222Seric ** not be relied upon. It is suggested you call map_rewrite 4360222Seric ** to return the results -- it takes care of null termination 4460222Seric ** and uses a dynamically expanded buffer as needed. 4560089Seric ** 4660089Seric ** void map_store(MAP *map, char *key, char *value) 4760089Seric ** Store the key:value pair in the map. 4860089Seric ** 4960089Seric ** bool map_open(MAP *map, int mode) 5060222Seric ** Open the map for the indicated mode. Mode should 5160222Seric ** be either O_RDONLY or O_RDWR. Return TRUE if it 5260222Seric ** was opened successfully, FALSE otherwise. If the open 5360222Seric ** failed an the MF_OPTIONAL flag is not set, it should 5460222Seric ** also print an error. If the MF_ALIAS bit is set 5560222Seric ** and this map class understands the @:@ convention, it 5660222Seric ** should call aliaswait() before returning. 5760089Seric ** 5860089Seric ** void map_close(MAP *map) 5960089Seric ** Close the map. 6069401Seric ** 6169401Seric ** This file also includes the implementation for getcanonname. 6269401Seric ** It is currently implemented in a pretty ad-hoc manner; it ought 6369401Seric ** to be more properly integrated into the map structure. 6460089Seric */ 6560089Seric 6660089Seric #define DBMMODE 0644 6764718Seric 6864718Seric extern bool aliaswait __P((MAP *, char *, int)); 6960089Seric /* 7060089Seric ** MAP_PARSEARGS -- parse config line arguments for database lookup 7160089Seric ** 7260089Seric ** This is a generic version of the map_parse method. 7360089Seric ** 7456822Seric ** Parameters: 7560089Seric ** map -- the map being initialized. 7660089Seric ** ap -- a pointer to the args on the config line. 7756822Seric ** 7856822Seric ** Returns: 7960089Seric ** TRUE -- if everything parsed OK. 8056822Seric ** FALSE -- otherwise. 8156822Seric ** 8256822Seric ** Side Effects: 8360089Seric ** null terminates the filename; stores it in map 8456822Seric */ 8556822Seric 8656822Seric bool 8760089Seric map_parseargs(map, ap) 8856822Seric MAP *map; 8960089Seric char *ap; 9056822Seric { 9160089Seric register char *p = ap; 9256822Seric 9363753Seric map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; 9460089Seric for (;;) 9560089Seric { 9660089Seric while (isascii(*p) && isspace(*p)) 9760089Seric p++; 9860089Seric if (*p != '-') 9960089Seric break; 10060089Seric switch (*++p) 10160089Seric { 10260089Seric case 'N': 10360207Seric map->map_mflags |= MF_INCLNULL; 10463753Seric map->map_mflags &= ~MF_TRY0NULL; 10560089Seric break; 10660089Seric 10763753Seric case 'O': 10863753Seric map->map_mflags &= ~MF_TRY1NULL; 10963753Seric break; 11063753Seric 11160089Seric case 'o': 11260207Seric map->map_mflags |= MF_OPTIONAL; 11360089Seric break; 11460089Seric 11560089Seric case 'f': 11660207Seric map->map_mflags |= MF_NOFOLDCASE; 11760089Seric break; 11860089Seric 11960089Seric case 'm': 12060207Seric map->map_mflags |= MF_MATCHONLY; 12160089Seric break; 12260089Seric 12368497Seric case 'A': 12468497Seric map->map_mflags |= MF_APPEND; 12568497Seric break; 12668497Seric 12769703Seric case 'q': 12869703Seric map->map_mflags |= MF_KEEPQUOTES; 12969703Seric break; 13069703Seric 13160089Seric case 'a': 13260089Seric map->map_app = ++p; 13360089Seric break; 13468350Seric 13568350Seric case 'k': 13668350Seric while (isascii(*++p) && isspace(*p)) 13768350Seric continue; 13868350Seric map->map_keycolnm = p; 13968350Seric break; 14068350Seric 14168350Seric case 'v': 14268350Seric while (isascii(*++p) && isspace(*p)) 14368350Seric continue; 14468350Seric map->map_valcolnm = p; 14568350Seric break; 14668350Seric 14768350Seric case 'z': 14868350Seric if (*++p != '\\') 14968350Seric map->map_coldelim = *p; 15068350Seric else 15168350Seric { 15268350Seric switch (*++p) 15368350Seric { 15468350Seric case 'n': 15568350Seric map->map_coldelim = '\n'; 15668350Seric break; 15768350Seric 15868350Seric case 't': 15968350Seric map->map_coldelim = '\t'; 16068350Seric break; 16168350Seric 16268350Seric default: 16368350Seric map->map_coldelim = '\\'; 16468350Seric } 16568350Seric } 16668350Seric break; 16768497Seric #ifdef RESERVED_FOR_SUN 16868497Seric case 'd': 16968497Seric map->map_mflags |= MF_DOMAIN_WIDE; 17068497Seric break; 17168497Seric 17268497Seric case 's': 17368497Seric /* info type */ 17468497Seric break; 17568497Seric #endif 17660089Seric } 17760089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 17860089Seric p++; 17960089Seric if (*p != '\0') 18060089Seric *p++ = '\0'; 18160089Seric } 18260089Seric if (map->map_app != NULL) 18360089Seric map->map_app = newstr(map->map_app); 18468350Seric if (map->map_keycolnm != NULL) 18568350Seric map->map_keycolnm = newstr(map->map_keycolnm); 18668350Seric if (map->map_valcolnm != NULL) 18768350Seric map->map_valcolnm = newstr(map->map_valcolnm); 18860089Seric 18960089Seric if (*p != '\0') 19060089Seric { 19160089Seric map->map_file = p; 19260089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 19360089Seric p++; 19460089Seric if (*p != '\0') 19560089Seric *p++ = '\0'; 19660089Seric map->map_file = newstr(map->map_file); 19760089Seric } 19860089Seric 19960089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 20060089Seric p++; 20160089Seric if (*p != '\0') 20260089Seric map->map_rebuild = newstr(p); 20360089Seric 20468350Seric if (map->map_file == NULL && 20568350Seric !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 20657208Seric { 20760089Seric syserr("No file name for %s map %s", 20860089Seric map->map_class->map_cname, map->map_mname); 20956822Seric return FALSE; 21057208Seric } 21160089Seric return TRUE; 21260089Seric } 21360089Seric /* 21460089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 21560089Seric ** 21660089Seric ** It also adds the map_app string. It can be used as a utility 21760089Seric ** in the map_lookup method. 21860089Seric ** 21960089Seric ** Parameters: 22060089Seric ** map -- the map that causes this. 22160089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 22260089Seric ** slen -- the length of s. 22360089Seric ** av -- arguments to interpolate into buf. 22460089Seric ** 22560089Seric ** Returns: 22667895Seric ** Pointer to rewritten result. This is static data that 22767895Seric ** should be copied if it is to be saved! 22860089Seric ** 22960089Seric ** Side Effects: 23060089Seric ** none. 23160089Seric */ 23260089Seric 23360089Seric char * 23460089Seric map_rewrite(map, s, slen, av) 23560089Seric register MAP *map; 23660089Seric register char *s; 23760089Seric int slen; 23860089Seric char **av; 23960089Seric { 24060089Seric register char *bp; 24160089Seric register char c; 24260089Seric char **avp; 24360089Seric register char *ap; 24460089Seric int i; 24560089Seric int len; 24667895Seric static int buflen = -1; 24767895Seric static char *buf = NULL; 24860089Seric 24960537Seric if (tTd(39, 1)) 25060089Seric { 25160256Seric printf("map_rewrite(%.*s), av =", slen, s); 25260256Seric if (av == NULL) 25360256Seric printf(" (nullv)"); 25460256Seric else 25560256Seric { 25660256Seric for (avp = av; *avp != NULL; avp++) 25760256Seric printf("\n\t%s", *avp); 25860256Seric } 25960256Seric printf("\n"); 26060089Seric } 26160089Seric 26260089Seric /* count expected size of output (can safely overestimate) */ 26360089Seric i = len = slen; 26460089Seric if (av != NULL) 26560089Seric { 26660089Seric bp = s; 26760089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 26860089Seric { 26960089Seric if (c != '%') 27060089Seric continue; 27160089Seric if (--i < 0) 27260089Seric break; 27360089Seric c = *bp++; 27460089Seric if (!(isascii(c) && isdigit(c))) 27560089Seric continue; 27663937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 27760089Seric continue; 27860089Seric if (*avp == NULL) 27960089Seric continue; 28060089Seric len += strlen(*avp); 28160089Seric } 28260089Seric } 28360089Seric if (map->map_app != NULL) 28460089Seric len += strlen(map->map_app); 28567895Seric if (buflen < ++len) 28660089Seric { 28760089Seric /* need to malloc additional space */ 28867895Seric buflen = len; 28967895Seric if (buf != NULL) 29067895Seric free(buf); 29167895Seric buf = xalloc(buflen); 29260089Seric } 29360089Seric 29467895Seric bp = buf; 29560089Seric if (av == NULL) 29660089Seric { 29760089Seric bcopy(s, bp, slen); 29860089Seric bp += slen; 29960089Seric } 30060089Seric else 30160089Seric { 30260089Seric while (--slen >= 0 && (c = *s++) != '\0') 30360089Seric { 30460089Seric if (c != '%') 30560089Seric { 30660089Seric pushc: 30760089Seric *bp++ = c; 30860089Seric continue; 30960089Seric } 31060089Seric if (--slen < 0 || (c = *s++) == '\0') 31160089Seric c = '%'; 31260089Seric if (c == '%') 31360089Seric goto pushc; 31460089Seric if (!(isascii(c) && isdigit(c))) 31560089Seric { 31660089Seric *bp++ = '%'; 31760089Seric goto pushc; 31860089Seric } 31963937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 32060089Seric continue; 32160089Seric if (*avp == NULL) 32260089Seric continue; 32360089Seric 32460089Seric /* transliterate argument into output string */ 32560089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 32660089Seric *bp++ = c; 32760089Seric } 32860089Seric } 32960089Seric if (map->map_app != NULL) 33060089Seric strcpy(bp, map->map_app); 33160089Seric else 33260089Seric *bp = '\0'; 33360537Seric if (tTd(39, 1)) 33467895Seric printf("map_rewrite => %s\n", buf); 33567895Seric return buf; 33660089Seric } 33760089Seric /* 33860537Seric ** INITMAPS -- initialize for aliasing 33960537Seric ** 34060537Seric ** Parameters: 34160537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 34260537Seric ** e -- current envelope. 34360537Seric ** 34460537Seric ** Returns: 34560537Seric ** none. 34660537Seric ** 34760537Seric ** Side Effects: 34860537Seric ** initializes aliases: 34960537Seric ** if NDBM: opens the database. 35060537Seric ** if ~NDBM: reads the aliases into the symbol table. 35160537Seric */ 35260537Seric 35369748Seric void 35460537Seric initmaps(rebuild, e) 35560537Seric bool rebuild; 35660537Seric register ENVELOPE *e; 35760537Seric { 35860537Seric extern void map_init(); 35960537Seric 36064671Seric #ifdef XDEBUG 36164671Seric checkfd012("entering initmaps"); 36264671Seric #endif 36360537Seric CurEnv = e; 36465085Seric if (rebuild) 36565085Seric { 36665085Seric stabapply(map_init, 1); 36765085Seric stabapply(map_init, 2); 36865085Seric } 36965085Seric else 37065085Seric { 37165085Seric stabapply(map_init, 0); 37265085Seric } 37364671Seric #ifdef XDEBUG 37464671Seric checkfd012("exiting initmaps"); 37564671Seric #endif 37660537Seric } 37760537Seric 37860537Seric void 37960537Seric map_init(s, rebuild) 38060537Seric register STAB *s; 38160537Seric int rebuild; 38260537Seric { 38360537Seric register MAP *map; 38460537Seric 38560537Seric /* has to be a map */ 38660537Seric if (s->s_type != ST_MAP) 38760537Seric return; 38860537Seric 38960537Seric map = &s->s_map; 39060537Seric if (!bitset(MF_VALID, map->map_mflags)) 39160537Seric return; 39260537Seric 39360537Seric if (tTd(38, 2)) 39468350Seric printf("map_init(%s:%s, %s, %d)\n", 39564690Seric map->map_class->map_cname == NULL ? "NULL" : 39664690Seric map->map_class->map_cname, 39768350Seric map->map_mname == NULL ? "NULL" : map->map_mname, 39865085Seric map->map_file == NULL ? "NULL" : map->map_file, 39965085Seric rebuild); 40060537Seric 40165085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && 40265085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) 40365085Seric { 40465085Seric if (tTd(38, 3)) 40565085Seric printf("\twrong pass\n"); 40665085Seric return; 40765085Seric } 40865085Seric 40960537Seric /* if already open, close it (for nested open) */ 41060537Seric if (bitset(MF_OPEN, map->map_mflags)) 41160537Seric { 41260537Seric map->map_class->map_close(map); 41360537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 41460537Seric } 41560537Seric 41665085Seric if (rebuild == 2) 41760537Seric { 41865085Seric rebuildaliases(map, FALSE); 41960537Seric } 42060537Seric else 42160537Seric { 42260537Seric if (map->map_class->map_open(map, O_RDONLY)) 42360537Seric { 42460537Seric if (tTd(38, 4)) 42568350Seric printf("\t%s:%s %s: valid\n", 42664690Seric map->map_class->map_cname == NULL ? "NULL" : 42764690Seric map->map_class->map_cname, 42868350Seric map->map_mname == NULL ? "NULL" : 42968350Seric map->map_mname, 43064690Seric map->map_file == NULL ? "NULL" : 43164690Seric map->map_file); 43260537Seric map->map_mflags |= MF_OPEN; 43360537Seric } 43468350Seric else 43568350Seric { 43668350Seric if (tTd(38, 4)) 43768350Seric printf("\t%s:%s %s: invalid: %s\n", 43868350Seric map->map_class->map_cname == NULL ? "NULL" : 43968350Seric map->map_class->map_cname, 44068350Seric map->map_mname == NULL ? "NULL" : 44168350Seric map->map_mname, 44268350Seric map->map_file == NULL ? "NULL" : 44368350Seric map->map_file, 44468350Seric errstring(errno)); 44568350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 44668350Seric { 44768350Seric extern MAPCLASS BogusMapClass; 44868350Seric 44968350Seric map->map_class = &BogusMapClass; 45068350Seric map->map_mflags |= MF_OPEN; 45168350Seric } 45268350Seric } 45360537Seric } 45460537Seric } 45560537Seric /* 45669802Seric ** GETCANONNAME -- look up name using service switch 45769802Seric ** 45869802Seric ** Parameters: 45969802Seric ** host -- the host name to look up. 46069802Seric ** hbsize -- the size of the host buffer. 46169802Seric ** trymx -- if set, try MX records. 46269802Seric ** 46369802Seric ** Returns: 46469802Seric ** TRUE -- if the host was found. 46569802Seric ** FALSE -- otherwise. 46669802Seric */ 46769802Seric 46869802Seric bool 46969802Seric getcanonname(host, hbsize, trymx) 47069802Seric char *host; 47169802Seric int hbsize; 47269802Seric bool trymx; 47369802Seric { 47469802Seric int nmaps; 47569802Seric int mapno; 47669802Seric bool found = FALSE; 47769802Seric auto int stat; 47869802Seric char *maptype[MAXMAPSTACK]; 47969802Seric short mapreturn[MAXMAPACTIONS]; 48069802Seric extern int h_errno; 48169802Seric 48269802Seric nmaps = switch_map_find("hosts", maptype, mapreturn); 48369802Seric for (mapno = 0; mapno < nmaps; mapno++) 48469802Seric { 48569802Seric int i; 48669802Seric 48769802Seric if (tTd(38, 20)) 48869802Seric printf("getcanonname(%s), trying %s\n", 48969802Seric host, maptype[mapno]); 49069802Seric if (strcmp("files", maptype[mapno]) == 0) 49169802Seric { 49269802Seric extern bool text_getcanonname __P((char *, int, int *)); 49369802Seric 49469802Seric found = text_getcanonname(host, hbsize, &stat); 49569802Seric } 49669802Seric #ifdef NIS 49769802Seric else if (strcmp("nis", maptype[mapno]) == 0) 49869802Seric { 49969802Seric extern bool nis_getcanonname __P((char *, int, int *)); 50069802Seric 50169802Seric found = nis_getcanonname(host, hbsize, &stat); 50269802Seric } 50369802Seric #endif 50469802Seric #ifdef NISPLUS 50569802Seric else if (strcmp("nisplus", maptype[mapno]) == 0) 50669802Seric { 50769802Seric extern bool nisplus_getcanonname __P((char *, int, int *)); 50869802Seric 50969802Seric found = nisplus_getcanonname(host, hbsize, &stat); 51069802Seric } 51169802Seric #endif 51269802Seric #if NAMED_BIND 51369802Seric else if (strcmp("dns", maptype[mapno]) == 0) 51469802Seric { 51569802Seric extern bool dns_getcanonname __P((char *, int, bool, int *)); 51669802Seric 51769802Seric found = dns_getcanonname(host, hbsize, trymx, &stat); 51869802Seric } 51969802Seric #endif 52069802Seric else 52169802Seric { 52269802Seric found = FALSE; 52369802Seric stat = EX_UNAVAILABLE; 52469802Seric } 52569802Seric if (found) 52669802Seric break; 52769802Seric 52869802Seric /* see if we should continue */ 52969802Seric if (stat == EX_TEMPFAIL) 53069802Seric i = MA_TRYAGAIN; 53169802Seric else if (stat == EX_NOHOST) 53269802Seric i = MA_NOTFOUND; 53369802Seric else 53469802Seric i = MA_UNAVAIL; 53569802Seric if (bitset(1 << mapno, mapreturn[i])) 53669802Seric break; 53769802Seric } 53869802Seric 53969802Seric if (found) 54069802Seric { 54169802Seric char *d; 54269802Seric 54369802Seric if (tTd(38, 20)) 54469802Seric printf("getcanonname(%s), found\n", host); 54569802Seric 54669802Seric /* 54769802Seric ** If returned name is still single token, compensate 54869802Seric ** by tagging on $m. This is because some sites set 54969802Seric ** up their DNS or NIS databases wrong. 55069802Seric */ 55169802Seric 55269802Seric if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 55369802Seric { 55469802Seric d = macvalue('m', CurEnv); 55569802Seric if (d != NULL && 55669802Seric hbsize > (int) (strlen(host) + strlen(d) + 1)) 55769802Seric { 55869802Seric if (host[strlen(host) - 1] != '.') 55969802Seric strcat(host, "."); 56069802Seric strcat(host, d); 56169802Seric } 56269802Seric else 56369802Seric { 56469802Seric return FALSE; 56569802Seric } 56669802Seric } 56769802Seric return TRUE; 56869802Seric } 56969802Seric 57069802Seric if (tTd(38, 20)) 57169802Seric printf("getcanonname(%s), failed, stat=%d\n", host, stat); 57269802Seric 57369802Seric #if NAMED_BIND 57469802Seric if (stat == EX_NOHOST) 57569802Seric h_errno = HOST_NOT_FOUND; 57669802Seric else 57769802Seric h_errno = TRY_AGAIN; 57869802Seric #endif 57969802Seric 58069802Seric return FALSE; 58169802Seric } 58269802Seric /* 58360089Seric ** NDBM modules 58460089Seric */ 58560089Seric 58660089Seric #ifdef NDBM 58760089Seric 58860089Seric /* 58960089Seric ** DBM_MAP_OPEN -- DBM-style map open 59060089Seric */ 59160089Seric 59260089Seric bool 59360089Seric ndbm_map_open(map, mode) 59460089Seric MAP *map; 59560089Seric int mode; 59660089Seric { 59764284Seric register DBM *dbm; 59864284Seric struct stat st; 59960089Seric 60060537Seric if (tTd(38, 2)) 60168350Seric printf("ndbm_map_open(%s, %s, %d)\n", 60268350Seric map->map_mname, map->map_file, mode); 60360089Seric 60460207Seric if (mode == O_RDWR) 60560207Seric mode |= O_CREAT|O_TRUNC; 60660207Seric 60760089Seric /* open the database */ 60860089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 60956822Seric if (dbm == NULL) 61056822Seric { 61164718Seric if (aliaswait(map, ".pag", FALSE)) 61264718Seric return TRUE; 61360207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 61456836Seric syserr("Cannot open DBM database %s", map->map_file); 61556822Seric return FALSE; 61656822Seric } 61760089Seric map->map_db1 = (void *) dbm; 61864964Seric if (mode == O_RDONLY) 61964964Seric { 62064964Seric if (bitset(MF_ALIAS, map->map_mflags) && 62164964Seric !aliaswait(map, ".pag", TRUE)) 62264718Seric return FALSE; 62364964Seric } 62464964Seric else 62564964Seric { 62664964Seric int fd; 62764964Seric 62864964Seric /* exclusive lock for duration of rebuild */ 62964964Seric fd = dbm_dirfno((DBM *) map->map_db1); 63064964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 63164964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 63264964Seric map->map_mflags |= MF_LOCKED; 63364964Seric } 63464718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 63564284Seric map->map_mtime = st.st_mtime; 63656822Seric return TRUE; 63756822Seric } 63860089Seric 63960089Seric 64060089Seric /* 64156822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 64256822Seric */ 64356822Seric 64456822Seric char * 64560089Seric ndbm_map_lookup(map, name, av, statp) 64656822Seric MAP *map; 64760089Seric char *name; 64856822Seric char **av; 64959084Seric int *statp; 65056822Seric { 65156822Seric datum key, val; 65264373Seric int fd; 65360089Seric char keybuf[MAXNAME + 1]; 65456822Seric 65560537Seric if (tTd(38, 20)) 65668350Seric printf("ndbm_map_lookup(%s, %s)\n", 65768350Seric map->map_mname, name); 65860089Seric 65960089Seric key.dptr = name; 66060089Seric key.dsize = strlen(name); 66160207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 66257014Seric { 66360089Seric if (key.dsize > sizeof keybuf - 1) 66460089Seric key.dsize = sizeof keybuf - 1; 66560089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 66660089Seric makelower(keybuf); 66760089Seric key.dptr = keybuf; 66857014Seric } 66964373Seric fd = dbm_dirfno((DBM *) map->map_db1); 67064388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 67164373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 67263753Seric val.dptr = NULL; 67363753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 67463753Seric { 67563753Seric val = dbm_fetch((DBM *) map->map_db1, key); 67663753Seric if (val.dptr != NULL) 67763753Seric map->map_mflags &= ~MF_TRY1NULL; 67863753Seric } 67963753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 68063753Seric { 68156822Seric key.dsize++; 68263753Seric val = dbm_fetch((DBM *) map->map_db1, key); 68363753Seric if (val.dptr != NULL) 68463753Seric map->map_mflags &= ~MF_TRY0NULL; 68563753Seric } 68664388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 68764373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 68856822Seric if (val.dptr == NULL) 68956822Seric return NULL; 69060207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 69163753Seric return map_rewrite(map, name, strlen(name), NULL); 69263753Seric else 69363753Seric return map_rewrite(map, val.dptr, val.dsize, av); 69456822Seric } 69556822Seric 69656822Seric 69756822Seric /* 69860089Seric ** DBM_MAP_STORE -- store a datum in the database 69956822Seric */ 70056822Seric 70160089Seric void 70260089Seric ndbm_map_store(map, lhs, rhs) 70360089Seric register MAP *map; 70460089Seric char *lhs; 70560089Seric char *rhs; 70660089Seric { 70760089Seric datum key; 70860089Seric datum data; 70960089Seric int stat; 71060089Seric 71160537Seric if (tTd(38, 12)) 71268350Seric printf("ndbm_map_store(%s, %s, %s)\n", 71368350Seric map->map_mname, lhs, rhs); 71460089Seric 71560089Seric key.dsize = strlen(lhs); 71660089Seric key.dptr = lhs; 71760089Seric 71860089Seric data.dsize = strlen(rhs); 71960089Seric data.dptr = rhs; 72060089Seric 72160207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 72260089Seric { 72360089Seric key.dsize++; 72460089Seric data.dsize++; 72560089Seric } 72660089Seric 72760089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 72860089Seric if (stat > 0) 72960089Seric { 73068497Seric if (!bitset(MF_APPEND, map->map_mflags)) 73168497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 73268497Seric else 73368497Seric { 73468497Seric static char *buf = NULL; 73568497Seric static int bufsiz = 0; 73668879Seric auto int xstat; 73768497Seric datum old; 73868497Seric 73968879Seric old.dptr = ndbm_map_lookup(map, key.dptr, NULL, &xstat); 74068497Seric if (old.dptr != NULL && *old.dptr != '\0') 74168497Seric { 74268497Seric old.dsize = strlen(old.dptr); 74368497Seric if (data.dsize + old.dsize + 2 > bufsiz) 74468497Seric { 74568497Seric if (buf != NULL) 74668497Seric (void) free(buf); 74768497Seric bufsiz = data.dsize + old.dsize + 2; 74868497Seric buf = xalloc(bufsiz); 74968497Seric } 75068497Seric sprintf(buf, "%s,%s", data.dptr, old.dptr); 75168497Seric data.dsize = data.dsize + old.dsize + 1; 75268497Seric data.dptr = buf; 75368497Seric if (tTd(38, 9)) 75468497Seric printf("ndbm_map_store append=%s\n", data.dptr); 75568497Seric } 75668497Seric } 75760089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 75860089Seric } 75960089Seric if (stat != 0) 76060089Seric syserr("readaliases: dbm put (%s)", lhs); 76160089Seric } 76260089Seric 76360089Seric 76460089Seric /* 76560207Seric ** NDBM_MAP_CLOSE -- close the database 76660089Seric */ 76760089Seric 76860089Seric void 76960089Seric ndbm_map_close(map) 77060089Seric register MAP *map; 77160089Seric { 77266773Seric if (tTd(38, 9)) 77368350Seric printf("ndbm_map_close(%s, %s, %x)\n", 77468350Seric map->map_mname, map->map_file, map->map_mflags); 77566773Seric 77660207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 77760089Seric { 77864250Seric #ifdef NIS 77964075Seric bool inclnull; 78060089Seric char buf[200]; 78160089Seric 78264075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 78364075Seric map->map_mflags &= ~MF_INCLNULL; 78464075Seric 78569651Seric if (strstr(map->map_file, "/yp/") != NULL) 78669651Seric { 78769651Seric (void) sprintf(buf, "%010ld", curtime()); 78869651Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 78960089Seric 79069651Seric (void) gethostname(buf, sizeof buf); 79169651Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 79269651Seric } 79364075Seric 79464075Seric if (inclnull) 79564075Seric map->map_mflags |= MF_INCLNULL; 79660089Seric #endif 79760089Seric 79860089Seric /* write out the distinguished alias */ 79960089Seric ndbm_map_store(map, "@", "@"); 80060089Seric } 80160089Seric dbm_close((DBM *) map->map_db1); 80260089Seric } 80360089Seric 80460089Seric #endif 80560089Seric /* 80660582Seric ** NEWDB (Hash and BTree) Modules 80760089Seric */ 80860089Seric 80960089Seric #ifdef NEWDB 81060089Seric 81160089Seric /* 81260582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 81360582Seric ** 81460582Seric ** These do rather bizarre locking. If you can lock on open, 81560582Seric ** do that to avoid the condition of opening a database that 81660582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 81760582Seric ** there will be a race condition. If opening for read-only, 81860582Seric ** we immediately release the lock to avoid freezing things up. 81960582Seric ** We really ought to hold the lock, but guarantee that we won't 82060582Seric ** be pokey about it. That's hard to do. 82160089Seric */ 82260089Seric 82356822Seric bool 82460089Seric bt_map_open(map, mode) 82556822Seric MAP *map; 82660089Seric int mode; 82756822Seric { 82856822Seric DB *db; 82960228Seric int i; 83060582Seric int omode; 83164373Seric int fd; 83264284Seric struct stat st; 83368528Seric char buf[MAXNAME + 1]; 83456822Seric 83560537Seric if (tTd(38, 2)) 83668350Seric printf("bt_map_open(%s, %s, %d)\n", 83768350Seric map->map_mname, map->map_file, mode); 83860089Seric 83960582Seric omode = mode; 84060582Seric if (omode == O_RDWR) 84160582Seric { 84260582Seric omode |= O_CREAT|O_TRUNC; 84365830Seric #if defined(O_EXLOCK) && HASFLOCK 84460582Seric omode |= O_EXLOCK; 84566843Seric # if !OLD_NEWDB 84660582Seric } 84760582Seric else 84860582Seric { 84960582Seric omode |= O_SHLOCK; 85060582Seric # endif 85160582Seric #endif 85260582Seric } 85360207Seric 85460228Seric (void) strcpy(buf, map->map_file); 85560228Seric i = strlen(buf); 85660228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 85760228Seric (void) strcat(buf, ".db"); 85860582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 85956822Seric if (db == NULL) 86056822Seric { 86164718Seric #ifdef MAYBENEXTRELEASE 86264718Seric if (aliaswait(map, ".db", FALSE)) 86364718Seric return TRUE; 86464718Seric #endif 86560207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 86656836Seric syserr("Cannot open BTREE database %s", map->map_file); 86756822Seric return FALSE; 86856822Seric } 86968350Seric #if !OLD_NEWDB 87064373Seric fd = db->fd(db); 87168778Seric # if defined(O_EXLOCK) && HASFLOCK 87268778Seric if (fd >= 0) 87368778Seric { 87468778Seric if (mode == O_RDONLY) 87568778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 87668778Seric else 87768778Seric map->map_mflags |= MF_LOCKED; 87868778Seric } 87968778Seric # else 88064373Seric if (mode == O_RDWR && fd >= 0) 88164388Seric { 88264388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 88364388Seric map->map_mflags |= MF_LOCKED; 88464388Seric } 88560582Seric # endif 88660582Seric #endif 88760585Seric 88860585Seric /* try to make sure that at least the database header is on disk */ 88960585Seric if (mode == O_RDWR) 89066843Seric #if OLD_NEWDB 89164373Seric (void) db->sync(db); 89264373Seric #else 89360585Seric (void) db->sync(db, 0); 89460585Seric 89564373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 89664284Seric map->map_mtime = st.st_mtime; 89764284Seric #endif 89864284Seric 89960089Seric map->map_db2 = (void *) db; 90060207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 90164718Seric if (!aliaswait(map, ".db", TRUE)) 90264718Seric return FALSE; 90356822Seric return TRUE; 90456822Seric } 90556822Seric 90656822Seric 90756822Seric /* 90856822Seric ** HASH_MAP_INIT -- HASH-style map initialization 90956822Seric */ 91056822Seric 91156822Seric bool 91260089Seric hash_map_open(map, mode) 91356822Seric MAP *map; 91460089Seric int mode; 91556822Seric { 91656822Seric DB *db; 91760228Seric int i; 91860582Seric int omode; 91964373Seric int fd; 92064284Seric struct stat st; 92168528Seric char buf[MAXNAME + 1]; 92256822Seric 92360537Seric if (tTd(38, 2)) 92468350Seric printf("hash_map_open(%s, %s, %d)\n", 92568350Seric map->map_mname, map->map_file, mode); 92660089Seric 92760582Seric omode = mode; 92860582Seric if (omode == O_RDWR) 92960582Seric { 93060582Seric omode |= O_CREAT|O_TRUNC; 93165830Seric #if defined(O_EXLOCK) && HASFLOCK 93260582Seric omode |= O_EXLOCK; 93366843Seric # if !OLD_NEWDB 93460582Seric } 93560582Seric else 93660582Seric { 93760582Seric omode |= O_SHLOCK; 93860582Seric # endif 93960582Seric #endif 94060582Seric } 94160207Seric 94260228Seric (void) strcpy(buf, map->map_file); 94360228Seric i = strlen(buf); 94460228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 94560228Seric (void) strcat(buf, ".db"); 94660582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 94756822Seric if (db == NULL) 94856822Seric { 94964718Seric #ifdef MAYBENEXTRELEASE 95064718Seric if (aliaswait(map, ".db", FALSE)) 95164718Seric return TRUE; 95264718Seric #endif 95360207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 95456836Seric syserr("Cannot open HASH database %s", map->map_file); 95556822Seric return FALSE; 95656822Seric } 95768350Seric #if !OLD_NEWDB 95864373Seric fd = db->fd(db); 95968778Seric # if defined(O_EXLOCK) && HASFLOCK 96068778Seric if (fd >= 0) 96168778Seric { 96268778Seric if (mode == O_RDONLY) 96368778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 96468778Seric else 96568778Seric map->map_mflags |= MF_LOCKED; 96668778Seric } 96768778Seric # else 96864373Seric if (mode == O_RDWR && fd >= 0) 96964388Seric { 97064388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 97164388Seric map->map_mflags |= MF_LOCKED; 97264388Seric } 97360582Seric # endif 97460582Seric #endif 97560585Seric 97660585Seric /* try to make sure that at least the database header is on disk */ 97760585Seric if (mode == O_RDWR) 97866843Seric #if OLD_NEWDB 97964373Seric (void) db->sync(db); 98064373Seric #else 98160585Seric (void) db->sync(db, 0); 98260585Seric 98364373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 98464284Seric map->map_mtime = st.st_mtime; 98564284Seric #endif 98664284Seric 98760089Seric map->map_db2 = (void *) db; 98860207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 98964718Seric if (!aliaswait(map, ".db", TRUE)) 99064718Seric return FALSE; 99156822Seric return TRUE; 99256822Seric } 99356822Seric 99456822Seric 99556822Seric /* 99656822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 99756822Seric */ 99856822Seric 99956822Seric char * 100060089Seric db_map_lookup(map, name, av, statp) 100156822Seric MAP *map; 100260089Seric char *name; 100356822Seric char **av; 100459084Seric int *statp; 100556822Seric { 100656822Seric DBT key, val; 100760422Seric register DB *db = (DB *) map->map_db2; 100860422Seric int st; 100960422Seric int saveerrno; 101064373Seric int fd; 101160089Seric char keybuf[MAXNAME + 1]; 101256822Seric 101360537Seric if (tTd(38, 20)) 101468350Seric printf("db_map_lookup(%s, %s)\n", 101568350Seric map->map_mname, name); 101660089Seric 101760089Seric key.size = strlen(name); 101860089Seric if (key.size > sizeof keybuf - 1) 101960089Seric key.size = sizeof keybuf - 1; 102060089Seric key.data = keybuf; 102160089Seric bcopy(name, keybuf, key.size + 1); 102260207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 102360089Seric makelower(keybuf); 102466843Seric #if !OLD_NEWDB 102564388Seric fd = db->fd(db); 102664388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 102764388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 102860422Seric #endif 102963753Seric st = 1; 103063753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 103163753Seric { 103263753Seric st = db->get(db, &key, &val, 0); 103363753Seric if (st == 0) 103463753Seric map->map_mflags &= ~MF_TRY1NULL; 103563753Seric } 103663753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 103763753Seric { 103863753Seric key.size++; 103963753Seric st = db->get(db, &key, &val, 0); 104063753Seric if (st == 0) 104163753Seric map->map_mflags &= ~MF_TRY0NULL; 104263753Seric } 104360422Seric saveerrno = errno; 104466843Seric #if !OLD_NEWDB 104564388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 104664373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 104760422Seric #endif 104860422Seric if (st != 0) 104960422Seric { 105060422Seric errno = saveerrno; 105160422Seric if (st < 0) 105260422Seric syserr("db_map_lookup: get (%s)", name); 105356822Seric return NULL; 105460422Seric } 105560207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 105663753Seric return map_rewrite(map, name, strlen(name), NULL); 105763753Seric else 105863753Seric return map_rewrite(map, val.data, val.size, av); 105956822Seric } 106056822Seric 106160089Seric 106260089Seric /* 106360089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 106456822Seric */ 106556822Seric 106660089Seric void 106760089Seric db_map_store(map, lhs, rhs) 106860089Seric register MAP *map; 106960089Seric char *lhs; 107060089Seric char *rhs; 107156822Seric { 107260089Seric int stat; 107360089Seric DBT key; 107460089Seric DBT data; 107560089Seric register DB *db = map->map_db2; 107656822Seric 107760537Seric if (tTd(38, 20)) 107868350Seric printf("db_map_store(%s, %s, %s)\n", 107968350Seric map->map_mname, lhs, rhs); 108060089Seric 108160089Seric key.size = strlen(lhs); 108260089Seric key.data = lhs; 108360089Seric 108460089Seric data.size = strlen(rhs); 108560089Seric data.data = rhs; 108660089Seric 108760207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 108856822Seric { 108960089Seric key.size++; 109060089Seric data.size++; 109160089Seric } 109256836Seric 109360089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 109460089Seric if (stat > 0) 109560089Seric { 109668497Seric if (!bitset(MF_APPEND, map->map_mflags)) 109768497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 109868497Seric else 109968497Seric { 110068497Seric static char *buf = NULL; 110168497Seric static int bufsiz = 0; 110268497Seric DBT old; 110368497Seric 110468497Seric old.data = db_map_lookup(map, key.data, NULL, &stat); 110568497Seric if (old.data != NULL) 110668497Seric { 110768497Seric old.size = strlen(old.data); 110868497Seric if (data.size + old.size + 2 > bufsiz) 110968497Seric { 111068497Seric if (buf != NULL) 111168497Seric (void) free(buf); 111268497Seric bufsiz = data.size + old.size + 2; 111368497Seric buf = xalloc(bufsiz); 111468497Seric } 111568497Seric sprintf(buf, "%s,%s", data.data, old.data); 111668497Seric data.size = data.size + old.size + 1; 111768497Seric data.data = buf; 111868497Seric if (tTd(38, 9)) 111968497Seric printf("db_map_store append=%s\n", data.data); 112068497Seric } 112168497Seric } 112260089Seric stat = db->put(db, &key, &data, 0); 112360089Seric } 112460089Seric if (stat != 0) 112560089Seric syserr("readaliases: db put (%s)", lhs); 112660089Seric } 112756836Seric 112856847Seric 112960089Seric /* 113060089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 113160089Seric */ 113260089Seric 113360089Seric void 113460089Seric db_map_close(map) 113560089Seric MAP *map; 113660089Seric { 113760089Seric register DB *db = map->map_db2; 113860089Seric 113960537Seric if (tTd(38, 9)) 114068350Seric printf("db_map_close(%s, %s, %x)\n", 114168350Seric map->map_mname, map->map_file, map->map_mflags); 114260089Seric 114360207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 114458804Seric { 114560089Seric /* write out the distinguished alias */ 114660089Seric db_map_store(map, "@", "@"); 114758804Seric } 114858963Seric 114960089Seric if (db->close(db) != 0) 115060089Seric syserr("readaliases: db close failure"); 115156822Seric } 115257208Seric 115360089Seric #endif 115460089Seric /* 115560089Seric ** NIS Modules 115660089Seric */ 115760089Seric 115860089Seric # ifdef NIS 115960089Seric 116064369Seric # ifndef YPERR_BUSY 116164369Seric # define YPERR_BUSY 16 116264369Seric # endif 116364369Seric 116457208Seric /* 116560089Seric ** NIS_MAP_OPEN -- open DBM map 116657208Seric */ 116757208Seric 116857208Seric bool 116960089Seric nis_map_open(map, mode) 117057208Seric MAP *map; 117160089Seric int mode; 117257208Seric { 117357216Seric int yperr; 117460215Seric register char *p; 117560215Seric auto char *vp; 117660215Seric auto int vsize; 117757216Seric 117860537Seric if (tTd(38, 2)) 117968350Seric printf("nis_map_open(%s, %s)\n", 118068350Seric map->map_mname, map->map_file); 118160089Seric 118260207Seric if (mode != O_RDONLY) 118360207Seric { 118464650Seric /* issue a pseudo-error message */ 118564650Seric #ifdef ENOSYS 118664650Seric errno = ENOSYS; 118764650Seric #else 118864650Seric # ifdef EFTYPE 118964650Seric errno = EFTYPE; 119064650Seric # else 119164650Seric errno = ENXIO; 119264650Seric # endif 119364650Seric #endif 119460207Seric return FALSE; 119560207Seric } 119660207Seric 119760089Seric p = strchr(map->map_file, '@'); 119860089Seric if (p != NULL) 119960089Seric { 120060089Seric *p++ = '\0'; 120160089Seric if (*p != '\0') 120260089Seric map->map_domain = p; 120360089Seric } 120460215Seric 120560089Seric if (*map->map_file == '\0') 120660089Seric map->map_file = "mail.aliases"; 120760089Seric 120866157Seric if (map->map_domain == NULL) 120966157Seric { 121066157Seric yperr = yp_get_default_domain(&map->map_domain); 121166157Seric if (yperr != 0) 121266157Seric { 121366744Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 121468350Seric syserr("421 NIS map %s specified, but NIS not running\n", 121566744Seric map->map_file); 121666157Seric return FALSE; 121766157Seric } 121866157Seric } 121966157Seric 122060215Seric /* check to see if this map actually exists */ 122160089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 122260089Seric &vp, &vsize); 122360537Seric if (tTd(38, 10)) 122460089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 122560089Seric map->map_domain, map->map_file, yperr_string(yperr)); 122660089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 122768350Seric { 122868350Seric if (!bitset(MF_ALIAS, map->map_mflags) || 122968350Seric aliaswait(map, NULL, TRUE)) 123068350Seric return TRUE; 123168350Seric } 123260215Seric 123360215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 123468735Seric { 123568735Seric syserr("421 Cannot bind to map %s in domain %s: %s", 123668735Seric map->map_file, map->map_domain, yperr_string(yperr)); 123768735Seric } 123860215Seric 123960089Seric return FALSE; 124060089Seric } 124160089Seric 124260089Seric 124360089Seric /* 124457208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 124557208Seric */ 124657208Seric 124757208Seric char * 124860089Seric nis_map_lookup(map, name, av, statp) 124957208Seric MAP *map; 125060089Seric char *name; 125157208Seric char **av; 125259084Seric int *statp; 125357208Seric { 125457208Seric char *vp; 125557642Seric auto int vsize; 125659274Seric int buflen; 125760215Seric int yperr; 125860089Seric char keybuf[MAXNAME + 1]; 125957208Seric 126060537Seric if (tTd(38, 20)) 126168350Seric printf("nis_map_lookup(%s, %s)\n", 126268350Seric map->map_mname, name); 126360089Seric 126460089Seric buflen = strlen(name); 126560089Seric if (buflen > sizeof keybuf - 1) 126660089Seric buflen = sizeof keybuf - 1; 126760089Seric bcopy(name, keybuf, buflen + 1); 126860207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 126960089Seric makelower(keybuf); 127063753Seric yperr = YPERR_KEY; 127163753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 127263753Seric { 127363753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 127463753Seric &vp, &vsize); 127563753Seric if (yperr == 0) 127663753Seric map->map_mflags &= ~MF_TRY1NULL; 127763753Seric } 127863753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 127963753Seric { 128059274Seric buflen++; 128163753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 128263753Seric &vp, &vsize); 128363753Seric if (yperr == 0) 128463753Seric map->map_mflags &= ~MF_TRY0NULL; 128563753Seric } 128660089Seric if (yperr != 0) 128760089Seric { 128860089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 128960215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 129057208Seric return NULL; 129160089Seric } 129260207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 129363753Seric return map_rewrite(map, name, strlen(name), NULL); 129463753Seric else 129563753Seric return map_rewrite(map, vp, vsize, av); 129657208Seric } 129757208Seric 129869401Seric 129969401Seric /* 130069401Seric ** NIS_GETCANONNAME -- look up canonical name in NIS 130169401Seric */ 130269401Seric 130369401Seric bool 130469401Seric nis_getcanonname(name, hbsize, statp) 130569401Seric char *name; 130669401Seric int hbsize; 130769401Seric int *statp; 130869401Seric { 130969401Seric char *vp; 131069401Seric auto int vsize; 131169401Seric int keylen; 131269401Seric int yperr; 131369401Seric static bool try0null = TRUE; 131469401Seric static bool try1null = TRUE; 131569401Seric static char *yp_domain = NULL; 131669748Seric char *domain; 131769780Seric char *cname; 131869401Seric char host_record[MAXLINE]; 131969780Seric char fbuf[MAXNAME]; 132069780Seric char nbuf[MAXNAME + 1]; 132169401Seric extern char *get_column(); 132269401Seric 132369401Seric if (tTd(38, 20)) 132469401Seric printf("nis_getcanonname(%s)\n", name); 132569401Seric 132669780Seric if (strlen(name) >= sizeof nbuf) 132769780Seric { 132869780Seric *statp = EX_UNAVAILABLE; 132969780Seric return FALSE; 133069780Seric } 133169780Seric (void) strcpy(nbuf, name); 133269780Seric shorten_hostname(nbuf); 133369401Seric 133469401Seric /* we only accept single token search key */ 133569780Seric if (strchr(nbuf, '.')) 133669401Seric { 133769401Seric *statp = EX_NOHOST; 133869401Seric return FALSE; 133969401Seric } 134069401Seric 134169780Seric keylen = strlen(nbuf); 134269401Seric 134369401Seric if (yp_domain == NULL) 134469401Seric yp_get_default_domain(&yp_domain); 134569780Seric makelower(nbuf); 134669401Seric yperr = YPERR_KEY; 134769401Seric if (try0null) 134869401Seric { 134969780Seric yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 135069401Seric &vp, &vsize); 135169401Seric if (yperr == 0) 135269401Seric try1null = FALSE; 135369401Seric } 135469401Seric if (yperr == YPERR_KEY && try1null) 135569401Seric { 135669401Seric keylen++; 135769780Seric yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 135869401Seric &vp, &vsize); 135969401Seric if (yperr == 0) 136069401Seric try0null = FALSE; 136169401Seric } 136269401Seric if (yperr != 0) 136369401Seric { 136469401Seric if (yperr == YPERR_KEY) 136569401Seric *statp = EX_NOHOST; 136669401Seric else if (yperr == YPERR_BUSY) 136769401Seric *statp = EX_TEMPFAIL; 136869401Seric else 136969401Seric *statp = EX_UNAVAILABLE; 137069401Seric return FALSE; 137169401Seric } 137269401Seric strncpy(host_record, vp, vsize); 137369401Seric host_record[vsize] = '\0'; 137469663Seric if (tTd(38, 44)) 137569663Seric printf("got record `%s'\n", host_record); 137669780Seric cname = get_column(host_record, 1, '\0', fbuf); 137769401Seric if (cname == NULL) 137869401Seric { 137969401Seric /* this should not happen, but.... */ 138069401Seric *statp = EX_NOHOST; 138169401Seric return FALSE; 138269401Seric } 138369401Seric 138469703Seric if (strchr(cname, '.') != NULL) 138569401Seric { 138669703Seric domain = ""; 138769703Seric } 138869703Seric else 138969703Seric { 139069703Seric domain = macvalue('m', CurEnv); 139169703Seric if (domain == NULL) 139269703Seric domain = ""; 139369703Seric } 139469703Seric if (hbsize >= strlen(cname) + strlen(domain) + 1) 139569703Seric { 139669703Seric if (domain[0] == '\0') 139769703Seric strcpy(name, vp); 139869703Seric else 139969703Seric sprintf(name, "%s.%s", vp, domain); 140069401Seric *statp = EX_OK; 140169401Seric return TRUE; 140269401Seric } 140369401Seric *statp = EX_UNAVAILABLE; 140469401Seric return FALSE; 140569401Seric } 140669401Seric 140768350Seric #endif 140868350Seric /* 140968350Seric ** NISPLUS Modules 141068350Seric ** 141168350Seric ** This code donated by Sun Microsystems. 141268350Seric */ 141367848Seric 141468350Seric #ifdef NISPLUS 141568350Seric 141668350Seric #undef NIS /* symbol conflict in nis.h */ 141768350Seric #include <rpcsvc/nis.h> 141868350Seric #include <rpcsvc/nislib.h> 141968350Seric 142068350Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 142168350Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 142268350Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 142368350Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 142468350Seric 142567848Seric /* 142668350Seric ** NISPLUS_MAP_OPEN -- open nisplus table 142767848Seric */ 142867848Seric 142968350Seric bool 143068350Seric nisplus_map_open(map, mode) 143167848Seric MAP *map; 143268350Seric int mode; 143367848Seric { 143468350Seric register char *p; 143568350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 143668350Seric nis_result *res = NULL; 143768350Seric u_int objs_len; 143868350Seric nis_object *obj_ptr; 143968350Seric int retry_cnt, max_col, i; 144068350Seric 144168350Seric if (tTd(38, 2)) 144268350Seric printf("nisplus_map_open(%s, %s, %d)\n", 144368350Seric map->map_mname, map->map_file, mode); 144468350Seric 144568350Seric if (mode != O_RDONLY) 144668350Seric { 144768350Seric errno = ENODEV; 144868350Seric return FALSE; 144968350Seric } 145068350Seric 145168350Seric if (*map->map_file == '\0') 145268350Seric map->map_file = "mail_aliases.org_dir"; 145368350Seric 145468350Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 145568350Seric { 145668350Seric /* set default NISPLUS Domain to $m */ 145768350Seric extern char *nisplus_default_domain(); 145868350Seric 145968350Seric map->map_domain = newstr(nisplus_default_domain()); 146068350Seric if (tTd(38, 2)) 146168350Seric printf("nisplus_map_open(%s): using domain %s\n", 146268350Seric map->map_file, map->map_domain); 146368350Seric } 146468350Seric if (!PARTIAL_NAME(map->map_file)) 146568350Seric map->map_domain = newstr(""); 146668350Seric 146768350Seric /* check to see if this map actually exists */ 146868350Seric if (PARTIAL_NAME(map->map_file)) 146968350Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 147068350Seric else 147168350Seric strcpy(qbuf, map->map_file); 147268350Seric 147368350Seric retry_cnt = 0; 147468350Seric while (res == NULL || res->status != NIS_SUCCESS) 147568350Seric { 147668350Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 147768350Seric switch (res->status) 147868350Seric { 147968350Seric case NIS_SUCCESS: 148068350Seric case NIS_TRYAGAIN: 148168350Seric case NIS_RPCERROR: 148268350Seric case NIS_NAMEUNREACHABLE: 148368350Seric break; 148468350Seric 148568350Seric default: /* all other nisplus errors */ 148668350Seric #if 0 148768350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 148868350Seric syserr("421 Cannot find table %s.%s: %s", 148968350Seric map->map_file, map->map_domain, 149068350Seric nis_sperrno(res->status)); 149168350Seric #endif 149268350Seric errno = EBADR; 149368350Seric return FALSE; 149468350Seric } 149568350Seric sleep(2); /* try not to overwhelm hosed server */ 149668350Seric if (retry_cnt++ > 4) 149768350Seric { 149868350Seric errno = EBADR; 149968350Seric return FALSE; 150068350Seric } 150168350Seric } 150268350Seric 150368350Seric if (NIS_RES_NUMOBJ(res) != 1 || 150468350Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 150568350Seric { 150668350Seric if (tTd(38, 10)) 150768350Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 150868350Seric #if 0 150968350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 151068350Seric syserr("421 %s.%s: %s is not a table", 151168350Seric map->map_file, map->map_domain, 151268350Seric nis_sperrno(res->status)); 151368350Seric #endif 151468350Seric errno = EBADR; 151568350Seric return FALSE; 151668350Seric } 151768350Seric /* default key column is column 0 */ 151868350Seric if (map->map_keycolnm == NULL) 151968350Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 152068350Seric 152168350Seric max_col = COL_MAX(res); 152268350Seric 152368350Seric /* verify the key column exist */ 152468350Seric for (i=0; i< max_col; i++) 152568350Seric { 152668350Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 152768350Seric break; 152868350Seric } 152968350Seric if (i == max_col) 153068350Seric { 153168350Seric if (tTd(38, 2)) 153268350Seric printf("nisplus_map_open(%s): can not find key column %s\n", 153368350Seric map->map_file, map->map_keycolnm); 153468350Seric errno = EBADR; 153568350Seric return FALSE; 153668350Seric } 153768350Seric 153868350Seric /* default value column is the last column */ 153968350Seric if (map->map_valcolnm == NULL) 154068350Seric { 154168350Seric map->map_valcolno = max_col - 1; 154268350Seric return TRUE; 154368350Seric } 154468350Seric 154568350Seric for (i=0; i< max_col; i++) 154668350Seric { 154768350Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 154868350Seric { 154968350Seric map->map_valcolno = i; 155068350Seric return TRUE; 155168350Seric } 155268350Seric } 155368350Seric 155468350Seric if (tTd(38, 2)) 155568350Seric printf("nisplus_map_open(%s): can not find column %s\n", 155668350Seric map->map_file, map->map_keycolnm); 155768350Seric errno = EBADR; 155868350Seric return FALSE; 155967848Seric } 156067848Seric 156167848Seric 156267848Seric /* 156368350Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 156467848Seric */ 156567848Seric 156668350Seric char * 156768350Seric nisplus_map_lookup(map, name, av, statp) 156867848Seric MAP *map; 156968350Seric char *name; 157068350Seric char **av; 157168350Seric int *statp; 157267848Seric { 157368350Seric char *vp; 157468350Seric auto int vsize; 157568350Seric int buflen; 157668350Seric char search_key[MAXNAME + 1]; 157768350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 157868350Seric nis_result *result; 157968350Seric 158068350Seric if (tTd(38, 20)) 158168350Seric printf("nisplus_map_lookup(%s, %s)\n", 158268350Seric map->map_mname, name); 158368350Seric 158468350Seric if (!bitset(MF_OPEN, map->map_mflags)) 158568350Seric { 158668350Seric if (nisplus_map_open(map, O_RDONLY)) 158768350Seric map->map_mflags |= MF_OPEN; 158868350Seric else 158968350Seric { 159068350Seric *statp = EX_UNAVAILABLE; 159168350Seric return NULL; 159268350Seric } 159368350Seric } 159468350Seric 159568350Seric buflen = strlen(name); 159668350Seric if (buflen > sizeof search_key - 1) 159768350Seric buflen = sizeof search_key - 1; 159868350Seric bcopy(name, search_key, buflen + 1); 159968350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 160068350Seric makelower(search_key); 160168350Seric 160268350Seric /* construct the query */ 160368350Seric if (PARTIAL_NAME(map->map_file)) 160468350Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 160568350Seric search_key, map->map_file, map->map_domain); 160668350Seric else 160768350Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 160868350Seric search_key, map->map_file); 160968350Seric 161068350Seric if (tTd(38, 20)) 161168350Seric printf("qbuf=%s\n", qbuf); 161268350Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 161368350Seric if (result->status == NIS_SUCCESS) 161468350Seric { 161568350Seric int count; 161668350Seric char *str; 161768350Seric 161868350Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 161968350Seric { 162068350Seric if (LogLevel > 10) 162168350Seric syslog(LOG_WARNING, 162268350Seric "%s:Lookup error, expected 1 entry, got (%d)", 162368350Seric map->map_file, count); 162468350Seric 162568350Seric /* ignore second entry */ 162668350Seric if (tTd(38, 20)) 162768350Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 162868350Seric name, count); 162968350Seric } 163068350Seric 163168350Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 163268350Seric /* set the length of the result */ 163368350Seric if (vp == NULL) 163468350Seric vp = ""; 163568350Seric vsize = strlen(vp); 163668350Seric if (tTd(38, 20)) 163768350Seric printf("nisplus_map_lookup(%s), found %s\n", 163868350Seric name, vp); 163968350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 164068350Seric str = map_rewrite(map, name, strlen(name), NULL); 164168350Seric else 164268350Seric str = map_rewrite(map, vp, vsize, av); 164368350Seric nis_freeresult(result); 164468350Seric #ifdef MAP_EXIT_STAT 164568350Seric *statp = EX_OK; 164668350Seric #endif 164768350Seric return str; 164868350Seric } 164968350Seric else 165068350Seric { 165168350Seric #ifdef MAP_EXIT_STAT 165268350Seric if (result->status == NIS_NOTFOUND) 165368350Seric *statp = EX_NOTFOUND; 165468350Seric else if (result->status == NIS_TRYAGAIN) 165568350Seric *statp = EX_TEMPFAIL; 165668350Seric else 165768350Seric { 165868350Seric *statp = EX_UNAVAILABLE; 165968350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 166068350Seric } 166168350Seric #else 166268350Seric if ((result->status != NIS_NOTFOUND) && 166368350Seric (result->status != NIS_TRYAGAIN)) 166468350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 166568350Seric #endif 166668350Seric } 166768350Seric if (tTd(38, 20)) 166868350Seric printf("nisplus_map_lookup(%s), failed\n", name); 166968350Seric nis_freeresult(result); 167068350Seric return NULL; 167167848Seric } 167267848Seric 167368350Seric 167469401Seric 167569401Seric /* 167669401Seric ** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 167769401Seric */ 167869401Seric 167969401Seric bool 168069401Seric nisplus_getcanonname(name, hbsize, statp) 168169401Seric char *name; 168269401Seric int hbsize; 168369401Seric int *statp; 168469401Seric { 168569401Seric char *vp; 168669401Seric auto int vsize; 168769401Seric int buflen; 168869401Seric nis_result *result; 168969401Seric char *p; 169069401Seric int len; 169169780Seric char nbuf[MAXNAME + 1]; 169269780Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 169369401Seric 169469780Seric if (strlen(name) >= sizeof nbuf) 169569780Seric { 169669780Seric *statp = EX_UNAVAILABLE; 169769780Seric return FALSE; 169869780Seric } 169969780Seric (void) strcpy(nbuf, name); 170069780Seric shorten_hostname(nbuf); 170169401Seric 170269780Seric p = strchr(nbuf, '.'); 170369401Seric if (p == NULL) 170469401Seric { 170569401Seric /* single token */ 170669780Seric sprintf(qbuf, "[name=%s],hosts.org_dir", nbuf); 170769401Seric } 170869401Seric else if (p[1] != '\0') 170969401Seric { 171069780Seric /* multi token -- take only first token in nbuf */ 171169401Seric *p = '\0'; 171269780Seric sprintf(qbuf, "[name=%s],hosts.org_dir.%s", nbuf, &p[1]); 171369401Seric } 171469401Seric else 171569401Seric { 171669401Seric *statp = EX_NOHOST; 171769401Seric return FALSE; 171869401Seric } 171969401Seric 172069401Seric if (tTd(38, 20)) 172169478Seric printf("\nnisplus_getcanoname(%s), qbuf=%s\n", 172269780Seric name, qbuf); 172369401Seric 172469780Seric result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 172569401Seric NULL, NULL); 172669401Seric 172769401Seric if (result->status == NIS_SUCCESS) 172869401Seric { 172969401Seric int count; 173069401Seric char *str; 173169401Seric char *domain; 173269401Seric 173369401Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 173469401Seric { 173569401Seric #ifdef LOG 173669401Seric if (LogLevel > 10) 173769401Seric syslog(LOG_WARNING, 173869401Seric "nisplus_getcanonname: Lookup error, expected 1 entry, got (%d)", 173969401Seric count); 174069401Seric #endif 174169401Seric 174269401Seric /* ignore second entry */ 174369401Seric if (tTd(38, 20)) 174469401Seric printf("nisplus_getcanoname(%s), got %d entries, addtional entries ignores\n", name); 174569401Seric } 174669401Seric 174769401Seric if (tTd(38, 20)) 174869401Seric printf("nisplus_getcanoname(%s), found in directory \"%s\"\n", 174969401Seric name, (NIS_RES_OBJECT(result))->zo_domain); 175069401Seric 175169401Seric 175269401Seric vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 175369401Seric vsize = strlen(vp); 175469401Seric if (tTd(38, 20)) 175569401Seric printf("nisplus_getcanonname(%s), found %s\n", 175669401Seric name, vp); 175769703Seric if (strchr(vp, '.') != NULL) 175869703Seric { 175969636Seric domain = ""; 176069703Seric } 176169703Seric else 176269703Seric { 176369703Seric domain = macvalue('m', CurEnv); 176469703Seric if (domain == NULL) 176569703Seric domain = ""; 176669703Seric } 176769636Seric if (hbsize > vsize + (int) strlen(domain) + 1) 176869401Seric { 176969636Seric if (domain[0] == '\0') 177069636Seric strcpy(name, vp); 177169636Seric else 177269636Seric sprintf(name, "%s.%s", vp, domain); 177369401Seric *statp = EX_OK; 177469401Seric } 177569401Seric else 177669401Seric *statp = EX_NOHOST; 177769401Seric nis_freeresult(result); 177869401Seric return TRUE; 177969401Seric } 178069401Seric else 178169401Seric { 178269401Seric if (result->status == NIS_NOTFOUND) 178369401Seric *statp = EX_NOHOST; 178469401Seric else if (result->status == NIS_TRYAGAIN) 178569401Seric *statp = EX_TEMPFAIL; 178669401Seric else 178769401Seric *statp = EX_UNAVAILABLE; 178869401Seric } 178969401Seric if (tTd(38, 20)) 179069401Seric printf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 179169401Seric name, result->status, *statp); 179269401Seric nis_freeresult(result); 179369401Seric return FALSE; 179469401Seric } 179569401Seric 179669401Seric 179768350Seric char * 179868350Seric nisplus_default_domain() 179968350Seric { 180068528Seric static char default_domain[MAXNAME + 1] = ""; 180168350Seric char *p; 180268350Seric 180368350Seric if (default_domain[0] != '\0') 180468350Seric return(default_domain); 180568350Seric 180668458Seric p = nis_local_directory(); 180768350Seric strcpy(default_domain, p); 180868458Seric return default_domain; 180968350Seric } 181068350Seric 181168350Seric #endif /* NISPLUS */ 181267848Seric /* 181368350Seric ** HESIOD Modules 181468350Seric */ 181568350Seric 181668350Seric #ifdef HESIOD 181768350Seric 181868350Seric #include <hesiod.h> 181968350Seric 182068350Seric char * 182168350Seric hes_map_lookup(map, name, av, statp) 182268350Seric MAP *map; 182368350Seric char *name; 182468350Seric char **av; 182568350Seric int *statp; 182668350Seric { 182768350Seric char **hp; 182868350Seric 182968350Seric if (tTd(38, 20)) 183068350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 183168350Seric 183269688Seric if (name[0] == '\\') 183369688Seric { 183469688Seric char *np; 183569688Seric int nl; 183669688Seric char nbuf[MAXNAME]; 183769688Seric 183869688Seric nl = strlen(name); 183969688Seric if (nl < sizeof nbuf - 1) 184069688Seric np = nbuf; 184169688Seric else 184269688Seric np = xalloc(strlen(name) + 2); 184369688Seric np[0] = '\\'; 184469688Seric strcpy(&np[1], name); 184569688Seric hp = hes_resolve(np, map->map_file); 184669688Seric if (np != nbuf) 184769688Seric free(np); 184869688Seric } 184969688Seric else 185069688Seric { 185169688Seric hp = hes_resolve(name, map->map_file); 185269688Seric } 185369623Seric if (hp == NULL || hp[0] == NULL) 185468350Seric return NULL; 185568350Seric 185669623Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 185769623Seric return map_rewrite(map, name, strlen(name), NULL); 185869623Seric else 185969623Seric return map_rewrite(map, hp[0], strlen(hp[0]), av); 186068350Seric } 186168350Seric 186268350Seric #endif 186368350Seric /* 186468350Seric ** NeXT NETINFO Modules 186568350Seric */ 186668350Seric 186768350Seric #ifdef NETINFO 186868350Seric 186968350Seric #define NETINFO_DEFAULT_DIR "/aliases" 187068350Seric #define NETINFO_DEFAULT_PROPERTY "members" 187168350Seric 187268350Seric 187368350Seric /* 187468350Seric ** NI_MAP_OPEN -- open NetInfo Aliases 187568350Seric */ 187668350Seric 187768350Seric bool 187868350Seric ni_map_open(map, mode) 187968350Seric MAP *map; 188068350Seric int mode; 188168350Seric { 188268350Seric char *p; 188368350Seric 188468350Seric if (tTd(38, 20)) 188568350Seric printf("ni_map_open: %s\n", map->map_file); 188668350Seric 188768350Seric if (*map->map_file == '\0') 188868350Seric map->map_file = NETINFO_DEFAULT_DIR; 188968350Seric 189068350Seric if (map->map_valcolnm == NULL) 189168350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 189268350Seric 189368350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 189468350Seric map->map_coldelim = ','; 189568350Seric 189668350Seric return TRUE; 189768350Seric } 189868350Seric 189968350Seric 190068350Seric /* 190168350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 190268350Seric */ 190368350Seric 190468350Seric char * 190568350Seric ni_map_lookup(map, name, av, statp) 190668350Seric MAP *map; 190768350Seric char *name; 190868350Seric char **av; 190968350Seric int *statp; 191068350Seric { 191168350Seric char *res; 191268350Seric char *propval; 191368350Seric extern char *ni_propval(); 191468350Seric 191568350Seric if (tTd(38, 20)) 191668350Seric printf("ni_map_lookup(%s, %s)\n", 191768350Seric map->map_mname, name); 191868350Seric 191968350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 192068350Seric map->map_valcolnm, map->map_coldelim); 192168350Seric 192268350Seric if (propval == NULL) 192368350Seric return NULL; 192468350Seric 192568350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 192668350Seric res = map_rewrite(map, name, strlen(name), NULL); 192768350Seric else 192868350Seric res = map_rewrite(map, propval, strlen(propval), av); 192968350Seric free(propval); 193068350Seric return res; 193168350Seric } 193268350Seric 193368350Seric #endif 193468350Seric /* 193568350Seric ** TEXT (unindexed text file) Modules 193668350Seric ** 193768350Seric ** This code donated by Sun Microsystems. 193868350Seric */ 193968350Seric 194068350Seric 194168350Seric /* 194268350Seric ** TEXT_MAP_OPEN -- open text table 194368350Seric */ 194468350Seric 194568350Seric bool 194668350Seric text_map_open(map, mode) 194768350Seric MAP *map; 194868350Seric int mode; 194968350Seric { 195068350Seric struct stat sbuf; 195168350Seric 195268350Seric if (tTd(38, 2)) 195368350Seric printf("text_map_open(%s, %s, %d)\n", 195468350Seric map->map_mname, map->map_file, mode); 195568350Seric 195668350Seric if (mode != O_RDONLY) 195768350Seric { 195868350Seric errno = ENODEV; 195968350Seric return FALSE; 196068350Seric } 196168350Seric 196268350Seric if (*map->map_file == '\0') 196368350Seric { 196468350Seric if (tTd(38, 2)) 196568350Seric printf("text_map_open: file name required\n"); 196668350Seric return FALSE; 196768350Seric } 196868350Seric 196968350Seric if (map->map_file[0] != '/') 197068350Seric { 197168350Seric if (tTd(38, 2)) 197268350Seric printf("text_map_open(%s): file name must be fully qualified\n", 197368350Seric map->map_file); 197468350Seric return FALSE; 197568350Seric } 197668350Seric /* check to see if this map actually accessable */ 197768350Seric if (access(map->map_file, R_OK) <0) 197868350Seric return FALSE; 197968350Seric 198068350Seric /* check to see if this map actually exist */ 198168350Seric if (stat(map->map_file, &sbuf) <0) 198268350Seric { 198368350Seric if (tTd(38, 2)) 198468350Seric printf("text_map_open(%s): can not stat %s\n", 198568350Seric map->map_file, map->map_file); 198668350Seric return FALSE; 198768350Seric } 198868350Seric 198968350Seric if (!S_ISREG(sbuf.st_mode)) 199068350Seric { 199168350Seric if (tTd(38, 2)) 199268350Seric printf("text_map_open(%s): %s is not a file\n", 199368350Seric map->map_file, map->map_file); 199468350Seric return FALSE; 199568350Seric } 199668350Seric 199768350Seric if (map->map_keycolnm == NULL) 199868350Seric map->map_keycolno = 0; 199968350Seric else 200068350Seric { 200168350Seric if (!isdigit(*map->map_keycolnm)) 200268350Seric { 200368350Seric if (tTd(38, 2)) 200468350Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 200568350Seric map->map_file, map->map_keycolnm); 200668350Seric return FALSE; 200768350Seric } 200868350Seric map->map_keycolno = atoi(map->map_keycolnm); 200968350Seric } 201068350Seric 201168350Seric if (map->map_valcolnm == NULL) 201268350Seric map->map_valcolno = 0; 201368350Seric else 201468350Seric { 201568350Seric if (!isdigit(*map->map_valcolnm)) 201668350Seric { 201768350Seric if (tTd(38, 2)) 201868350Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 201968350Seric map->map_file, map->map_valcolnm); 202068350Seric return FALSE; 202168350Seric } 202268350Seric map->map_valcolno = atoi(map->map_valcolnm); 202368350Seric } 202468350Seric 202568350Seric if (tTd(38, 2)) 202668350Seric { 202768520Seric printf("text_map_open(%s): delimiter = ", 202868520Seric map->map_file); 202968520Seric if (map->map_coldelim == '\0') 203068520Seric printf("(white space)\n"); 203168520Seric else 203268520Seric printf("%c\n", map->map_coldelim); 203368350Seric } 203468350Seric 203568350Seric return TRUE; 203668350Seric } 203768350Seric 203868350Seric 203968350Seric /* 204068350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 204168350Seric */ 204268350Seric 204368350Seric char * 204468350Seric text_map_lookup(map, name, av, statp) 204568350Seric MAP *map; 204668350Seric char *name; 204768350Seric char **av; 204868350Seric int *statp; 204968350Seric { 205068350Seric char *vp; 205168350Seric auto int vsize; 205268350Seric int buflen; 205368350Seric char search_key[MAXNAME + 1]; 205468350Seric char linebuf[MAXLINE]; 205568350Seric FILE *f; 205668528Seric char buf[MAXNAME + 1]; 205768350Seric char delim; 205868350Seric int key_idx; 205968350Seric bool found_it; 206068350Seric extern char *get_column(); 206168350Seric 206268350Seric 206368350Seric found_it = FALSE; 206468350Seric if (tTd(38, 20)) 206568350Seric printf("text_map_lookup(%s)\n", name); 206668350Seric 206768350Seric buflen = strlen(name); 206868350Seric if (buflen > sizeof search_key - 1) 206968350Seric buflen = sizeof search_key - 1; 207068350Seric bcopy(name, search_key, buflen + 1); 207168350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 207268350Seric makelower(search_key); 207368350Seric 207468350Seric f = fopen(map->map_file, "r"); 207568350Seric if (f == NULL) 207668350Seric { 207768350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 207868350Seric *statp = EX_UNAVAILABLE; 207968350Seric return NULL; 208068350Seric } 208168350Seric key_idx = map->map_keycolno; 208268350Seric delim = map->map_coldelim; 208368350Seric while (fgets(linebuf, MAXLINE, f)) 208468350Seric { 208568350Seric char *lf; 208668350Seric if (linebuf[0] == '#') 208768350Seric continue; /* skip comment line */ 208868350Seric if (lf = strchr(linebuf, '\n')) 208968350Seric *lf = '\0'; 209068350Seric if (!strcasecmp(search_key, 209168350Seric get_column(linebuf, key_idx, delim, buf))) 209268350Seric { 209368350Seric found_it = TRUE; 209468350Seric break; 209568350Seric } 209668350Seric } 209768350Seric fclose(f); 209868350Seric if (!found_it) 209968350Seric { 210068350Seric #ifdef MAP_EXIT_STAT 210168350Seric *statp = EX_NOTFOUND; 210268350Seric #endif 210368350Seric return(NULL); 210468350Seric } 210568350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 210668350Seric vsize = strlen(vp); 210768350Seric #ifdef MAP_EXIT_STAT 210868350Seric *statp = EX_OK; 210968350Seric #endif 211068350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 211168350Seric return map_rewrite(map, name, strlen(name), NULL); 211268350Seric else 211368350Seric return map_rewrite(map, vp, vsize, av); 211468350Seric } 211569401Seric 211669401Seric 211769401Seric /* 211869401Seric ** TEXT_GETCANONNAME -- look up canonical name in hosts file 211969401Seric */ 212069401Seric 212169401Seric bool 212269401Seric text_getcanonname(name, hbsize, statp) 212369401Seric char *name; 212469401Seric int hbsize; 212569401Seric int *statp; 212669401Seric { 212769401Seric int key_idx; 212869401Seric char *cname; 212969401Seric bool found; 213069401Seric FILE *f; 213169401Seric char linebuf[MAXLINE]; 213269401Seric char cbuf[MAXNAME + 1]; 213369780Seric char fbuf[MAXNAME + 1]; 213469780Seric char nbuf[MAXNAME + 1]; 213569401Seric extern char *get_column(); 213669401Seric 213769780Seric if (strlen(name) >= sizeof nbuf) 213869780Seric { 213969780Seric *statp = EX_UNAVAILABLE; 214069780Seric return FALSE; 214169780Seric } 214269780Seric (void) strcpy(nbuf, name); 214369780Seric shorten_hostname(nbuf); 214469401Seric 214569401Seric /* we only accept single token search key */ 214669780Seric if (strchr(nbuf, '.') != NULL) 214769401Seric { 214869401Seric *statp = EX_NOHOST; 214969401Seric return FALSE; 215069401Seric } 215169401Seric 215269401Seric found = FALSE; 215369401Seric 215469401Seric f = fopen(HostsFile, "r"); 215569401Seric if (f == NULL) 215669401Seric { 215769401Seric #ifdef MAP_EXIT_STAT 215869401Seric *statp = EX_UNAVAILABLE; 215969401Seric #endif 216069401Seric return FALSE; 216169401Seric } 216269401Seric while (!found && fgets(linebuf, MAXLINE, f) != NULL) 216369401Seric { 216469401Seric char *p; 216569401Seric 216669401Seric if (linebuf[0] == '#') 216769401Seric continue; 216869401Seric if ((p = strchr(linebuf, '\n')) != NULL) 216969401Seric *p = '\0'; 217069663Seric cname = get_column(linebuf, 1, '\0', cbuf); 217169780Seric if (cname != NULL && strcasecmp(nbuf, cname) == 0) 217269401Seric { 217369401Seric found = TRUE; 217469401Seric break; 217569401Seric } 217669401Seric 217769401Seric key_idx = 2; 217869780Seric while ((p = get_column(linebuf, key_idx, '\0', fbuf)) != NULL) 217969401Seric { 218069780Seric if (strcasecmp(nbuf, p) == 0) 218169401Seric { 218269401Seric found = TRUE; 218369401Seric break; 218469401Seric } 218569401Seric key_idx++; 218669401Seric } 218769401Seric } 218869401Seric fclose(f); 218969401Seric if (!found) 219069401Seric { 219169401Seric *statp = EX_NOHOST; 219269401Seric return FALSE; 219369401Seric } 219469401Seric 219569401Seric if (hbsize >= strlen(cname)) 219669401Seric { 219769401Seric strcpy(name, cname); 219869401Seric *statp = EX_OK; 219969401Seric return TRUE; 220069401Seric } 220169401Seric *statp = EX_UNAVAILABLE; 220269401Seric return FALSE; 220369401Seric } 220468350Seric /* 220560089Seric ** STAB (Symbol Table) Modules 220660089Seric */ 220760089Seric 220860089Seric 220960089Seric /* 221060207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 221160089Seric */ 221260089Seric 221360089Seric char * 221461707Seric stab_map_lookup(map, name, av, pstat) 221560089Seric register MAP *map; 221660089Seric char *name; 221761707Seric char **av; 221861707Seric int *pstat; 221960089Seric { 222060089Seric register STAB *s; 222160089Seric 222260537Seric if (tTd(38, 20)) 222368350Seric printf("stab_lookup(%s, %s)\n", 222468350Seric map->map_mname, name); 222560089Seric 222660089Seric s = stab(name, ST_ALIAS, ST_FIND); 222760089Seric if (s != NULL) 222860089Seric return (s->s_alias); 222960089Seric return (NULL); 223060089Seric } 223160089Seric 223260089Seric 223360089Seric /* 223460207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 223560089Seric */ 223660089Seric 223760089Seric void 223860089Seric stab_map_store(map, lhs, rhs) 223960089Seric register MAP *map; 224060089Seric char *lhs; 224160089Seric char *rhs; 224260089Seric { 224360089Seric register STAB *s; 224460089Seric 224560089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 224660089Seric s->s_alias = newstr(rhs); 224760089Seric } 224860089Seric 224960089Seric 225060089Seric /* 225160207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 225260207Seric ** 225360207Seric ** This is a wierd case -- it is only intended as a fallback for 225460207Seric ** aliases. For this reason, opens for write (only during a 225560207Seric ** "newaliases") always fails, and opens for read open the 225660207Seric ** actual underlying text file instead of the database. 225760089Seric */ 225860089Seric 225960089Seric bool 226060089Seric stab_map_open(map, mode) 226160089Seric register MAP *map; 226260089Seric int mode; 226360089Seric { 226463835Seric FILE *af; 226564284Seric struct stat st; 226663835Seric 226760537Seric if (tTd(38, 2)) 226868350Seric printf("stab_map_open(%s, %s)\n", 226968350Seric map->map_mname, map->map_file); 227060089Seric 227160089Seric if (mode != O_RDONLY) 227260207Seric { 227360207Seric errno = ENODEV; 227460089Seric return FALSE; 227560207Seric } 227660089Seric 227763835Seric af = fopen(map->map_file, "r"); 227863835Seric if (af == NULL) 227963835Seric return FALSE; 228068350Seric readaliases(map, af, FALSE, FALSE); 228164284Seric 228264284Seric if (fstat(fileno(af), &st) >= 0) 228364284Seric map->map_mtime = st.st_mtime; 228463835Seric fclose(af); 228563835Seric 228660089Seric return TRUE; 228760089Seric } 228860089Seric /* 228960089Seric ** Implicit Modules 229056822Seric ** 229160089Seric ** Tries several types. For back compatibility of aliases. 229256822Seric */ 229356822Seric 229460089Seric 229560089Seric /* 229660207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 229760089Seric */ 229860089Seric 229960089Seric char * 230060089Seric impl_map_lookup(map, name, av, pstat) 230160089Seric MAP *map; 230260089Seric char *name; 230356822Seric char **av; 230460089Seric int *pstat; 230556822Seric { 230660537Seric if (tTd(38, 20)) 230768350Seric printf("impl_map_lookup(%s, %s)\n", 230868350Seric map->map_mname, name); 230956822Seric 231060089Seric #ifdef NEWDB 231160207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 231260089Seric return db_map_lookup(map, name, av, pstat); 231360089Seric #endif 231460089Seric #ifdef NDBM 231560207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 231660089Seric return ndbm_map_lookup(map, name, av, pstat); 231760089Seric #endif 231860089Seric return stab_map_lookup(map, name, av, pstat); 231960089Seric } 232060089Seric 232160089Seric /* 232260207Seric ** IMPL_MAP_STORE -- store in open databases 232360089Seric */ 232460089Seric 232560089Seric void 232660089Seric impl_map_store(map, lhs, rhs) 232760089Seric MAP *map; 232860089Seric char *lhs; 232960089Seric char *rhs; 233060089Seric { 233160089Seric #ifdef NEWDB 233260207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 233360089Seric db_map_store(map, lhs, rhs); 233460089Seric #endif 233560089Seric #ifdef NDBM 233660207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 233760089Seric ndbm_map_store(map, lhs, rhs); 233860089Seric #endif 233960089Seric stab_map_store(map, lhs, rhs); 234060089Seric } 234160089Seric 234260089Seric /* 234360089Seric ** IMPL_MAP_OPEN -- implicit database open 234460089Seric */ 234560089Seric 234660089Seric bool 234760089Seric impl_map_open(map, mode) 234860089Seric MAP *map; 234960089Seric int mode; 235060089Seric { 235160089Seric struct stat stb; 235260089Seric 235360537Seric if (tTd(38, 2)) 235468350Seric printf("impl_map_open(%s, %s, %d)\n", 235568350Seric map->map_mname, map->map_file, mode); 235660089Seric 235760089Seric if (stat(map->map_file, &stb) < 0) 235856822Seric { 235960089Seric /* no alias file at all */ 236064718Seric if (tTd(38, 3)) 236164718Seric printf("no map file\n"); 236260089Seric return FALSE; 236356822Seric } 236456822Seric 236560089Seric #ifdef NEWDB 236660207Seric map->map_mflags |= MF_IMPL_HASH; 236760089Seric if (hash_map_open(map, mode)) 236856822Seric { 236964250Seric #if defined(NDBM) && defined(NIS) 237069651Seric if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 237160207Seric #endif 237260207Seric return TRUE; 237360089Seric } 237460207Seric else 237560207Seric map->map_mflags &= ~MF_IMPL_HASH; 237660089Seric #endif 237760089Seric #ifdef NDBM 237860207Seric map->map_mflags |= MF_IMPL_NDBM; 237960089Seric if (ndbm_map_open(map, mode)) 238060089Seric { 238160089Seric return TRUE; 238260089Seric } 238360207Seric else 238460207Seric map->map_mflags &= ~MF_IMPL_NDBM; 238560089Seric #endif 238656822Seric 238764650Seric #if defined(NEWDB) || defined(NDBM) 238860089Seric if (Verbose) 238960089Seric message("WARNING: cannot open alias database %s", map->map_file); 239064964Seric #else 239164964Seric if (mode != O_RDONLY) 239264964Seric usrerr("Cannot rebuild aliases: no database format defined"); 239360207Seric #endif 239460089Seric 239560207Seric return stab_map_open(map, mode); 239656822Seric } 239760089Seric 239860207Seric 239960089Seric /* 240060207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 240160089Seric */ 240260089Seric 240360089Seric void 240460207Seric impl_map_close(map) 240560089Seric MAP *map; 240660089Seric { 240768350Seric if (tTd(38, 20)) 240868350Seric printf("impl_map_close(%s, %s, %x)\n", 240968350Seric map->map_mname, map->map_file, map->map_mflags); 241060089Seric #ifdef NEWDB 241160207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 241260089Seric { 241360207Seric db_map_close(map); 241460207Seric map->map_mflags &= ~MF_IMPL_HASH; 241560089Seric } 241660089Seric #endif 241760089Seric 241860089Seric #ifdef NDBM 241960207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 242060089Seric { 242160207Seric ndbm_map_close(map); 242260207Seric map->map_mflags &= ~MF_IMPL_NDBM; 242360089Seric } 242460089Seric #endif 242560089Seric } 242660207Seric /* 242768350Seric ** User map class. 242868350Seric ** 242968350Seric ** Provides access to the system password file. 243068350Seric */ 243168350Seric 243268350Seric /* 243368350Seric ** USER_MAP_OPEN -- open user map 243468350Seric ** 243568350Seric ** Really just binds field names to field numbers. 243668350Seric */ 243768350Seric 243868350Seric bool 243968350Seric user_map_open(map, mode) 244068350Seric MAP *map; 244168350Seric int mode; 244268350Seric { 244368350Seric if (tTd(38, 2)) 244468350Seric printf("user_map_open(%s)\n", map->map_mname); 244568350Seric 244668350Seric if (mode != O_RDONLY) 244768350Seric { 244868350Seric /* issue a pseudo-error message */ 244968350Seric #ifdef ENOSYS 245068350Seric errno = ENOSYS; 245168350Seric #else 245268350Seric # ifdef EFTYPE 245368350Seric errno = EFTYPE; 245468350Seric # else 245568350Seric errno = ENXIO; 245668350Seric # endif 245768350Seric #endif 245868350Seric return FALSE; 245968350Seric } 246068350Seric if (map->map_valcolnm == NULL) 246168350Seric /* nothing */ ; 246268350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 246368350Seric map->map_valcolno = 1; 246468350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 246568350Seric map->map_valcolno = 2; 246668350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 246768350Seric map->map_valcolno = 3; 246868350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 246968350Seric map->map_valcolno = 4; 247068350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 247168350Seric map->map_valcolno = 5; 247268350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 247368350Seric map->map_valcolno = 6; 247468350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 247568350Seric map->map_valcolno = 7; 247668350Seric else 247768350Seric { 247868350Seric syserr("User map %s: unknown column name %s", 247968350Seric map->map_mname, map->map_valcolnm); 248068350Seric return FALSE; 248168350Seric } 248268350Seric return TRUE; 248368350Seric } 248468350Seric 248568350Seric 248668350Seric /* 248768350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 248868350Seric */ 248968350Seric 249068350Seric char * 249168350Seric user_map_lookup(map, key, av, statp) 249268350Seric MAP *map; 249368350Seric char *key; 249468350Seric char **av; 249568350Seric int *statp; 249668350Seric { 249768350Seric struct passwd *pw; 249868350Seric 249968350Seric if (tTd(38, 20)) 250068350Seric printf("user_map_lookup(%s, %s)\n", 250168350Seric map->map_mname, key); 250268350Seric 250368693Seric pw = sm_getpwnam(key); 250468350Seric if (pw == NULL) 250568350Seric return NULL; 250668350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 250768350Seric return map_rewrite(map, key, strlen(key), NULL); 250868350Seric else 250968350Seric { 251068433Seric char *rwval = NULL; 251168350Seric char buf[30]; 251268350Seric 251368350Seric switch (map->map_valcolno) 251468350Seric { 251568350Seric case 0: 251668350Seric case 1: 251768350Seric rwval = pw->pw_name; 251868350Seric break; 251968350Seric 252068350Seric case 2: 252168350Seric rwval = pw->pw_passwd; 252268350Seric break; 252368350Seric 252468350Seric case 3: 252568350Seric sprintf(buf, "%d", pw->pw_uid); 252668350Seric rwval = buf; 252768350Seric break; 252868350Seric 252968350Seric case 4: 253068350Seric sprintf(buf, "%d", pw->pw_gid); 253168350Seric rwval = buf; 253268350Seric break; 253368350Seric 253468350Seric case 5: 253568350Seric rwval = pw->pw_gecos; 253668350Seric break; 253768350Seric 253868350Seric case 6: 253968350Seric rwval = pw->pw_dir; 254068350Seric break; 254168350Seric 254268350Seric case 7: 254368350Seric rwval = pw->pw_shell; 254468350Seric break; 254568350Seric } 254668350Seric return map_rewrite(map, rwval, strlen(rwval), av); 254768350Seric } 254868350Seric } 254968350Seric /* 255068350Seric ** BESTMX -- find the best MX for a name 255168350Seric ** 255268350Seric ** This is really a hack, but I don't see any obvious way 255368350Seric ** to generalize it at the moment. 255468350Seric */ 255568350Seric 255668350Seric #if NAMED_BIND 255768350Seric 255868350Seric char * 255968350Seric bestmx_map_lookup(map, name, av, statp) 256068350Seric MAP *map; 256168350Seric char *name; 256268350Seric char **av; 256368350Seric int *statp; 256468350Seric { 256568350Seric int nmx; 256668350Seric auto int rcode; 256768350Seric char *mxhosts[MAXMXHOSTS + 1]; 256868350Seric 256968350Seric nmx = getmxrr(name, mxhosts, FALSE, &rcode); 257068350Seric if (nmx <= 0) 257168350Seric return NULL; 257268350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 257368350Seric return map_rewrite(map, name, strlen(name), NULL); 257468350Seric else 257568350Seric return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 257668350Seric } 257768350Seric 257868350Seric #endif 257968350Seric /* 258069453Seric ** Program map type. 258169453Seric ** 258269453Seric ** This provides access to arbitrary programs. It should be used 258369453Seric ** only very sparingly, since there is no way to bound the cost 258469453Seric ** of invoking an arbitrary program. 258569453Seric */ 258669453Seric 258769453Seric char * 258869453Seric prog_map_lookup(map, name, av, statp) 258969453Seric MAP *map; 259069453Seric char *name; 259169453Seric char **av; 259269453Seric int *statp; 259369453Seric { 259469453Seric int i; 259569453Seric register char *p; 259669453Seric int fd; 259769453Seric auto pid_t pid; 2598*69827Seric char *rval; 2599*69827Seric int stat; 260069453Seric char *argv[MAXPV + 1]; 260169453Seric char buf[MAXLINE]; 260269453Seric 260369453Seric if (tTd(38, 20)) 260469453Seric printf("prog_map_lookup(%s, %s) %s\n", 260569453Seric map->map_mname, name, map->map_file); 260669453Seric 260769453Seric i = 0; 260869453Seric argv[i++] = map->map_file; 260969453Seric strcpy(buf, map->map_rebuild); 261069453Seric for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 261169453Seric { 261269453Seric if (i >= MAXPV - 1) 261369453Seric break; 261469453Seric argv[i++] = p; 261569453Seric } 261669453Seric argv[i++] = name; 261769453Seric argv[i] = NULL; 261869453Seric pid = prog_open(argv, &fd, CurEnv); 261969453Seric if (pid < 0) 262069453Seric { 2621*69827Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 2622*69827Seric syserr("prog_map_lookup(%s) failed (%s) -- closing", 2623*69827Seric map->map_mname, errstring(errno)); 2624*69827Seric else if (tTd(38, 9)) 262569453Seric printf("prog_map_lookup(%s) failed (%s) -- closing", 262669453Seric map->map_mname, errstring(errno)); 262769453Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 2628*69827Seric *statp = EX_OSFILE; 262969453Seric return NULL; 263069453Seric } 263169453Seric i = read(fd, buf, sizeof buf - 1); 2632*69827Seric if (i < 0) 2633*69827Seric { 2634*69827Seric syserr("prog_map_lookup(%s): read error %s\n", 263569562Seric map->map_mname, errstring(errno)); 2636*69827Seric rval = NULL; 2637*69827Seric } 2638*69827Seric else if (i == 0 && tTd(38, 2)) 2639*69827Seric { 2640*69827Seric printf("prog_map_lookup(%s): empty answer\n", 2641*69827Seric map->map_mname); 2642*69827Seric rval = NULL; 2643*69827Seric } 264469453Seric if (i > 0) 264569453Seric { 264669453Seric buf[i] = '\0'; 264769453Seric p = strchr(buf, '\n'); 264869453Seric if (p != NULL) 264969453Seric *p = '\0'; 265069453Seric 265169453Seric /* collect the return value */ 265269453Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 265369453Seric rval = map_rewrite(map, name, strlen(name), NULL); 265469453Seric else 265569453Seric rval = map_rewrite(map, buf, strlen(buf), NULL); 265669453Seric 265769453Seric /* now flush any additional output */ 265869453Seric while ((i = read(fd, buf, sizeof buf)) > 0) 265969453Seric continue; 2660*69827Seric } 266169453Seric 2662*69827Seric /* wait for the process to terminate */ 2663*69827Seric close(fd); 2664*69827Seric stat = waitfor(pid); 266569453Seric 2666*69827Seric if (stat == -1) 2667*69827Seric { 2668*69827Seric syserr("prog_map_lookup(%s): wait error %s\n", 2669*69827Seric map->map_mname, errstring(errno)); 2670*69827Seric *statp = EX_SOFTWARE; 2671*69827Seric rval = NULL; 267269453Seric } 2673*69827Seric else if (WIFEXITED(*statp)) 2674*69827Seric { 2675*69827Seric *statp = WEXITSTATUS(*statp); 2676*69827Seric } 2677*69827Seric else 2678*69827Seric { 2679*69827Seric syserr("prog_map_lookup(%s): child died on signal %d", 2680*69827Seric map->map_mname, *statp); 2681*69827Seric *statp = EX_UNAVAILABLE; 2682*69827Seric rval = NULL; 2683*69827Seric } 2684*69827Seric return rval; 268569453Seric } 268669453Seric /* 268768350Seric ** Sequenced map type. 268868350Seric ** 268968350Seric ** Tries each map in order until something matches, much like 269068350Seric ** implicit. Stores go to the first map in the list that can 269168350Seric ** support storing. 269268350Seric ** 269368350Seric ** This is slightly unusual in that there are two interfaces. 269468350Seric ** The "sequence" interface lets you stack maps arbitrarily. 269568350Seric ** The "switch" interface builds a sequence map by looking 269668350Seric ** at a system-dependent configuration file such as 269768350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 269868350Seric ** 269968350Seric ** We don't need an explicit open, since all maps are 270068350Seric ** opened during startup, including underlying maps. 270168350Seric */ 270268350Seric 270368350Seric /* 270468350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 270568350Seric */ 270668350Seric 270768350Seric bool 270868350Seric seq_map_parse(map, ap) 270968350Seric MAP *map; 271068350Seric char *ap; 271168350Seric { 271268350Seric int maxmap; 271368350Seric 271468350Seric if (tTd(38, 2)) 271568350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 271668350Seric maxmap = 0; 271768350Seric while (*ap != '\0') 271868350Seric { 271968350Seric register char *p; 272068350Seric STAB *s; 272168350Seric 272268350Seric /* find beginning of map name */ 272368350Seric while (isascii(*ap) && isspace(*ap)) 272468350Seric ap++; 272568350Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 272668350Seric continue; 272768350Seric if (*p != '\0') 272868350Seric *p++ = '\0'; 272968350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 273068350Seric p++; 273168350Seric if (*ap == '\0') 273268350Seric { 273368350Seric ap = p; 273468350Seric continue; 273568350Seric } 273668350Seric s = stab(ap, ST_MAP, ST_FIND); 273768350Seric if (s == NULL) 273868350Seric { 273968350Seric syserr("Sequence map %s: unknown member map %s", 274068350Seric map->map_mname, ap); 274168350Seric } 274268350Seric else if (maxmap == MAXMAPSTACK) 274368350Seric { 274468350Seric syserr("Sequence map %s: too many member maps (%d max)", 274568350Seric map->map_mname, MAXMAPSTACK); 274668350Seric maxmap++; 274768350Seric } 274868350Seric else if (maxmap < MAXMAPSTACK) 274968350Seric { 275068350Seric map->map_stack[maxmap++] = &s->s_map; 275168350Seric } 275268350Seric ap = p; 275368350Seric } 275468350Seric return TRUE; 275568350Seric } 275668350Seric 275768350Seric 275868350Seric /* 275968350Seric ** SWITCH_MAP_OPEN -- open a switched map 276068350Seric ** 276168350Seric ** This looks at the system-dependent configuration and builds 276268350Seric ** a sequence map that does the same thing. 276368350Seric ** 276468350Seric ** Every system must define a switch_map_find routine in conf.c 276568350Seric ** that will return the list of service types associated with a 276668350Seric ** given service class. 276768350Seric */ 276868350Seric 276968350Seric bool 277068350Seric switch_map_open(map, mode) 277168350Seric MAP *map; 277268350Seric int mode; 277368350Seric { 277468350Seric int mapno; 277568350Seric int nmaps; 277668350Seric char *maptype[MAXMAPSTACK]; 277768350Seric 277868350Seric if (tTd(38, 2)) 277968350Seric printf("switch_map_open(%s, %s, %d)\n", 278068350Seric map->map_mname, map->map_file, mode); 278168350Seric 278268350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 278368350Seric if (tTd(38, 19)) 278468350Seric { 278568350Seric printf("\tswitch_map_find => %d\n", nmaps); 278668350Seric for (mapno = 0; mapno < nmaps; mapno++) 278768350Seric printf("\t\t%s\n", maptype[mapno]); 278868350Seric } 278968350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 279068350Seric return FALSE; 279168350Seric 279268350Seric for (mapno = 0; mapno < nmaps; mapno++) 279368350Seric { 279468350Seric register STAB *s; 279568350Seric char nbuf[MAXNAME + 1]; 279668350Seric 279768350Seric if (maptype[mapno] == NULL) 279868350Seric continue; 279968350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 280068350Seric s = stab(nbuf, ST_MAP, ST_FIND); 280168350Seric if (s == NULL) 280268350Seric { 280368350Seric syserr("Switch map %s: unknown member map %s", 280468350Seric map->map_mname, nbuf); 280568350Seric } 280668350Seric else 280768350Seric { 280868350Seric map->map_stack[mapno] = &s->s_map; 280968350Seric if (tTd(38, 4)) 281068350Seric printf("\tmap_stack[%d] = %s:%s\n", 281168350Seric mapno, s->s_map.map_class->map_cname, 281268350Seric nbuf); 281368350Seric } 281468350Seric } 281568350Seric return TRUE; 281668350Seric } 281768350Seric 281868350Seric 281968350Seric /* 282068350Seric ** SEQ_MAP_CLOSE -- close all underlying maps 282168350Seric */ 282268350Seric 282369748Seric void 282468350Seric seq_map_close(map) 282568350Seric MAP *map; 282668350Seric { 282768350Seric int mapno; 282868350Seric 282968350Seric if (tTd(38, 20)) 283068350Seric printf("seq_map_close(%s)\n", map->map_mname); 283168350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 283268350Seric { 283368350Seric MAP *mm = map->map_stack[mapno]; 283468350Seric 283568350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 283668350Seric continue; 283768350Seric mm->map_class->map_close(mm); 283868798Seric mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 283968350Seric } 284068350Seric } 284168350Seric 284268350Seric 284368350Seric /* 284468350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 284568350Seric */ 284668350Seric 284768350Seric char * 284868350Seric seq_map_lookup(map, key, args, pstat) 284968350Seric MAP *map; 285068350Seric char *key; 285168350Seric char **args; 285268350Seric int *pstat; 285368350Seric { 285468350Seric int mapno; 285568350Seric int mapbit = 0x01; 285668350Seric 285768350Seric if (tTd(38, 20)) 285868350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 285968350Seric 286068350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 286168350Seric { 286268350Seric MAP *mm = map->map_stack[mapno]; 286368350Seric int stat = 0; 286468350Seric char *rv; 286568350Seric 286668350Seric if (mm == NULL) 286768350Seric continue; 286868350Seric if (!bitset(MF_OPEN, mm->map_mflags)) 286968350Seric { 287068350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 287168350Seric { 287268350Seric *pstat = EX_UNAVAILABLE; 287368350Seric return NULL; 287468350Seric } 287568350Seric continue; 287668350Seric } 287768350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 287868350Seric if (rv != NULL) 287968350Seric return rv; 288068350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 288168350Seric return NULL; 288268350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 288368350Seric { 288468350Seric *pstat = stat; 288568350Seric return NULL; 288668350Seric } 288768350Seric } 288868350Seric return NULL; 288968350Seric } 289068350Seric 289168350Seric 289268350Seric /* 289368350Seric ** SEQ_MAP_STORE -- sequenced map store 289468350Seric */ 289568350Seric 289668350Seric void 289768350Seric seq_map_store(map, key, val) 289868350Seric MAP *map; 289968350Seric char *key; 290068350Seric char *val; 290168350Seric { 290268350Seric int mapno; 290368350Seric 290468350Seric if (tTd(38, 12)) 290568350Seric printf("seq_map_store(%s, %s, %s)\n", 290668350Seric map->map_mname, key, val); 290768350Seric 290868350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 290968350Seric { 291068350Seric MAP *mm = map->map_stack[mapno]; 291168350Seric 291268350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 291368350Seric continue; 291468350Seric 291568350Seric mm->map_class->map_store(mm, key, val); 291668350Seric return; 291768350Seric } 291868350Seric syserr("seq_map_store(%s, %s, %s): no writable map", 291968350Seric map->map_mname, key, val); 292068350Seric } 292168350Seric /* 292260207Seric ** NULL stubs 292360089Seric */ 292460089Seric 292560207Seric bool 292660207Seric null_map_open(map, mode) 292760089Seric MAP *map; 292860207Seric int mode; 292960089Seric { 293060207Seric return TRUE; 293160089Seric } 293260089Seric 293360207Seric void 293460207Seric null_map_close(map) 293560207Seric MAP *map; 293660089Seric { 293760207Seric return; 293860207Seric } 293960089Seric 294060207Seric void 294160207Seric null_map_store(map, key, val) 294260207Seric MAP *map; 294360207Seric char *key; 294460207Seric char *val; 294560089Seric { 294660207Seric return; 294760089Seric } 294868350Seric 294968350Seric 295068350Seric /* 295168350Seric ** BOGUS stubs 295268350Seric */ 295368350Seric 295468350Seric char * 295568350Seric bogus_map_lookup(map, key, args, pstat) 295668350Seric MAP *map; 295768350Seric char *key; 295868350Seric char **args; 295968350Seric int *pstat; 296068350Seric { 296168350Seric *pstat = EX_TEMPFAIL; 296268350Seric return NULL; 296368350Seric } 296468350Seric 296568350Seric MAPCLASS BogusMapClass = 296668350Seric { 296768350Seric "bogus-map", NULL, 0, 296868350Seric NULL, bogus_map_lookup, null_map_store, 296968350Seric null_map_open, null_map_close, 297068350Seric }; 2971