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*69872Seric static char sccsid[] = "@(#)map.c 8.75 (Berkeley) 06/12/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)); 6969833Seric extern bool extract_canonname __P((char *, char *, char[])); 7060089Seric /* 7160089Seric ** MAP_PARSEARGS -- parse config line arguments for database lookup 7260089Seric ** 7360089Seric ** This is a generic version of the map_parse method. 7460089Seric ** 7556822Seric ** Parameters: 7660089Seric ** map -- the map being initialized. 7760089Seric ** ap -- a pointer to the args on the config line. 7856822Seric ** 7956822Seric ** Returns: 8060089Seric ** TRUE -- if everything parsed OK. 8156822Seric ** FALSE -- otherwise. 8256822Seric ** 8356822Seric ** Side Effects: 8460089Seric ** null terminates the filename; stores it in map 8556822Seric */ 8656822Seric 8756822Seric bool 8860089Seric map_parseargs(map, ap) 8956822Seric MAP *map; 9060089Seric char *ap; 9156822Seric { 9260089Seric register char *p = ap; 9356822Seric 9463753Seric map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; 9560089Seric for (;;) 9660089Seric { 9760089Seric while (isascii(*p) && isspace(*p)) 9860089Seric p++; 9960089Seric if (*p != '-') 10060089Seric break; 10160089Seric switch (*++p) 10260089Seric { 10360089Seric case 'N': 10460207Seric map->map_mflags |= MF_INCLNULL; 10563753Seric map->map_mflags &= ~MF_TRY0NULL; 10660089Seric break; 10760089Seric 10863753Seric case 'O': 10963753Seric map->map_mflags &= ~MF_TRY1NULL; 11063753Seric break; 11163753Seric 11260089Seric case 'o': 11360207Seric map->map_mflags |= MF_OPTIONAL; 11460089Seric break; 11560089Seric 11660089Seric case 'f': 11760207Seric map->map_mflags |= MF_NOFOLDCASE; 11860089Seric break; 11960089Seric 12060089Seric case 'm': 12160207Seric map->map_mflags |= MF_MATCHONLY; 12260089Seric break; 12360089Seric 12468497Seric case 'A': 12568497Seric map->map_mflags |= MF_APPEND; 12668497Seric break; 12768497Seric 12869703Seric case 'q': 12969703Seric map->map_mflags |= MF_KEEPQUOTES; 13069703Seric break; 13169703Seric 13260089Seric case 'a': 13360089Seric map->map_app = ++p; 13460089Seric break; 13568350Seric 13668350Seric case 'k': 13768350Seric while (isascii(*++p) && isspace(*p)) 13868350Seric continue; 13968350Seric map->map_keycolnm = p; 14068350Seric break; 14168350Seric 14268350Seric case 'v': 14368350Seric while (isascii(*++p) && isspace(*p)) 14468350Seric continue; 14568350Seric map->map_valcolnm = p; 14668350Seric break; 14768350Seric 14868350Seric case 'z': 14968350Seric if (*++p != '\\') 15068350Seric map->map_coldelim = *p; 15168350Seric else 15268350Seric { 15368350Seric switch (*++p) 15468350Seric { 15568350Seric case 'n': 15668350Seric map->map_coldelim = '\n'; 15768350Seric break; 15868350Seric 15968350Seric case 't': 16068350Seric map->map_coldelim = '\t'; 16168350Seric break; 16268350Seric 16368350Seric default: 16468350Seric map->map_coldelim = '\\'; 16568350Seric } 16668350Seric } 16768350Seric break; 16868497Seric #ifdef RESERVED_FOR_SUN 16968497Seric case 'd': 17068497Seric map->map_mflags |= MF_DOMAIN_WIDE; 17168497Seric break; 17268497Seric 17368497Seric case 's': 17468497Seric /* info type */ 17568497Seric break; 17668497Seric #endif 17760089Seric } 17860089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 17960089Seric p++; 18060089Seric if (*p != '\0') 18160089Seric *p++ = '\0'; 18260089Seric } 18360089Seric if (map->map_app != NULL) 18460089Seric map->map_app = newstr(map->map_app); 18568350Seric if (map->map_keycolnm != NULL) 18668350Seric map->map_keycolnm = newstr(map->map_keycolnm); 18768350Seric if (map->map_valcolnm != NULL) 18868350Seric map->map_valcolnm = newstr(map->map_valcolnm); 18960089Seric 19060089Seric if (*p != '\0') 19160089Seric { 19260089Seric map->map_file = p; 19360089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 19460089Seric p++; 19560089Seric if (*p != '\0') 19660089Seric *p++ = '\0'; 19760089Seric map->map_file = newstr(map->map_file); 19860089Seric } 19960089Seric 20060089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 20160089Seric p++; 20260089Seric if (*p != '\0') 20360089Seric map->map_rebuild = newstr(p); 20460089Seric 20568350Seric if (map->map_file == NULL && 20668350Seric !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 20757208Seric { 20860089Seric syserr("No file name for %s map %s", 20960089Seric map->map_class->map_cname, map->map_mname); 21056822Seric return FALSE; 21157208Seric } 21260089Seric return TRUE; 21360089Seric } 21460089Seric /* 21560089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 21660089Seric ** 21760089Seric ** It also adds the map_app string. It can be used as a utility 21860089Seric ** in the map_lookup method. 21960089Seric ** 22060089Seric ** Parameters: 22160089Seric ** map -- the map that causes this. 22260089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 22360089Seric ** slen -- the length of s. 22460089Seric ** av -- arguments to interpolate into buf. 22560089Seric ** 22660089Seric ** Returns: 22767895Seric ** Pointer to rewritten result. This is static data that 22867895Seric ** should be copied if it is to be saved! 22960089Seric ** 23060089Seric ** Side Effects: 23160089Seric ** none. 23260089Seric */ 23360089Seric 23460089Seric char * 23560089Seric map_rewrite(map, s, slen, av) 23660089Seric register MAP *map; 23760089Seric register char *s; 23860089Seric int slen; 23960089Seric char **av; 24060089Seric { 24160089Seric register char *bp; 24260089Seric register char c; 24360089Seric char **avp; 24460089Seric register char *ap; 24560089Seric int i; 24660089Seric int len; 24767895Seric static int buflen = -1; 24867895Seric static char *buf = NULL; 24960089Seric 25060537Seric if (tTd(39, 1)) 25160089Seric { 25260256Seric printf("map_rewrite(%.*s), av =", slen, s); 25360256Seric if (av == NULL) 25460256Seric printf(" (nullv)"); 25560256Seric else 25660256Seric { 25760256Seric for (avp = av; *avp != NULL; avp++) 25860256Seric printf("\n\t%s", *avp); 25960256Seric } 26060256Seric printf("\n"); 26160089Seric } 26260089Seric 26360089Seric /* count expected size of output (can safely overestimate) */ 26460089Seric i = len = slen; 26560089Seric if (av != NULL) 26660089Seric { 26760089Seric bp = s; 26860089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 26960089Seric { 27060089Seric if (c != '%') 27160089Seric continue; 27260089Seric if (--i < 0) 27360089Seric break; 27460089Seric c = *bp++; 27560089Seric if (!(isascii(c) && isdigit(c))) 27660089Seric continue; 27763937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 27860089Seric continue; 27960089Seric if (*avp == NULL) 28060089Seric continue; 28160089Seric len += strlen(*avp); 28260089Seric } 28360089Seric } 28460089Seric if (map->map_app != NULL) 28560089Seric len += strlen(map->map_app); 28667895Seric if (buflen < ++len) 28760089Seric { 28860089Seric /* need to malloc additional space */ 28967895Seric buflen = len; 29067895Seric if (buf != NULL) 29167895Seric free(buf); 29267895Seric buf = xalloc(buflen); 29360089Seric } 29460089Seric 29567895Seric bp = buf; 29660089Seric if (av == NULL) 29760089Seric { 29860089Seric bcopy(s, bp, slen); 29960089Seric bp += slen; 30060089Seric } 30160089Seric else 30260089Seric { 30360089Seric while (--slen >= 0 && (c = *s++) != '\0') 30460089Seric { 30560089Seric if (c != '%') 30660089Seric { 30760089Seric pushc: 30860089Seric *bp++ = c; 30960089Seric continue; 31060089Seric } 31160089Seric if (--slen < 0 || (c = *s++) == '\0') 31260089Seric c = '%'; 31360089Seric if (c == '%') 31460089Seric goto pushc; 31560089Seric if (!(isascii(c) && isdigit(c))) 31660089Seric { 31760089Seric *bp++ = '%'; 31860089Seric goto pushc; 31960089Seric } 32063937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 32160089Seric continue; 32260089Seric if (*avp == NULL) 32360089Seric continue; 32460089Seric 32560089Seric /* transliterate argument into output string */ 32660089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 32760089Seric *bp++ = c; 32860089Seric } 32960089Seric } 33060089Seric if (map->map_app != NULL) 33160089Seric strcpy(bp, map->map_app); 33260089Seric else 33360089Seric *bp = '\0'; 33460537Seric if (tTd(39, 1)) 33567895Seric printf("map_rewrite => %s\n", buf); 33667895Seric return buf; 33760089Seric } 33860089Seric /* 33960537Seric ** INITMAPS -- initialize for aliasing 34060537Seric ** 34160537Seric ** Parameters: 34260537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 34360537Seric ** e -- current envelope. 34460537Seric ** 34560537Seric ** Returns: 34660537Seric ** none. 34760537Seric ** 34860537Seric ** Side Effects: 34960537Seric ** initializes aliases: 35060537Seric ** if NDBM: opens the database. 35160537Seric ** if ~NDBM: reads the aliases into the symbol table. 35260537Seric */ 35360537Seric 35469748Seric void 35560537Seric initmaps(rebuild, e) 35660537Seric bool rebuild; 35760537Seric register ENVELOPE *e; 35860537Seric { 35960537Seric extern void map_init(); 36060537Seric 36164671Seric #ifdef XDEBUG 36264671Seric checkfd012("entering initmaps"); 36364671Seric #endif 36460537Seric CurEnv = e; 36565085Seric if (rebuild) 36665085Seric { 36765085Seric stabapply(map_init, 1); 36865085Seric stabapply(map_init, 2); 36965085Seric } 37065085Seric else 37165085Seric { 37265085Seric stabapply(map_init, 0); 37365085Seric } 37464671Seric #ifdef XDEBUG 37564671Seric checkfd012("exiting initmaps"); 37664671Seric #endif 37760537Seric } 37860537Seric 37960537Seric void 38060537Seric map_init(s, rebuild) 38160537Seric register STAB *s; 38260537Seric int rebuild; 38360537Seric { 38460537Seric register MAP *map; 38560537Seric 38660537Seric /* has to be a map */ 38760537Seric if (s->s_type != ST_MAP) 38860537Seric return; 38960537Seric 39060537Seric map = &s->s_map; 39160537Seric if (!bitset(MF_VALID, map->map_mflags)) 39260537Seric return; 39360537Seric 39460537Seric if (tTd(38, 2)) 39568350Seric printf("map_init(%s:%s, %s, %d)\n", 39664690Seric map->map_class->map_cname == NULL ? "NULL" : 39764690Seric map->map_class->map_cname, 39868350Seric map->map_mname == NULL ? "NULL" : map->map_mname, 39965085Seric map->map_file == NULL ? "NULL" : map->map_file, 40065085Seric rebuild); 40160537Seric 40265085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && 40365085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) 40465085Seric { 40565085Seric if (tTd(38, 3)) 40665085Seric printf("\twrong pass\n"); 40765085Seric return; 40865085Seric } 40965085Seric 41060537Seric /* if already open, close it (for nested open) */ 41160537Seric if (bitset(MF_OPEN, map->map_mflags)) 41260537Seric { 41360537Seric map->map_class->map_close(map); 41460537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 41560537Seric } 41660537Seric 41765085Seric if (rebuild == 2) 41860537Seric { 41965085Seric rebuildaliases(map, FALSE); 42060537Seric } 42160537Seric else 42260537Seric { 42360537Seric if (map->map_class->map_open(map, O_RDONLY)) 42460537Seric { 42560537Seric if (tTd(38, 4)) 42668350Seric printf("\t%s:%s %s: valid\n", 42764690Seric map->map_class->map_cname == NULL ? "NULL" : 42864690Seric map->map_class->map_cname, 42968350Seric map->map_mname == NULL ? "NULL" : 43068350Seric map->map_mname, 43164690Seric map->map_file == NULL ? "NULL" : 43264690Seric map->map_file); 43360537Seric map->map_mflags |= MF_OPEN; 43460537Seric } 43568350Seric else 43668350Seric { 43768350Seric if (tTd(38, 4)) 43868350Seric printf("\t%s:%s %s: invalid: %s\n", 43968350Seric map->map_class->map_cname == NULL ? "NULL" : 44068350Seric map->map_class->map_cname, 44168350Seric map->map_mname == NULL ? "NULL" : 44268350Seric map->map_mname, 44368350Seric map->map_file == NULL ? "NULL" : 44468350Seric map->map_file, 44568350Seric errstring(errno)); 44668350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 44768350Seric { 44868350Seric extern MAPCLASS BogusMapClass; 44968350Seric 45068350Seric map->map_class = &BogusMapClass; 45168350Seric map->map_mflags |= MF_OPEN; 45268350Seric } 45368350Seric } 45460537Seric } 45560537Seric } 45660537Seric /* 45769802Seric ** GETCANONNAME -- look up name using service switch 45869802Seric ** 45969802Seric ** Parameters: 46069802Seric ** host -- the host name to look up. 46169802Seric ** hbsize -- the size of the host buffer. 46269802Seric ** trymx -- if set, try MX records. 46369802Seric ** 46469802Seric ** Returns: 46569802Seric ** TRUE -- if the host was found. 46669802Seric ** FALSE -- otherwise. 46769802Seric */ 46869802Seric 46969802Seric bool 47069802Seric getcanonname(host, hbsize, trymx) 47169802Seric char *host; 47269802Seric int hbsize; 47369802Seric bool trymx; 47469802Seric { 47569802Seric int nmaps; 47669802Seric int mapno; 47769802Seric bool found = FALSE; 47869802Seric auto int stat; 47969802Seric char *maptype[MAXMAPSTACK]; 48069802Seric short mapreturn[MAXMAPACTIONS]; 48169802Seric extern int h_errno; 48269802Seric 48369802Seric nmaps = switch_map_find("hosts", maptype, mapreturn); 48469802Seric for (mapno = 0; mapno < nmaps; mapno++) 48569802Seric { 48669802Seric int i; 48769802Seric 48869802Seric if (tTd(38, 20)) 48969802Seric printf("getcanonname(%s), trying %s\n", 49069802Seric host, maptype[mapno]); 49169802Seric if (strcmp("files", maptype[mapno]) == 0) 49269802Seric { 49369802Seric extern bool text_getcanonname __P((char *, int, int *)); 49469802Seric 49569802Seric found = text_getcanonname(host, hbsize, &stat); 49669802Seric } 49769802Seric #ifdef NIS 49869802Seric else if (strcmp("nis", maptype[mapno]) == 0) 49969802Seric { 50069802Seric extern bool nis_getcanonname __P((char *, int, int *)); 50169802Seric 50269802Seric found = nis_getcanonname(host, hbsize, &stat); 50369802Seric } 50469802Seric #endif 50569802Seric #ifdef NISPLUS 50669802Seric else if (strcmp("nisplus", maptype[mapno]) == 0) 50769802Seric { 50869802Seric extern bool nisplus_getcanonname __P((char *, int, int *)); 50969802Seric 51069802Seric found = nisplus_getcanonname(host, hbsize, &stat); 51169802Seric } 51269802Seric #endif 51369802Seric #if NAMED_BIND 51469802Seric else if (strcmp("dns", maptype[mapno]) == 0) 51569802Seric { 51669802Seric extern bool dns_getcanonname __P((char *, int, bool, int *)); 51769802Seric 51869802Seric found = dns_getcanonname(host, hbsize, trymx, &stat); 51969802Seric } 52069802Seric #endif 52169802Seric else 52269802Seric { 52369802Seric found = FALSE; 52469802Seric stat = EX_UNAVAILABLE; 52569802Seric } 52669802Seric if (found) 52769802Seric break; 52869802Seric 52969802Seric /* see if we should continue */ 53069802Seric if (stat == EX_TEMPFAIL) 53169802Seric i = MA_TRYAGAIN; 53269802Seric else if (stat == EX_NOHOST) 53369802Seric i = MA_NOTFOUND; 53469802Seric else 53569802Seric i = MA_UNAVAIL; 53669802Seric if (bitset(1 << mapno, mapreturn[i])) 53769802Seric break; 53869802Seric } 53969802Seric 54069802Seric if (found) 54169802Seric { 54269802Seric char *d; 54369802Seric 54469802Seric if (tTd(38, 20)) 54569802Seric printf("getcanonname(%s), found\n", host); 54669802Seric 54769802Seric /* 54869802Seric ** If returned name is still single token, compensate 54969802Seric ** by tagging on $m. This is because some sites set 55069802Seric ** up their DNS or NIS databases wrong. 55169802Seric */ 55269802Seric 55369802Seric if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 55469802Seric { 55569802Seric d = macvalue('m', CurEnv); 55669802Seric if (d != NULL && 55769802Seric hbsize > (int) (strlen(host) + strlen(d) + 1)) 55869802Seric { 55969802Seric if (host[strlen(host) - 1] != '.') 56069802Seric strcat(host, "."); 56169802Seric strcat(host, d); 56269802Seric } 56369802Seric else 56469802Seric { 56569802Seric return FALSE; 56669802Seric } 56769802Seric } 56869802Seric return TRUE; 56969802Seric } 57069802Seric 57169802Seric if (tTd(38, 20)) 57269802Seric printf("getcanonname(%s), failed, stat=%d\n", host, stat); 57369802Seric 57469802Seric #if NAMED_BIND 57569802Seric if (stat == EX_NOHOST) 57669802Seric h_errno = HOST_NOT_FOUND; 57769802Seric else 57869802Seric h_errno = TRY_AGAIN; 57969802Seric #endif 58069802Seric 58169802Seric return FALSE; 58269802Seric } 58369802Seric /* 58469833Seric ** EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry 58569833Seric ** 58669833Seric ** Parameters: 58769833Seric ** name -- the name against which to match. 58869833Seric ** line -- the /etc/hosts line. 58969833Seric ** cbuf -- the location to store the result. 59069833Seric ** 59169833Seric ** Returns: 59269833Seric ** TRUE -- if the line matched the desired name. 59369833Seric ** FALSE -- otherwise. 59469833Seric */ 59569833Seric 59669833Seric bool 59769833Seric extract_canonname(name, line, cbuf) 59869833Seric char *name; 59969833Seric char *line; 60069833Seric char cbuf[]; 60169833Seric { 60269833Seric int i; 60369833Seric char *p; 60469833Seric bool found = FALSE; 60569833Seric extern char *get_column(); 60669833Seric 60769833Seric cbuf[0] = '\0'; 60869833Seric if (line[0] == '#') 60969833Seric return FALSE; 61069833Seric 61169833Seric for (i = 1; !found; i++) 61269833Seric { 61369833Seric char nbuf[MAXNAME + 1]; 61469833Seric 61569833Seric p = get_column(line, i, '\0', nbuf); 61669833Seric if (p == NULL) 61769833Seric break; 61869833Seric if (cbuf[0] == '\0' || 61969833Seric (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL)) 62069833Seric strcpy(cbuf, p); 62169833Seric if (strcasecmp(name, p) == 0) 62269833Seric found = TRUE; 62369833Seric } 62469833Seric if (found && strchr(cbuf, '.') == NULL) 62569833Seric { 62669833Seric /* try to add a domain on the end of the name */ 62769833Seric char *domain = macvalue('m', CurEnv); 62869833Seric 62969833Seric if (domain != NULL && 63069833Seric strlen(domain) + strlen(cbuf) + 1 < MAXNAME) 63169833Seric { 63269833Seric p = &cbuf[strlen(cbuf)]; 63369833Seric *p++ = '.'; 63469833Seric strcpy(p, domain); 63569833Seric } 63669833Seric } 63769833Seric return found; 63869833Seric } 63969833Seric /* 64060089Seric ** NDBM modules 64160089Seric */ 64260089Seric 64360089Seric #ifdef NDBM 64460089Seric 64560089Seric /* 64660089Seric ** DBM_MAP_OPEN -- DBM-style map open 64760089Seric */ 64860089Seric 64960089Seric bool 65060089Seric ndbm_map_open(map, mode) 65160089Seric MAP *map; 65260089Seric int mode; 65360089Seric { 65464284Seric register DBM *dbm; 65564284Seric struct stat st; 65660089Seric 65760537Seric if (tTd(38, 2)) 65868350Seric printf("ndbm_map_open(%s, %s, %d)\n", 65968350Seric map->map_mname, map->map_file, mode); 66060089Seric 66160207Seric if (mode == O_RDWR) 66260207Seric mode |= O_CREAT|O_TRUNC; 66360207Seric 66460089Seric /* open the database */ 66560089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 66656822Seric if (dbm == NULL) 66756822Seric { 66864718Seric if (aliaswait(map, ".pag", FALSE)) 66964718Seric return TRUE; 67060207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 67156836Seric syserr("Cannot open DBM database %s", map->map_file); 67256822Seric return FALSE; 67356822Seric } 67460089Seric map->map_db1 = (void *) dbm; 67564964Seric if (mode == O_RDONLY) 67664964Seric { 67764964Seric if (bitset(MF_ALIAS, map->map_mflags) && 67864964Seric !aliaswait(map, ".pag", TRUE)) 67964718Seric return FALSE; 68064964Seric } 68164964Seric else 68264964Seric { 68364964Seric int fd; 68464964Seric 68564964Seric /* exclusive lock for duration of rebuild */ 68664964Seric fd = dbm_dirfno((DBM *) map->map_db1); 68764964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 68864964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 68964964Seric map->map_mflags |= MF_LOCKED; 69064964Seric } 69164718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 69264284Seric map->map_mtime = st.st_mtime; 69356822Seric return TRUE; 69456822Seric } 69560089Seric 69660089Seric 69760089Seric /* 69856822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 69956822Seric */ 70056822Seric 70156822Seric char * 70260089Seric ndbm_map_lookup(map, name, av, statp) 70356822Seric MAP *map; 70460089Seric char *name; 70556822Seric char **av; 70659084Seric int *statp; 70756822Seric { 70856822Seric datum key, val; 70964373Seric int fd; 71060089Seric char keybuf[MAXNAME + 1]; 71156822Seric 71260537Seric if (tTd(38, 20)) 71368350Seric printf("ndbm_map_lookup(%s, %s)\n", 71468350Seric map->map_mname, name); 71560089Seric 71660089Seric key.dptr = name; 71760089Seric key.dsize = strlen(name); 71860207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 71957014Seric { 72060089Seric if (key.dsize > sizeof keybuf - 1) 72160089Seric key.dsize = sizeof keybuf - 1; 72260089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 72360089Seric makelower(keybuf); 72460089Seric key.dptr = keybuf; 72557014Seric } 72664373Seric fd = dbm_dirfno((DBM *) map->map_db1); 72764388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 72864373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 72963753Seric val.dptr = NULL; 73063753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 73163753Seric { 73263753Seric val = dbm_fetch((DBM *) map->map_db1, key); 73363753Seric if (val.dptr != NULL) 73463753Seric map->map_mflags &= ~MF_TRY1NULL; 73563753Seric } 73663753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 73763753Seric { 73856822Seric key.dsize++; 73963753Seric val = dbm_fetch((DBM *) map->map_db1, key); 74063753Seric if (val.dptr != NULL) 74163753Seric map->map_mflags &= ~MF_TRY0NULL; 74263753Seric } 74364388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 74464373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 74556822Seric if (val.dptr == NULL) 74656822Seric return NULL; 74760207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 74863753Seric return map_rewrite(map, name, strlen(name), NULL); 74963753Seric else 75063753Seric return map_rewrite(map, val.dptr, val.dsize, av); 75156822Seric } 75256822Seric 75356822Seric 75456822Seric /* 75560089Seric ** DBM_MAP_STORE -- store a datum in the database 75656822Seric */ 75756822Seric 75860089Seric void 75960089Seric ndbm_map_store(map, lhs, rhs) 76060089Seric register MAP *map; 76160089Seric char *lhs; 76260089Seric char *rhs; 76360089Seric { 76460089Seric datum key; 76560089Seric datum data; 76660089Seric int stat; 76760089Seric 76860537Seric if (tTd(38, 12)) 76968350Seric printf("ndbm_map_store(%s, %s, %s)\n", 77068350Seric map->map_mname, lhs, rhs); 77160089Seric 77260089Seric key.dsize = strlen(lhs); 77360089Seric key.dptr = lhs; 77460089Seric 77560089Seric data.dsize = strlen(rhs); 77660089Seric data.dptr = rhs; 77760089Seric 77860207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 77960089Seric { 78060089Seric key.dsize++; 78160089Seric data.dsize++; 78260089Seric } 78360089Seric 78460089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 78560089Seric if (stat > 0) 78660089Seric { 78768497Seric if (!bitset(MF_APPEND, map->map_mflags)) 78868497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 78968497Seric else 79068497Seric { 79168497Seric static char *buf = NULL; 79268497Seric static int bufsiz = 0; 79368879Seric auto int xstat; 79468497Seric datum old; 79568497Seric 79668879Seric old.dptr = ndbm_map_lookup(map, key.dptr, NULL, &xstat); 79768497Seric if (old.dptr != NULL && *old.dptr != '\0') 79868497Seric { 79968497Seric old.dsize = strlen(old.dptr); 80068497Seric if (data.dsize + old.dsize + 2 > bufsiz) 80168497Seric { 80268497Seric if (buf != NULL) 80368497Seric (void) free(buf); 80468497Seric bufsiz = data.dsize + old.dsize + 2; 80568497Seric buf = xalloc(bufsiz); 80668497Seric } 80768497Seric sprintf(buf, "%s,%s", data.dptr, old.dptr); 80868497Seric data.dsize = data.dsize + old.dsize + 1; 80968497Seric data.dptr = buf; 81068497Seric if (tTd(38, 9)) 81168497Seric printf("ndbm_map_store append=%s\n", data.dptr); 81268497Seric } 81368497Seric } 81460089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 81560089Seric } 81660089Seric if (stat != 0) 81760089Seric syserr("readaliases: dbm put (%s)", lhs); 81860089Seric } 81960089Seric 82060089Seric 82160089Seric /* 82260207Seric ** NDBM_MAP_CLOSE -- close the database 82360089Seric */ 82460089Seric 82560089Seric void 82660089Seric ndbm_map_close(map) 82760089Seric register MAP *map; 82860089Seric { 82966773Seric if (tTd(38, 9)) 83068350Seric printf("ndbm_map_close(%s, %s, %x)\n", 83168350Seric map->map_mname, map->map_file, map->map_mflags); 83266773Seric 83360207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 83460089Seric { 83564250Seric #ifdef NIS 83664075Seric bool inclnull; 83760089Seric char buf[200]; 83860089Seric 83964075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 84064075Seric map->map_mflags &= ~MF_INCLNULL; 84164075Seric 84269651Seric if (strstr(map->map_file, "/yp/") != NULL) 84369651Seric { 84469651Seric (void) sprintf(buf, "%010ld", curtime()); 84569651Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 84660089Seric 84769651Seric (void) gethostname(buf, sizeof buf); 84869651Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 84969651Seric } 85064075Seric 85164075Seric if (inclnull) 85264075Seric map->map_mflags |= MF_INCLNULL; 85360089Seric #endif 85460089Seric 85560089Seric /* write out the distinguished alias */ 85660089Seric ndbm_map_store(map, "@", "@"); 85760089Seric } 85860089Seric dbm_close((DBM *) map->map_db1); 85960089Seric } 86060089Seric 86160089Seric #endif 86260089Seric /* 86360582Seric ** NEWDB (Hash and BTree) Modules 86460089Seric */ 86560089Seric 86660089Seric #ifdef NEWDB 86760089Seric 86860089Seric /* 86960582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 87060582Seric ** 87160582Seric ** These do rather bizarre locking. If you can lock on open, 87260582Seric ** do that to avoid the condition of opening a database that 87360582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 87460582Seric ** there will be a race condition. If opening for read-only, 87560582Seric ** we immediately release the lock to avoid freezing things up. 87660582Seric ** We really ought to hold the lock, but guarantee that we won't 87760582Seric ** be pokey about it. That's hard to do. 87860089Seric */ 87960089Seric 88056822Seric bool 88160089Seric bt_map_open(map, mode) 88256822Seric MAP *map; 88360089Seric int mode; 88456822Seric { 88556822Seric DB *db; 88660228Seric int i; 88760582Seric int omode; 88864373Seric int fd; 88964284Seric struct stat st; 89068528Seric char buf[MAXNAME + 1]; 89156822Seric 89260537Seric if (tTd(38, 2)) 89368350Seric printf("bt_map_open(%s, %s, %d)\n", 89468350Seric map->map_mname, map->map_file, mode); 89560089Seric 89660582Seric omode = mode; 89760582Seric if (omode == O_RDWR) 89860582Seric { 89960582Seric omode |= O_CREAT|O_TRUNC; 90065830Seric #if defined(O_EXLOCK) && HASFLOCK 90160582Seric omode |= O_EXLOCK; 90266843Seric # if !OLD_NEWDB 90360582Seric } 90460582Seric else 90560582Seric { 90660582Seric omode |= O_SHLOCK; 90760582Seric # endif 90860582Seric #endif 90960582Seric } 91060207Seric 91160228Seric (void) strcpy(buf, map->map_file); 91260228Seric i = strlen(buf); 91360228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 91460228Seric (void) strcat(buf, ".db"); 91560582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 91656822Seric if (db == NULL) 91756822Seric { 91864718Seric #ifdef MAYBENEXTRELEASE 91964718Seric if (aliaswait(map, ".db", FALSE)) 92064718Seric return TRUE; 92164718Seric #endif 92260207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 92356836Seric syserr("Cannot open BTREE database %s", map->map_file); 92456822Seric return FALSE; 92556822Seric } 92668350Seric #if !OLD_NEWDB 92764373Seric fd = db->fd(db); 92868778Seric # if defined(O_EXLOCK) && HASFLOCK 92968778Seric if (fd >= 0) 93068778Seric { 93168778Seric if (mode == O_RDONLY) 93268778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 93368778Seric else 93468778Seric map->map_mflags |= MF_LOCKED; 93568778Seric } 93668778Seric # else 93764373Seric if (mode == O_RDWR && fd >= 0) 93864388Seric { 93964388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 94064388Seric map->map_mflags |= MF_LOCKED; 94164388Seric } 94260582Seric # endif 94360582Seric #endif 94460585Seric 94560585Seric /* try to make sure that at least the database header is on disk */ 94660585Seric if (mode == O_RDWR) 94766843Seric #if OLD_NEWDB 94864373Seric (void) db->sync(db); 94964373Seric #else 95060585Seric (void) db->sync(db, 0); 95160585Seric 95264373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 95364284Seric map->map_mtime = st.st_mtime; 95464284Seric #endif 95564284Seric 95660089Seric map->map_db2 = (void *) db; 95760207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 95864718Seric if (!aliaswait(map, ".db", TRUE)) 95964718Seric return FALSE; 96056822Seric return TRUE; 96156822Seric } 96256822Seric 96356822Seric 96456822Seric /* 96556822Seric ** HASH_MAP_INIT -- HASH-style map initialization 96656822Seric */ 96756822Seric 96856822Seric bool 96960089Seric hash_map_open(map, mode) 97056822Seric MAP *map; 97160089Seric int mode; 97256822Seric { 97356822Seric DB *db; 97460228Seric int i; 97560582Seric int omode; 97664373Seric int fd; 97764284Seric struct stat st; 97868528Seric char buf[MAXNAME + 1]; 97956822Seric 98060537Seric if (tTd(38, 2)) 98168350Seric printf("hash_map_open(%s, %s, %d)\n", 98268350Seric map->map_mname, map->map_file, mode); 98360089Seric 98460582Seric omode = mode; 98560582Seric if (omode == O_RDWR) 98660582Seric { 98760582Seric omode |= O_CREAT|O_TRUNC; 98865830Seric #if defined(O_EXLOCK) && HASFLOCK 98960582Seric omode |= O_EXLOCK; 99066843Seric # if !OLD_NEWDB 99160582Seric } 99260582Seric else 99360582Seric { 99460582Seric omode |= O_SHLOCK; 99560582Seric # endif 99660582Seric #endif 99760582Seric } 99860207Seric 99960228Seric (void) strcpy(buf, map->map_file); 100060228Seric i = strlen(buf); 100160228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 100260228Seric (void) strcat(buf, ".db"); 100360582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 100456822Seric if (db == NULL) 100556822Seric { 100664718Seric #ifdef MAYBENEXTRELEASE 100764718Seric if (aliaswait(map, ".db", FALSE)) 100864718Seric return TRUE; 100964718Seric #endif 101060207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 101156836Seric syserr("Cannot open HASH database %s", map->map_file); 101256822Seric return FALSE; 101356822Seric } 101468350Seric #if !OLD_NEWDB 101564373Seric fd = db->fd(db); 101668778Seric # if defined(O_EXLOCK) && HASFLOCK 101768778Seric if (fd >= 0) 101868778Seric { 101968778Seric if (mode == O_RDONLY) 102068778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 102168778Seric else 102268778Seric map->map_mflags |= MF_LOCKED; 102368778Seric } 102468778Seric # else 102564373Seric if (mode == O_RDWR && fd >= 0) 102664388Seric { 102764388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 102864388Seric map->map_mflags |= MF_LOCKED; 102964388Seric } 103060582Seric # endif 103160582Seric #endif 103260585Seric 103360585Seric /* try to make sure that at least the database header is on disk */ 103460585Seric if (mode == O_RDWR) 103566843Seric #if OLD_NEWDB 103664373Seric (void) db->sync(db); 103764373Seric #else 103860585Seric (void) db->sync(db, 0); 103960585Seric 104064373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 104164284Seric map->map_mtime = st.st_mtime; 104264284Seric #endif 104364284Seric 104460089Seric map->map_db2 = (void *) db; 104560207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 104664718Seric if (!aliaswait(map, ".db", TRUE)) 104764718Seric return FALSE; 104856822Seric return TRUE; 104956822Seric } 105056822Seric 105156822Seric 105256822Seric /* 105356822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 105456822Seric */ 105556822Seric 105656822Seric char * 105760089Seric db_map_lookup(map, name, av, statp) 105856822Seric MAP *map; 105960089Seric char *name; 106056822Seric char **av; 106159084Seric int *statp; 106256822Seric { 106356822Seric DBT key, val; 106460422Seric register DB *db = (DB *) map->map_db2; 106560422Seric int st; 106660422Seric int saveerrno; 106764373Seric int fd; 106860089Seric char keybuf[MAXNAME + 1]; 106956822Seric 107060537Seric if (tTd(38, 20)) 107168350Seric printf("db_map_lookup(%s, %s)\n", 107268350Seric map->map_mname, name); 107360089Seric 107460089Seric key.size = strlen(name); 107560089Seric if (key.size > sizeof keybuf - 1) 107660089Seric key.size = sizeof keybuf - 1; 107760089Seric key.data = keybuf; 107860089Seric bcopy(name, keybuf, key.size + 1); 107960207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 108060089Seric makelower(keybuf); 108166843Seric #if !OLD_NEWDB 108264388Seric fd = db->fd(db); 108364388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 108464388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 108560422Seric #endif 108663753Seric st = 1; 108763753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 108863753Seric { 108963753Seric st = db->get(db, &key, &val, 0); 109063753Seric if (st == 0) 109163753Seric map->map_mflags &= ~MF_TRY1NULL; 109263753Seric } 109363753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 109463753Seric { 109563753Seric key.size++; 109663753Seric st = db->get(db, &key, &val, 0); 109763753Seric if (st == 0) 109863753Seric map->map_mflags &= ~MF_TRY0NULL; 109963753Seric } 110060422Seric saveerrno = errno; 110166843Seric #if !OLD_NEWDB 110264388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 110364373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 110460422Seric #endif 110560422Seric if (st != 0) 110660422Seric { 110760422Seric errno = saveerrno; 110860422Seric if (st < 0) 110960422Seric syserr("db_map_lookup: get (%s)", name); 111056822Seric return NULL; 111160422Seric } 111260207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 111363753Seric return map_rewrite(map, name, strlen(name), NULL); 111463753Seric else 111563753Seric return map_rewrite(map, val.data, val.size, av); 111656822Seric } 111756822Seric 111860089Seric 111960089Seric /* 112060089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 112156822Seric */ 112256822Seric 112360089Seric void 112460089Seric db_map_store(map, lhs, rhs) 112560089Seric register MAP *map; 112660089Seric char *lhs; 112760089Seric char *rhs; 112856822Seric { 112960089Seric int stat; 113060089Seric DBT key; 113160089Seric DBT data; 113260089Seric register DB *db = map->map_db2; 113356822Seric 113460537Seric if (tTd(38, 20)) 113568350Seric printf("db_map_store(%s, %s, %s)\n", 113668350Seric map->map_mname, lhs, rhs); 113760089Seric 113860089Seric key.size = strlen(lhs); 113960089Seric key.data = lhs; 114060089Seric 114160089Seric data.size = strlen(rhs); 114260089Seric data.data = rhs; 114360089Seric 114460207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 114556822Seric { 114660089Seric key.size++; 114760089Seric data.size++; 114860089Seric } 114956836Seric 115060089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 115160089Seric if (stat > 0) 115260089Seric { 115368497Seric if (!bitset(MF_APPEND, map->map_mflags)) 115468497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 115568497Seric else 115668497Seric { 115768497Seric static char *buf = NULL; 115868497Seric static int bufsiz = 0; 115968497Seric DBT old; 116068497Seric 116168497Seric old.data = db_map_lookup(map, key.data, NULL, &stat); 116268497Seric if (old.data != NULL) 116368497Seric { 116468497Seric old.size = strlen(old.data); 116568497Seric if (data.size + old.size + 2 > bufsiz) 116668497Seric { 116768497Seric if (buf != NULL) 116868497Seric (void) free(buf); 116968497Seric bufsiz = data.size + old.size + 2; 117068497Seric buf = xalloc(bufsiz); 117168497Seric } 117268497Seric sprintf(buf, "%s,%s", data.data, old.data); 117368497Seric data.size = data.size + old.size + 1; 117468497Seric data.data = buf; 117568497Seric if (tTd(38, 9)) 117668497Seric printf("db_map_store append=%s\n", data.data); 117768497Seric } 117868497Seric } 117960089Seric stat = db->put(db, &key, &data, 0); 118060089Seric } 118160089Seric if (stat != 0) 118260089Seric syserr("readaliases: db put (%s)", lhs); 118360089Seric } 118456836Seric 118556847Seric 118660089Seric /* 118760089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 118860089Seric */ 118960089Seric 119060089Seric void 119160089Seric db_map_close(map) 119260089Seric MAP *map; 119360089Seric { 119460089Seric register DB *db = map->map_db2; 119560089Seric 119660537Seric if (tTd(38, 9)) 119768350Seric printf("db_map_close(%s, %s, %x)\n", 119868350Seric map->map_mname, map->map_file, map->map_mflags); 119960089Seric 120060207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 120158804Seric { 120260089Seric /* write out the distinguished alias */ 120360089Seric db_map_store(map, "@", "@"); 120458804Seric } 120558963Seric 120660089Seric if (db->close(db) != 0) 120760089Seric syserr("readaliases: db close failure"); 120856822Seric } 120957208Seric 121060089Seric #endif 121160089Seric /* 121260089Seric ** NIS Modules 121360089Seric */ 121460089Seric 121560089Seric # ifdef NIS 121660089Seric 121764369Seric # ifndef YPERR_BUSY 121864369Seric # define YPERR_BUSY 16 121964369Seric # endif 122064369Seric 122157208Seric /* 122260089Seric ** NIS_MAP_OPEN -- open DBM map 122357208Seric */ 122457208Seric 122557208Seric bool 122660089Seric nis_map_open(map, mode) 122757208Seric MAP *map; 122860089Seric int mode; 122957208Seric { 123057216Seric int yperr; 123160215Seric register char *p; 123260215Seric auto char *vp; 123360215Seric auto int vsize; 123457216Seric 123560537Seric if (tTd(38, 2)) 123668350Seric printf("nis_map_open(%s, %s)\n", 123768350Seric map->map_mname, map->map_file); 123860089Seric 123960207Seric if (mode != O_RDONLY) 124060207Seric { 124164650Seric /* issue a pseudo-error message */ 124264650Seric #ifdef ENOSYS 124364650Seric errno = ENOSYS; 124464650Seric #else 124564650Seric # ifdef EFTYPE 124664650Seric errno = EFTYPE; 124764650Seric # else 124864650Seric errno = ENXIO; 124964650Seric # endif 125064650Seric #endif 125160207Seric return FALSE; 125260207Seric } 125360207Seric 125460089Seric p = strchr(map->map_file, '@'); 125560089Seric if (p != NULL) 125660089Seric { 125760089Seric *p++ = '\0'; 125860089Seric if (*p != '\0') 125960089Seric map->map_domain = p; 126060089Seric } 126160215Seric 126260089Seric if (*map->map_file == '\0') 126360089Seric map->map_file = "mail.aliases"; 126460089Seric 126566157Seric if (map->map_domain == NULL) 126666157Seric { 126766157Seric yperr = yp_get_default_domain(&map->map_domain); 126866157Seric if (yperr != 0) 126966157Seric { 127066744Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 127168350Seric syserr("421 NIS map %s specified, but NIS not running\n", 127266744Seric map->map_file); 127366157Seric return FALSE; 127466157Seric } 127566157Seric } 127666157Seric 127760215Seric /* check to see if this map actually exists */ 127860089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 127960089Seric &vp, &vsize); 128060537Seric if (tTd(38, 10)) 128160089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 128260089Seric map->map_domain, map->map_file, yperr_string(yperr)); 128360089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 128468350Seric { 128568350Seric if (!bitset(MF_ALIAS, map->map_mflags) || 128668350Seric aliaswait(map, NULL, TRUE)) 128768350Seric return TRUE; 128868350Seric } 128960215Seric 129060215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 129168735Seric { 129268735Seric syserr("421 Cannot bind to map %s in domain %s: %s", 129368735Seric map->map_file, map->map_domain, yperr_string(yperr)); 129468735Seric } 129560215Seric 129660089Seric return FALSE; 129760089Seric } 129860089Seric 129960089Seric 130060089Seric /* 130157208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 130257208Seric */ 130357208Seric 130457208Seric char * 130560089Seric nis_map_lookup(map, name, av, statp) 130657208Seric MAP *map; 130760089Seric char *name; 130857208Seric char **av; 130959084Seric int *statp; 131057208Seric { 131157208Seric char *vp; 131257642Seric auto int vsize; 131359274Seric int buflen; 131460215Seric int yperr; 131560089Seric char keybuf[MAXNAME + 1]; 131657208Seric 131760537Seric if (tTd(38, 20)) 131868350Seric printf("nis_map_lookup(%s, %s)\n", 131968350Seric map->map_mname, name); 132060089Seric 132160089Seric buflen = strlen(name); 132260089Seric if (buflen > sizeof keybuf - 1) 132360089Seric buflen = sizeof keybuf - 1; 132460089Seric bcopy(name, keybuf, buflen + 1); 132560207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 132660089Seric makelower(keybuf); 132763753Seric yperr = YPERR_KEY; 132863753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 132963753Seric { 133063753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 133163753Seric &vp, &vsize); 133263753Seric if (yperr == 0) 133363753Seric map->map_mflags &= ~MF_TRY1NULL; 133463753Seric } 133563753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 133663753Seric { 133759274Seric buflen++; 133863753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 133963753Seric &vp, &vsize); 134063753Seric if (yperr == 0) 134163753Seric map->map_mflags &= ~MF_TRY0NULL; 134263753Seric } 134360089Seric if (yperr != 0) 134460089Seric { 134560089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 134660215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 134757208Seric return NULL; 134860089Seric } 134960207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 135063753Seric return map_rewrite(map, name, strlen(name), NULL); 135163753Seric else 135263753Seric return map_rewrite(map, vp, vsize, av); 135357208Seric } 135457208Seric 135569401Seric 135669401Seric /* 135769401Seric ** NIS_GETCANONNAME -- look up canonical name in NIS 135869401Seric */ 135969401Seric 136069401Seric bool 136169401Seric nis_getcanonname(name, hbsize, statp) 136269401Seric char *name; 136369401Seric int hbsize; 136469401Seric int *statp; 136569401Seric { 136669401Seric char *vp; 136769401Seric auto int vsize; 136869401Seric int keylen; 136969401Seric int yperr; 137069401Seric static bool try0null = TRUE; 137169401Seric static bool try1null = TRUE; 137269401Seric static char *yp_domain = NULL; 137369748Seric char *domain; 137469401Seric char host_record[MAXLINE]; 137569833Seric char cbuf[MAXNAME]; 137669780Seric char nbuf[MAXNAME + 1]; 137769401Seric extern char *get_column(); 137869401Seric 137969401Seric if (tTd(38, 20)) 138069401Seric printf("nis_getcanonname(%s)\n", name); 138169401Seric 138269780Seric if (strlen(name) >= sizeof nbuf) 138369780Seric { 138469780Seric *statp = EX_UNAVAILABLE; 138569780Seric return FALSE; 138669780Seric } 138769780Seric (void) strcpy(nbuf, name); 138869780Seric shorten_hostname(nbuf); 138969401Seric 139069401Seric /* we only accept single token search key */ 139169780Seric if (strchr(nbuf, '.')) 139269401Seric { 139369401Seric *statp = EX_NOHOST; 139469401Seric return FALSE; 139569401Seric } 139669401Seric 139769780Seric keylen = strlen(nbuf); 139869401Seric 139969401Seric if (yp_domain == NULL) 140069401Seric yp_get_default_domain(&yp_domain); 140169780Seric makelower(nbuf); 140269401Seric yperr = YPERR_KEY; 140369401Seric if (try0null) 140469401Seric { 140569780Seric yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 140669401Seric &vp, &vsize); 140769401Seric if (yperr == 0) 140869401Seric try1null = FALSE; 140969401Seric } 141069401Seric if (yperr == YPERR_KEY && try1null) 141169401Seric { 141269401Seric keylen++; 141369780Seric yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 141469401Seric &vp, &vsize); 141569401Seric if (yperr == 0) 141669401Seric try0null = FALSE; 141769401Seric } 141869401Seric if (yperr != 0) 141969401Seric { 142069401Seric if (yperr == YPERR_KEY) 142169401Seric *statp = EX_NOHOST; 142269401Seric else if (yperr == YPERR_BUSY) 142369401Seric *statp = EX_TEMPFAIL; 142469401Seric else 142569401Seric *statp = EX_UNAVAILABLE; 142669401Seric return FALSE; 142769401Seric } 142869401Seric strncpy(host_record, vp, vsize); 142969401Seric host_record[vsize] = '\0'; 143069663Seric if (tTd(38, 44)) 143169663Seric printf("got record `%s'\n", host_record); 143269833Seric if (!extract_canonname(nbuf, host_record, cbuf)) 143369401Seric { 143469401Seric /* this should not happen, but.... */ 143569401Seric *statp = EX_NOHOST; 143669401Seric return FALSE; 143769401Seric } 143869833Seric if (hbsize < strlen(cbuf)) 143969401Seric { 144069833Seric *statp = EX_UNAVAILABLE; 144169833Seric return FALSE; 144269703Seric } 144369833Seric strcpy(name, cbuf); 144469833Seric *statp = EX_OK; 144569833Seric return TRUE; 144669401Seric } 144769401Seric 144868350Seric #endif 144968350Seric /* 145068350Seric ** NISPLUS Modules 145168350Seric ** 145268350Seric ** This code donated by Sun Microsystems. 145368350Seric */ 145467848Seric 145568350Seric #ifdef NISPLUS 145668350Seric 145768350Seric #undef NIS /* symbol conflict in nis.h */ 145868350Seric #include <rpcsvc/nis.h> 145968350Seric #include <rpcsvc/nislib.h> 146068350Seric 146168350Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 146268350Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 146368350Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 146468350Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 146568350Seric 146667848Seric /* 146768350Seric ** NISPLUS_MAP_OPEN -- open nisplus table 146867848Seric */ 146967848Seric 147068350Seric bool 147168350Seric nisplus_map_open(map, mode) 147267848Seric MAP *map; 147368350Seric int mode; 147467848Seric { 147568350Seric register char *p; 147668350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 147768350Seric nis_result *res = NULL; 147868350Seric u_int objs_len; 147968350Seric nis_object *obj_ptr; 148068350Seric int retry_cnt, max_col, i; 148168350Seric 148268350Seric if (tTd(38, 2)) 148368350Seric printf("nisplus_map_open(%s, %s, %d)\n", 148468350Seric map->map_mname, map->map_file, mode); 148568350Seric 148668350Seric if (mode != O_RDONLY) 148768350Seric { 148868350Seric errno = ENODEV; 148968350Seric return FALSE; 149068350Seric } 149168350Seric 149268350Seric if (*map->map_file == '\0') 149368350Seric map->map_file = "mail_aliases.org_dir"; 149468350Seric 149568350Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 149668350Seric { 149768350Seric /* set default NISPLUS Domain to $m */ 149868350Seric extern char *nisplus_default_domain(); 149968350Seric 150068350Seric map->map_domain = newstr(nisplus_default_domain()); 150168350Seric if (tTd(38, 2)) 150268350Seric printf("nisplus_map_open(%s): using domain %s\n", 150368350Seric map->map_file, map->map_domain); 150468350Seric } 150568350Seric if (!PARTIAL_NAME(map->map_file)) 150668350Seric map->map_domain = newstr(""); 150768350Seric 150868350Seric /* check to see if this map actually exists */ 150968350Seric if (PARTIAL_NAME(map->map_file)) 151068350Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 151168350Seric else 151268350Seric strcpy(qbuf, map->map_file); 151368350Seric 151468350Seric retry_cnt = 0; 151568350Seric while (res == NULL || res->status != NIS_SUCCESS) 151668350Seric { 151768350Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 151868350Seric switch (res->status) 151968350Seric { 152068350Seric case NIS_SUCCESS: 152168350Seric case NIS_TRYAGAIN: 152268350Seric case NIS_RPCERROR: 152368350Seric case NIS_NAMEUNREACHABLE: 152468350Seric break; 152568350Seric 152668350Seric default: /* all other nisplus errors */ 152768350Seric #if 0 152868350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 152968350Seric syserr("421 Cannot find table %s.%s: %s", 153068350Seric map->map_file, map->map_domain, 153168350Seric nis_sperrno(res->status)); 153268350Seric #endif 153368350Seric errno = EBADR; 153468350Seric return FALSE; 153568350Seric } 153668350Seric sleep(2); /* try not to overwhelm hosed server */ 153768350Seric if (retry_cnt++ > 4) 153868350Seric { 153968350Seric errno = EBADR; 154068350Seric return FALSE; 154168350Seric } 154268350Seric } 154368350Seric 154468350Seric if (NIS_RES_NUMOBJ(res) != 1 || 154568350Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 154668350Seric { 154768350Seric if (tTd(38, 10)) 154868350Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 154968350Seric #if 0 155068350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 155168350Seric syserr("421 %s.%s: %s is not a table", 155268350Seric map->map_file, map->map_domain, 155368350Seric nis_sperrno(res->status)); 155468350Seric #endif 155568350Seric errno = EBADR; 155668350Seric return FALSE; 155768350Seric } 155868350Seric /* default key column is column 0 */ 155968350Seric if (map->map_keycolnm == NULL) 156068350Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 156168350Seric 156268350Seric max_col = COL_MAX(res); 156368350Seric 156468350Seric /* verify the key column exist */ 156568350Seric for (i=0; i< max_col; i++) 156668350Seric { 156768350Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 156868350Seric break; 156968350Seric } 157068350Seric if (i == max_col) 157168350Seric { 157268350Seric if (tTd(38, 2)) 157368350Seric printf("nisplus_map_open(%s): can not find key column %s\n", 157468350Seric map->map_file, map->map_keycolnm); 157568350Seric errno = EBADR; 157668350Seric return FALSE; 157768350Seric } 157868350Seric 157968350Seric /* default value column is the last column */ 158068350Seric if (map->map_valcolnm == NULL) 158168350Seric { 158268350Seric map->map_valcolno = max_col - 1; 158368350Seric return TRUE; 158468350Seric } 158568350Seric 158668350Seric for (i=0; i< max_col; i++) 158768350Seric { 158868350Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 158968350Seric { 159068350Seric map->map_valcolno = i; 159168350Seric return TRUE; 159268350Seric } 159368350Seric } 159468350Seric 159568350Seric if (tTd(38, 2)) 159668350Seric printf("nisplus_map_open(%s): can not find column %s\n", 159768350Seric map->map_file, map->map_keycolnm); 159868350Seric errno = EBADR; 159968350Seric return FALSE; 160067848Seric } 160167848Seric 160267848Seric 160367848Seric /* 160468350Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 160567848Seric */ 160667848Seric 160768350Seric char * 160868350Seric nisplus_map_lookup(map, name, av, statp) 160967848Seric MAP *map; 161068350Seric char *name; 161168350Seric char **av; 161268350Seric int *statp; 161367848Seric { 161468350Seric char *vp; 161568350Seric auto int vsize; 161668350Seric int buflen; 161768350Seric char search_key[MAXNAME + 1]; 161868350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 161968350Seric nis_result *result; 162068350Seric 162168350Seric if (tTd(38, 20)) 162268350Seric printf("nisplus_map_lookup(%s, %s)\n", 162368350Seric map->map_mname, name); 162468350Seric 162568350Seric if (!bitset(MF_OPEN, map->map_mflags)) 162668350Seric { 162768350Seric if (nisplus_map_open(map, O_RDONLY)) 162868350Seric map->map_mflags |= MF_OPEN; 162968350Seric else 163068350Seric { 163168350Seric *statp = EX_UNAVAILABLE; 163268350Seric return NULL; 163368350Seric } 163468350Seric } 163568350Seric 163668350Seric buflen = strlen(name); 163768350Seric if (buflen > sizeof search_key - 1) 163868350Seric buflen = sizeof search_key - 1; 163968350Seric bcopy(name, search_key, buflen + 1); 164068350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 164168350Seric makelower(search_key); 164268350Seric 164368350Seric /* construct the query */ 164468350Seric if (PARTIAL_NAME(map->map_file)) 164568350Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 164668350Seric search_key, map->map_file, map->map_domain); 164768350Seric else 164868350Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 164968350Seric search_key, map->map_file); 165068350Seric 165168350Seric if (tTd(38, 20)) 165268350Seric printf("qbuf=%s\n", qbuf); 165368350Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 165468350Seric if (result->status == NIS_SUCCESS) 165568350Seric { 165668350Seric int count; 165768350Seric char *str; 165868350Seric 165968350Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 166068350Seric { 166168350Seric if (LogLevel > 10) 166268350Seric syslog(LOG_WARNING, 166368350Seric "%s:Lookup error, expected 1 entry, got (%d)", 166468350Seric map->map_file, count); 166568350Seric 166668350Seric /* ignore second entry */ 166768350Seric if (tTd(38, 20)) 166868350Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 166968350Seric name, count); 167068350Seric } 167168350Seric 167268350Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 167368350Seric /* set the length of the result */ 167468350Seric if (vp == NULL) 167568350Seric vp = ""; 167668350Seric vsize = strlen(vp); 167768350Seric if (tTd(38, 20)) 167868350Seric printf("nisplus_map_lookup(%s), found %s\n", 167968350Seric name, vp); 168068350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 168168350Seric str = map_rewrite(map, name, strlen(name), NULL); 168268350Seric else 168368350Seric str = map_rewrite(map, vp, vsize, av); 168468350Seric nis_freeresult(result); 168568350Seric #ifdef MAP_EXIT_STAT 168668350Seric *statp = EX_OK; 168768350Seric #endif 168868350Seric return str; 168968350Seric } 169068350Seric else 169168350Seric { 169268350Seric #ifdef MAP_EXIT_STAT 169368350Seric if (result->status == NIS_NOTFOUND) 169468350Seric *statp = EX_NOTFOUND; 169568350Seric else if (result->status == NIS_TRYAGAIN) 169668350Seric *statp = EX_TEMPFAIL; 169768350Seric else 169868350Seric { 169968350Seric *statp = EX_UNAVAILABLE; 170068350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 170168350Seric } 170268350Seric #else 170368350Seric if ((result->status != NIS_NOTFOUND) && 170468350Seric (result->status != NIS_TRYAGAIN)) 170568350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 170668350Seric #endif 170768350Seric } 170868350Seric if (tTd(38, 20)) 170968350Seric printf("nisplus_map_lookup(%s), failed\n", name); 171068350Seric nis_freeresult(result); 171168350Seric return NULL; 171267848Seric } 171367848Seric 171468350Seric 171569401Seric 171669401Seric /* 171769401Seric ** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 171869401Seric */ 171969401Seric 172069401Seric bool 172169401Seric nisplus_getcanonname(name, hbsize, statp) 172269401Seric char *name; 172369401Seric int hbsize; 172469401Seric int *statp; 172569401Seric { 172669401Seric char *vp; 172769401Seric auto int vsize; 172869401Seric int buflen; 172969401Seric nis_result *result; 173069401Seric char *p; 173169401Seric int len; 173269780Seric char nbuf[MAXNAME + 1]; 173369780Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 173469401Seric 173569780Seric if (strlen(name) >= sizeof nbuf) 173669780Seric { 173769780Seric *statp = EX_UNAVAILABLE; 173869780Seric return FALSE; 173969780Seric } 174069780Seric (void) strcpy(nbuf, name); 174169780Seric shorten_hostname(nbuf); 174269401Seric 174369780Seric p = strchr(nbuf, '.'); 174469401Seric if (p == NULL) 174569401Seric { 174669401Seric /* single token */ 174769780Seric sprintf(qbuf, "[name=%s],hosts.org_dir", nbuf); 174869401Seric } 174969401Seric else if (p[1] != '\0') 175069401Seric { 175169780Seric /* multi token -- take only first token in nbuf */ 175269401Seric *p = '\0'; 175369780Seric sprintf(qbuf, "[name=%s],hosts.org_dir.%s", nbuf, &p[1]); 175469401Seric } 175569401Seric else 175669401Seric { 175769401Seric *statp = EX_NOHOST; 175869401Seric return FALSE; 175969401Seric } 176069401Seric 176169401Seric if (tTd(38, 20)) 176269478Seric printf("\nnisplus_getcanoname(%s), qbuf=%s\n", 176369780Seric name, qbuf); 176469401Seric 176569780Seric result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 176669401Seric NULL, NULL); 176769401Seric 176869401Seric if (result->status == NIS_SUCCESS) 176969401Seric { 177069401Seric int count; 177169401Seric char *str; 177269401Seric char *domain; 177369401Seric 177469401Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 177569401Seric { 177669401Seric #ifdef LOG 177769401Seric if (LogLevel > 10) 177869401Seric syslog(LOG_WARNING, 177969401Seric "nisplus_getcanonname: Lookup error, expected 1 entry, got (%d)", 178069401Seric count); 178169401Seric #endif 178269401Seric 178369401Seric /* ignore second entry */ 178469401Seric if (tTd(38, 20)) 178569401Seric printf("nisplus_getcanoname(%s), got %d entries, addtional entries ignores\n", name); 178669401Seric } 178769401Seric 178869401Seric if (tTd(38, 20)) 178969401Seric printf("nisplus_getcanoname(%s), found in directory \"%s\"\n", 179069401Seric name, (NIS_RES_OBJECT(result))->zo_domain); 179169401Seric 179269401Seric 179369401Seric vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 179469401Seric vsize = strlen(vp); 179569401Seric if (tTd(38, 20)) 179669401Seric printf("nisplus_getcanonname(%s), found %s\n", 179769401Seric name, vp); 179869703Seric if (strchr(vp, '.') != NULL) 179969703Seric { 180069636Seric domain = ""; 180169703Seric } 180269703Seric else 180369703Seric { 180469703Seric domain = macvalue('m', CurEnv); 180569703Seric if (domain == NULL) 180669703Seric domain = ""; 180769703Seric } 180869636Seric if (hbsize > vsize + (int) strlen(domain) + 1) 180969401Seric { 181069636Seric if (domain[0] == '\0') 181169636Seric strcpy(name, vp); 181269636Seric else 181369636Seric sprintf(name, "%s.%s", vp, domain); 181469401Seric *statp = EX_OK; 181569401Seric } 181669401Seric else 181769401Seric *statp = EX_NOHOST; 181869401Seric nis_freeresult(result); 181969401Seric return TRUE; 182069401Seric } 182169401Seric else 182269401Seric { 182369401Seric if (result->status == NIS_NOTFOUND) 182469401Seric *statp = EX_NOHOST; 182569401Seric else if (result->status == NIS_TRYAGAIN) 182669401Seric *statp = EX_TEMPFAIL; 182769401Seric else 182869401Seric *statp = EX_UNAVAILABLE; 182969401Seric } 183069401Seric if (tTd(38, 20)) 183169401Seric printf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 183269401Seric name, result->status, *statp); 183369401Seric nis_freeresult(result); 183469401Seric return FALSE; 183569401Seric } 183669401Seric 183769401Seric 183868350Seric char * 183968350Seric nisplus_default_domain() 184068350Seric { 184168528Seric static char default_domain[MAXNAME + 1] = ""; 184268350Seric char *p; 184368350Seric 184468350Seric if (default_domain[0] != '\0') 184568350Seric return(default_domain); 184668350Seric 184768458Seric p = nis_local_directory(); 184868350Seric strcpy(default_domain, p); 184968458Seric return default_domain; 185068350Seric } 185168350Seric 185268350Seric #endif /* NISPLUS */ 185367848Seric /* 185468350Seric ** HESIOD Modules 185568350Seric */ 185668350Seric 185768350Seric #ifdef HESIOD 185868350Seric 185968350Seric #include <hesiod.h> 186068350Seric 186168350Seric char * 186268350Seric hes_map_lookup(map, name, av, statp) 186368350Seric MAP *map; 186468350Seric char *name; 186568350Seric char **av; 186668350Seric int *statp; 186768350Seric { 186868350Seric char **hp; 186968350Seric 187068350Seric if (tTd(38, 20)) 187168350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 187268350Seric 187369688Seric if (name[0] == '\\') 187469688Seric { 187569688Seric char *np; 187669688Seric int nl; 187769688Seric char nbuf[MAXNAME]; 187869688Seric 187969688Seric nl = strlen(name); 188069688Seric if (nl < sizeof nbuf - 1) 188169688Seric np = nbuf; 188269688Seric else 188369688Seric np = xalloc(strlen(name) + 2); 188469688Seric np[0] = '\\'; 188569688Seric strcpy(&np[1], name); 188669688Seric hp = hes_resolve(np, map->map_file); 188769688Seric if (np != nbuf) 188869688Seric free(np); 188969688Seric } 189069688Seric else 189169688Seric { 189269688Seric hp = hes_resolve(name, map->map_file); 189369688Seric } 189469623Seric if (hp == NULL || hp[0] == NULL) 189568350Seric return NULL; 189668350Seric 189769623Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 189869623Seric return map_rewrite(map, name, strlen(name), NULL); 189969623Seric else 190069623Seric return map_rewrite(map, hp[0], strlen(hp[0]), av); 190168350Seric } 190268350Seric 190368350Seric #endif 190468350Seric /* 190568350Seric ** NeXT NETINFO Modules 190668350Seric */ 190768350Seric 190868350Seric #ifdef NETINFO 190968350Seric 191068350Seric #define NETINFO_DEFAULT_DIR "/aliases" 191168350Seric #define NETINFO_DEFAULT_PROPERTY "members" 191268350Seric 191368350Seric 191468350Seric /* 191568350Seric ** NI_MAP_OPEN -- open NetInfo Aliases 191668350Seric */ 191768350Seric 191868350Seric bool 191968350Seric ni_map_open(map, mode) 192068350Seric MAP *map; 192168350Seric int mode; 192268350Seric { 192368350Seric char *p; 192468350Seric 192568350Seric if (tTd(38, 20)) 192668350Seric printf("ni_map_open: %s\n", map->map_file); 192768350Seric 192868350Seric if (*map->map_file == '\0') 192968350Seric map->map_file = NETINFO_DEFAULT_DIR; 193068350Seric 193168350Seric if (map->map_valcolnm == NULL) 193268350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 193368350Seric 193468350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 193568350Seric map->map_coldelim = ','; 193668350Seric 193768350Seric return TRUE; 193868350Seric } 193968350Seric 194068350Seric 194168350Seric /* 194268350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 194368350Seric */ 194468350Seric 194568350Seric char * 194668350Seric ni_map_lookup(map, name, av, statp) 194768350Seric MAP *map; 194868350Seric char *name; 194968350Seric char **av; 195068350Seric int *statp; 195168350Seric { 195268350Seric char *res; 195368350Seric char *propval; 195468350Seric extern char *ni_propval(); 195568350Seric 195668350Seric if (tTd(38, 20)) 195768350Seric printf("ni_map_lookup(%s, %s)\n", 195868350Seric map->map_mname, name); 195968350Seric 196068350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 196168350Seric map->map_valcolnm, map->map_coldelim); 196268350Seric 196368350Seric if (propval == NULL) 196468350Seric return NULL; 196568350Seric 196668350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 196768350Seric res = map_rewrite(map, name, strlen(name), NULL); 196868350Seric else 196968350Seric res = map_rewrite(map, propval, strlen(propval), av); 197068350Seric free(propval); 197168350Seric return res; 197268350Seric } 197368350Seric 197468350Seric #endif 197568350Seric /* 197668350Seric ** TEXT (unindexed text file) Modules 197768350Seric ** 197868350Seric ** This code donated by Sun Microsystems. 197968350Seric */ 198068350Seric 198168350Seric 198268350Seric /* 198368350Seric ** TEXT_MAP_OPEN -- open text table 198468350Seric */ 198568350Seric 198668350Seric bool 198768350Seric text_map_open(map, mode) 198868350Seric MAP *map; 198968350Seric int mode; 199068350Seric { 199168350Seric struct stat sbuf; 199268350Seric 199368350Seric if (tTd(38, 2)) 199468350Seric printf("text_map_open(%s, %s, %d)\n", 199568350Seric map->map_mname, map->map_file, mode); 199668350Seric 199768350Seric if (mode != O_RDONLY) 199868350Seric { 199968350Seric errno = ENODEV; 200068350Seric return FALSE; 200168350Seric } 200268350Seric 200368350Seric if (*map->map_file == '\0') 200468350Seric { 200568350Seric if (tTd(38, 2)) 200668350Seric printf("text_map_open: file name required\n"); 200768350Seric return FALSE; 200868350Seric } 200968350Seric 201068350Seric if (map->map_file[0] != '/') 201168350Seric { 201268350Seric if (tTd(38, 2)) 201368350Seric printf("text_map_open(%s): file name must be fully qualified\n", 201468350Seric map->map_file); 201568350Seric return FALSE; 201668350Seric } 201768350Seric /* check to see if this map actually accessable */ 201868350Seric if (access(map->map_file, R_OK) <0) 201968350Seric return FALSE; 202068350Seric 202168350Seric /* check to see if this map actually exist */ 202268350Seric if (stat(map->map_file, &sbuf) <0) 202368350Seric { 202468350Seric if (tTd(38, 2)) 202568350Seric printf("text_map_open(%s): can not stat %s\n", 202668350Seric map->map_file, map->map_file); 202768350Seric return FALSE; 202868350Seric } 202968350Seric 203068350Seric if (!S_ISREG(sbuf.st_mode)) 203168350Seric { 203268350Seric if (tTd(38, 2)) 203368350Seric printf("text_map_open(%s): %s is not a file\n", 203468350Seric map->map_file, map->map_file); 203568350Seric return FALSE; 203668350Seric } 203768350Seric 203868350Seric if (map->map_keycolnm == NULL) 203968350Seric map->map_keycolno = 0; 204068350Seric else 204168350Seric { 204268350Seric if (!isdigit(*map->map_keycolnm)) 204368350Seric { 204468350Seric if (tTd(38, 2)) 204568350Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 204668350Seric map->map_file, map->map_keycolnm); 204768350Seric return FALSE; 204868350Seric } 204968350Seric map->map_keycolno = atoi(map->map_keycolnm); 205068350Seric } 205168350Seric 205268350Seric if (map->map_valcolnm == NULL) 205368350Seric map->map_valcolno = 0; 205468350Seric else 205568350Seric { 205668350Seric if (!isdigit(*map->map_valcolnm)) 205768350Seric { 205868350Seric if (tTd(38, 2)) 205968350Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 206068350Seric map->map_file, map->map_valcolnm); 206168350Seric return FALSE; 206268350Seric } 206368350Seric map->map_valcolno = atoi(map->map_valcolnm); 206468350Seric } 206568350Seric 206668350Seric if (tTd(38, 2)) 206768350Seric { 206868520Seric printf("text_map_open(%s): delimiter = ", 206968520Seric map->map_file); 207068520Seric if (map->map_coldelim == '\0') 207168520Seric printf("(white space)\n"); 207268520Seric else 207368520Seric printf("%c\n", map->map_coldelim); 207468350Seric } 207568350Seric 207668350Seric return TRUE; 207768350Seric } 207868350Seric 207968350Seric 208068350Seric /* 208168350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 208268350Seric */ 208368350Seric 208468350Seric char * 208568350Seric text_map_lookup(map, name, av, statp) 208668350Seric MAP *map; 208768350Seric char *name; 208868350Seric char **av; 208968350Seric int *statp; 209068350Seric { 209168350Seric char *vp; 209268350Seric auto int vsize; 209368350Seric int buflen; 209468350Seric char search_key[MAXNAME + 1]; 209568350Seric char linebuf[MAXLINE]; 209668350Seric FILE *f; 209768528Seric char buf[MAXNAME + 1]; 209868350Seric char delim; 209968350Seric int key_idx; 210068350Seric bool found_it; 210168350Seric extern char *get_column(); 210268350Seric 210368350Seric 210468350Seric found_it = FALSE; 210568350Seric if (tTd(38, 20)) 210668350Seric printf("text_map_lookup(%s)\n", name); 210768350Seric 210868350Seric buflen = strlen(name); 210968350Seric if (buflen > sizeof search_key - 1) 211068350Seric buflen = sizeof search_key - 1; 211168350Seric bcopy(name, search_key, buflen + 1); 211268350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 211368350Seric makelower(search_key); 211468350Seric 211568350Seric f = fopen(map->map_file, "r"); 211668350Seric if (f == NULL) 211768350Seric { 211868350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 211968350Seric *statp = EX_UNAVAILABLE; 212068350Seric return NULL; 212168350Seric } 212268350Seric key_idx = map->map_keycolno; 212368350Seric delim = map->map_coldelim; 212468350Seric while (fgets(linebuf, MAXLINE, f)) 212568350Seric { 212668350Seric char *lf; 212768350Seric if (linebuf[0] == '#') 212868350Seric continue; /* skip comment line */ 212968350Seric if (lf = strchr(linebuf, '\n')) 213068350Seric *lf = '\0'; 213168350Seric if (!strcasecmp(search_key, 213268350Seric get_column(linebuf, key_idx, delim, buf))) 213368350Seric { 213468350Seric found_it = TRUE; 213568350Seric break; 213668350Seric } 213768350Seric } 213868350Seric fclose(f); 213968350Seric if (!found_it) 214068350Seric { 214168350Seric #ifdef MAP_EXIT_STAT 214268350Seric *statp = EX_NOTFOUND; 214368350Seric #endif 214468350Seric return(NULL); 214568350Seric } 214668350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 214768350Seric vsize = strlen(vp); 214868350Seric #ifdef MAP_EXIT_STAT 214968350Seric *statp = EX_OK; 215068350Seric #endif 215168350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 215268350Seric return map_rewrite(map, name, strlen(name), NULL); 215368350Seric else 215468350Seric return map_rewrite(map, vp, vsize, av); 215568350Seric } 215669401Seric 215769401Seric 215869401Seric /* 215969401Seric ** TEXT_GETCANONNAME -- look up canonical name in hosts file 216069401Seric */ 216169401Seric 216269401Seric bool 216369401Seric text_getcanonname(name, hbsize, statp) 216469401Seric char *name; 216569401Seric int hbsize; 216669401Seric int *statp; 216769401Seric { 216869401Seric int key_idx; 216969401Seric bool found; 217069401Seric FILE *f; 217169401Seric char linebuf[MAXLINE]; 217269401Seric char cbuf[MAXNAME + 1]; 217369780Seric char fbuf[MAXNAME + 1]; 217469780Seric char nbuf[MAXNAME + 1]; 217569401Seric extern char *get_column(); 217669401Seric 217769780Seric if (strlen(name) >= sizeof nbuf) 217869780Seric { 217969780Seric *statp = EX_UNAVAILABLE; 218069780Seric return FALSE; 218169780Seric } 218269780Seric (void) strcpy(nbuf, name); 218369780Seric shorten_hostname(nbuf); 218469401Seric 218569401Seric /* we only accept single token search key */ 218669780Seric if (strchr(nbuf, '.') != NULL) 218769401Seric { 218869401Seric *statp = EX_NOHOST; 218969401Seric return FALSE; 219069401Seric } 219169401Seric 219269401Seric found = FALSE; 219369401Seric 219469401Seric f = fopen(HostsFile, "r"); 219569401Seric if (f == NULL) 219669401Seric { 219769401Seric #ifdef MAP_EXIT_STAT 219869401Seric *statp = EX_UNAVAILABLE; 219969401Seric #endif 220069401Seric return FALSE; 220169401Seric } 220269401Seric while (!found && fgets(linebuf, MAXLINE, f) != NULL) 220369401Seric { 220469401Seric char *p; 220569401Seric 220669401Seric if (linebuf[0] == '#') 220769401Seric continue; 220869401Seric if ((p = strchr(linebuf, '\n')) != NULL) 220969401Seric *p = '\0'; 221069833Seric found = extract_canonname(nbuf, linebuf, cbuf); 221169401Seric } 221269401Seric fclose(f); 221369401Seric if (!found) 221469401Seric { 221569401Seric *statp = EX_NOHOST; 221669401Seric return FALSE; 221769401Seric } 221869401Seric 221969833Seric if (hbsize >= strlen(cbuf)) 222069401Seric { 222169833Seric strcpy(name, cbuf); 222269401Seric *statp = EX_OK; 222369401Seric return TRUE; 222469401Seric } 222569401Seric *statp = EX_UNAVAILABLE; 222669401Seric return FALSE; 222769401Seric } 222868350Seric /* 222960089Seric ** STAB (Symbol Table) Modules 223060089Seric */ 223160089Seric 223260089Seric 223360089Seric /* 223460207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 223560089Seric */ 223660089Seric 223760089Seric char * 223861707Seric stab_map_lookup(map, name, av, pstat) 223960089Seric register MAP *map; 224060089Seric char *name; 224161707Seric char **av; 224261707Seric int *pstat; 224360089Seric { 224460089Seric register STAB *s; 224560089Seric 224660537Seric if (tTd(38, 20)) 224768350Seric printf("stab_lookup(%s, %s)\n", 224868350Seric map->map_mname, name); 224960089Seric 225060089Seric s = stab(name, ST_ALIAS, ST_FIND); 225160089Seric if (s != NULL) 225260089Seric return (s->s_alias); 225360089Seric return (NULL); 225460089Seric } 225560089Seric 225660089Seric 225760089Seric /* 225860207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 225960089Seric */ 226060089Seric 226160089Seric void 226260089Seric stab_map_store(map, lhs, rhs) 226360089Seric register MAP *map; 226460089Seric char *lhs; 226560089Seric char *rhs; 226660089Seric { 226760089Seric register STAB *s; 226860089Seric 226960089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 227060089Seric s->s_alias = newstr(rhs); 227160089Seric } 227260089Seric 227360089Seric 227460089Seric /* 227560207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 227660207Seric ** 227760207Seric ** This is a wierd case -- it is only intended as a fallback for 227860207Seric ** aliases. For this reason, opens for write (only during a 227960207Seric ** "newaliases") always fails, and opens for read open the 228060207Seric ** actual underlying text file instead of the database. 228160089Seric */ 228260089Seric 228360089Seric bool 228460089Seric stab_map_open(map, mode) 228560089Seric register MAP *map; 228660089Seric int mode; 228760089Seric { 228863835Seric FILE *af; 228964284Seric struct stat st; 229063835Seric 229160537Seric if (tTd(38, 2)) 229268350Seric printf("stab_map_open(%s, %s)\n", 229368350Seric map->map_mname, map->map_file); 229460089Seric 229560089Seric if (mode != O_RDONLY) 229660207Seric { 229760207Seric errno = ENODEV; 229860089Seric return FALSE; 229960207Seric } 230060089Seric 230163835Seric af = fopen(map->map_file, "r"); 230263835Seric if (af == NULL) 230363835Seric return FALSE; 230468350Seric readaliases(map, af, FALSE, FALSE); 230564284Seric 230664284Seric if (fstat(fileno(af), &st) >= 0) 230764284Seric map->map_mtime = st.st_mtime; 230863835Seric fclose(af); 230963835Seric 231060089Seric return TRUE; 231160089Seric } 231260089Seric /* 231360089Seric ** Implicit Modules 231456822Seric ** 231560089Seric ** Tries several types. For back compatibility of aliases. 231656822Seric */ 231756822Seric 231860089Seric 231960089Seric /* 232060207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 232160089Seric */ 232260089Seric 232360089Seric char * 232460089Seric impl_map_lookup(map, name, av, pstat) 232560089Seric MAP *map; 232660089Seric char *name; 232756822Seric char **av; 232860089Seric int *pstat; 232956822Seric { 233060537Seric if (tTd(38, 20)) 233168350Seric printf("impl_map_lookup(%s, %s)\n", 233268350Seric map->map_mname, name); 233356822Seric 233460089Seric #ifdef NEWDB 233560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 233660089Seric return db_map_lookup(map, name, av, pstat); 233760089Seric #endif 233860089Seric #ifdef NDBM 233960207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 234060089Seric return ndbm_map_lookup(map, name, av, pstat); 234160089Seric #endif 234260089Seric return stab_map_lookup(map, name, av, pstat); 234360089Seric } 234460089Seric 234560089Seric /* 234660207Seric ** IMPL_MAP_STORE -- store in open databases 234760089Seric */ 234860089Seric 234960089Seric void 235060089Seric impl_map_store(map, lhs, rhs) 235160089Seric MAP *map; 235260089Seric char *lhs; 235360089Seric char *rhs; 235460089Seric { 235560089Seric #ifdef NEWDB 235660207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 235760089Seric db_map_store(map, lhs, rhs); 235860089Seric #endif 235960089Seric #ifdef NDBM 236060207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 236160089Seric ndbm_map_store(map, lhs, rhs); 236260089Seric #endif 236360089Seric stab_map_store(map, lhs, rhs); 236460089Seric } 236560089Seric 236660089Seric /* 236760089Seric ** IMPL_MAP_OPEN -- implicit database open 236860089Seric */ 236960089Seric 237060089Seric bool 237160089Seric impl_map_open(map, mode) 237260089Seric MAP *map; 237360089Seric int mode; 237460089Seric { 237560089Seric struct stat stb; 237660089Seric 237760537Seric if (tTd(38, 2)) 237868350Seric printf("impl_map_open(%s, %s, %d)\n", 237968350Seric map->map_mname, map->map_file, mode); 238060089Seric 238160089Seric if (stat(map->map_file, &stb) < 0) 238256822Seric { 238360089Seric /* no alias file at all */ 238464718Seric if (tTd(38, 3)) 238564718Seric printf("no map file\n"); 238660089Seric return FALSE; 238756822Seric } 238856822Seric 238960089Seric #ifdef NEWDB 239060207Seric map->map_mflags |= MF_IMPL_HASH; 239160089Seric if (hash_map_open(map, mode)) 239256822Seric { 239364250Seric #if defined(NDBM) && defined(NIS) 239469651Seric if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 239560207Seric #endif 239660207Seric return TRUE; 239760089Seric } 239860207Seric else 239960207Seric map->map_mflags &= ~MF_IMPL_HASH; 240060089Seric #endif 240160089Seric #ifdef NDBM 240260207Seric map->map_mflags |= MF_IMPL_NDBM; 240360089Seric if (ndbm_map_open(map, mode)) 240460089Seric { 240560089Seric return TRUE; 240660089Seric } 240760207Seric else 240860207Seric map->map_mflags &= ~MF_IMPL_NDBM; 240960089Seric #endif 241056822Seric 241164650Seric #if defined(NEWDB) || defined(NDBM) 241260089Seric if (Verbose) 241360089Seric message("WARNING: cannot open alias database %s", map->map_file); 241464964Seric #else 241564964Seric if (mode != O_RDONLY) 241664964Seric usrerr("Cannot rebuild aliases: no database format defined"); 241760207Seric #endif 241860089Seric 241960207Seric return stab_map_open(map, mode); 242056822Seric } 242160089Seric 242260207Seric 242360089Seric /* 242460207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 242560089Seric */ 242660089Seric 242760089Seric void 242860207Seric impl_map_close(map) 242960089Seric MAP *map; 243060089Seric { 243168350Seric if (tTd(38, 20)) 243268350Seric printf("impl_map_close(%s, %s, %x)\n", 243368350Seric map->map_mname, map->map_file, map->map_mflags); 243460089Seric #ifdef NEWDB 243560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 243660089Seric { 243760207Seric db_map_close(map); 243860207Seric map->map_mflags &= ~MF_IMPL_HASH; 243960089Seric } 244060089Seric #endif 244160089Seric 244260089Seric #ifdef NDBM 244360207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 244460089Seric { 244560207Seric ndbm_map_close(map); 244660207Seric map->map_mflags &= ~MF_IMPL_NDBM; 244760089Seric } 244860089Seric #endif 244960089Seric } 245060207Seric /* 245168350Seric ** User map class. 245268350Seric ** 245368350Seric ** Provides access to the system password file. 245468350Seric */ 245568350Seric 245668350Seric /* 245768350Seric ** USER_MAP_OPEN -- open user map 245868350Seric ** 245968350Seric ** Really just binds field names to field numbers. 246068350Seric */ 246168350Seric 246268350Seric bool 246368350Seric user_map_open(map, mode) 246468350Seric MAP *map; 246568350Seric int mode; 246668350Seric { 246768350Seric if (tTd(38, 2)) 246868350Seric printf("user_map_open(%s)\n", map->map_mname); 246968350Seric 247068350Seric if (mode != O_RDONLY) 247168350Seric { 247268350Seric /* issue a pseudo-error message */ 247368350Seric #ifdef ENOSYS 247468350Seric errno = ENOSYS; 247568350Seric #else 247668350Seric # ifdef EFTYPE 247768350Seric errno = EFTYPE; 247868350Seric # else 247968350Seric errno = ENXIO; 248068350Seric # endif 248168350Seric #endif 248268350Seric return FALSE; 248368350Seric } 248468350Seric if (map->map_valcolnm == NULL) 248568350Seric /* nothing */ ; 248668350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 248768350Seric map->map_valcolno = 1; 248868350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 248968350Seric map->map_valcolno = 2; 249068350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 249168350Seric map->map_valcolno = 3; 249268350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 249368350Seric map->map_valcolno = 4; 249468350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 249568350Seric map->map_valcolno = 5; 249668350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 249768350Seric map->map_valcolno = 6; 249868350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 249968350Seric map->map_valcolno = 7; 250068350Seric else 250168350Seric { 250268350Seric syserr("User map %s: unknown column name %s", 250368350Seric map->map_mname, map->map_valcolnm); 250468350Seric return FALSE; 250568350Seric } 250668350Seric return TRUE; 250768350Seric } 250868350Seric 250968350Seric 251068350Seric /* 251168350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 251268350Seric */ 251368350Seric 251468350Seric char * 251568350Seric user_map_lookup(map, key, av, statp) 251668350Seric MAP *map; 251768350Seric char *key; 251868350Seric char **av; 251968350Seric int *statp; 252068350Seric { 252168350Seric struct passwd *pw; 252268350Seric 252368350Seric if (tTd(38, 20)) 252468350Seric printf("user_map_lookup(%s, %s)\n", 252568350Seric map->map_mname, key); 252668350Seric 252768693Seric pw = sm_getpwnam(key); 252868350Seric if (pw == NULL) 252968350Seric return NULL; 253068350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 253168350Seric return map_rewrite(map, key, strlen(key), NULL); 253268350Seric else 253368350Seric { 253468433Seric char *rwval = NULL; 253568350Seric char buf[30]; 253668350Seric 253768350Seric switch (map->map_valcolno) 253868350Seric { 253968350Seric case 0: 254068350Seric case 1: 254168350Seric rwval = pw->pw_name; 254268350Seric break; 254368350Seric 254468350Seric case 2: 254568350Seric rwval = pw->pw_passwd; 254668350Seric break; 254768350Seric 254868350Seric case 3: 254968350Seric sprintf(buf, "%d", pw->pw_uid); 255068350Seric rwval = buf; 255168350Seric break; 255268350Seric 255368350Seric case 4: 255468350Seric sprintf(buf, "%d", pw->pw_gid); 255568350Seric rwval = buf; 255668350Seric break; 255768350Seric 255868350Seric case 5: 255968350Seric rwval = pw->pw_gecos; 256068350Seric break; 256168350Seric 256268350Seric case 6: 256368350Seric rwval = pw->pw_dir; 256468350Seric break; 256568350Seric 256668350Seric case 7: 256768350Seric rwval = pw->pw_shell; 256868350Seric break; 256968350Seric } 257068350Seric return map_rewrite(map, rwval, strlen(rwval), av); 257168350Seric } 257268350Seric } 257368350Seric /* 257468350Seric ** BESTMX -- find the best MX for a name 257568350Seric ** 257668350Seric ** This is really a hack, but I don't see any obvious way 257768350Seric ** to generalize it at the moment. 257868350Seric */ 257968350Seric 258068350Seric #if NAMED_BIND 258168350Seric 258268350Seric char * 258368350Seric bestmx_map_lookup(map, name, av, statp) 258468350Seric MAP *map; 258568350Seric char *name; 258668350Seric char **av; 258768350Seric int *statp; 258868350Seric { 258968350Seric int nmx; 259068350Seric auto int rcode; 259168350Seric char *mxhosts[MAXMXHOSTS + 1]; 259268350Seric 259368350Seric nmx = getmxrr(name, mxhosts, FALSE, &rcode); 259468350Seric if (nmx <= 0) 259568350Seric return NULL; 259668350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 259768350Seric return map_rewrite(map, name, strlen(name), NULL); 259868350Seric else 259968350Seric return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 260068350Seric } 260168350Seric 260268350Seric #endif 260368350Seric /* 260469453Seric ** Program map type. 260569453Seric ** 260669453Seric ** This provides access to arbitrary programs. It should be used 260769453Seric ** only very sparingly, since there is no way to bound the cost 260869453Seric ** of invoking an arbitrary program. 260969453Seric */ 261069453Seric 261169453Seric char * 261269453Seric prog_map_lookup(map, name, av, statp) 261369453Seric MAP *map; 261469453Seric char *name; 261569453Seric char **av; 261669453Seric int *statp; 261769453Seric { 261869453Seric int i; 261969453Seric register char *p; 262069453Seric int fd; 262169453Seric auto pid_t pid; 262269827Seric char *rval; 262369827Seric int stat; 262469453Seric char *argv[MAXPV + 1]; 262569453Seric char buf[MAXLINE]; 262669453Seric 262769453Seric if (tTd(38, 20)) 262869453Seric printf("prog_map_lookup(%s, %s) %s\n", 262969453Seric map->map_mname, name, map->map_file); 263069453Seric 263169453Seric i = 0; 263269453Seric argv[i++] = map->map_file; 263369453Seric strcpy(buf, map->map_rebuild); 263469453Seric for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 263569453Seric { 263669453Seric if (i >= MAXPV - 1) 263769453Seric break; 263869453Seric argv[i++] = p; 263969453Seric } 264069453Seric argv[i++] = name; 264169453Seric argv[i] = NULL; 264269453Seric pid = prog_open(argv, &fd, CurEnv); 264369453Seric if (pid < 0) 264469453Seric { 264569827Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 264669827Seric syserr("prog_map_lookup(%s) failed (%s) -- closing", 264769827Seric map->map_mname, errstring(errno)); 264869827Seric else if (tTd(38, 9)) 264969453Seric printf("prog_map_lookup(%s) failed (%s) -- closing", 265069453Seric map->map_mname, errstring(errno)); 265169453Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 265269827Seric *statp = EX_OSFILE; 265369453Seric return NULL; 265469453Seric } 265569453Seric i = read(fd, buf, sizeof buf - 1); 265669827Seric if (i < 0) 265769827Seric { 265869827Seric syserr("prog_map_lookup(%s): read error %s\n", 265969562Seric map->map_mname, errstring(errno)); 266069827Seric rval = NULL; 266169827Seric } 266269827Seric else if (i == 0 && tTd(38, 2)) 266369827Seric { 266469827Seric printf("prog_map_lookup(%s): empty answer\n", 266569827Seric map->map_mname); 266669827Seric rval = NULL; 266769827Seric } 266869453Seric if (i > 0) 266969453Seric { 267069453Seric buf[i] = '\0'; 267169453Seric p = strchr(buf, '\n'); 267269453Seric if (p != NULL) 267369453Seric *p = '\0'; 267469453Seric 267569453Seric /* collect the return value */ 267669453Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 267769453Seric rval = map_rewrite(map, name, strlen(name), NULL); 267869453Seric else 267969453Seric rval = map_rewrite(map, buf, strlen(buf), NULL); 268069453Seric 268169453Seric /* now flush any additional output */ 268269453Seric while ((i = read(fd, buf, sizeof buf)) > 0) 268369453Seric continue; 268469827Seric } 268569453Seric 268669827Seric /* wait for the process to terminate */ 268769827Seric close(fd); 268869827Seric stat = waitfor(pid); 268969453Seric 269069827Seric if (stat == -1) 269169827Seric { 269269827Seric syserr("prog_map_lookup(%s): wait error %s\n", 269369827Seric map->map_mname, errstring(errno)); 269469827Seric *statp = EX_SOFTWARE; 269569827Seric rval = NULL; 269669453Seric } 2697*69872Seric else if (WIFEXITED(stat)) 269869827Seric { 2699*69872Seric *statp = WEXITSTATUS(stat); 270069827Seric } 270169827Seric else 270269827Seric { 270369827Seric syserr("prog_map_lookup(%s): child died on signal %d", 2704*69872Seric map->map_mname, stat); 270569827Seric *statp = EX_UNAVAILABLE; 270669827Seric rval = NULL; 270769827Seric } 270869827Seric return rval; 270969453Seric } 271069453Seric /* 271168350Seric ** Sequenced map type. 271268350Seric ** 271368350Seric ** Tries each map in order until something matches, much like 271468350Seric ** implicit. Stores go to the first map in the list that can 271568350Seric ** support storing. 271668350Seric ** 271768350Seric ** This is slightly unusual in that there are two interfaces. 271868350Seric ** The "sequence" interface lets you stack maps arbitrarily. 271968350Seric ** The "switch" interface builds a sequence map by looking 272068350Seric ** at a system-dependent configuration file such as 272168350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 272268350Seric ** 272368350Seric ** We don't need an explicit open, since all maps are 272468350Seric ** opened during startup, including underlying maps. 272568350Seric */ 272668350Seric 272768350Seric /* 272868350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 272968350Seric */ 273068350Seric 273168350Seric bool 273268350Seric seq_map_parse(map, ap) 273368350Seric MAP *map; 273468350Seric char *ap; 273568350Seric { 273668350Seric int maxmap; 273768350Seric 273868350Seric if (tTd(38, 2)) 273968350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 274068350Seric maxmap = 0; 274168350Seric while (*ap != '\0') 274268350Seric { 274368350Seric register char *p; 274468350Seric STAB *s; 274568350Seric 274668350Seric /* find beginning of map name */ 274768350Seric while (isascii(*ap) && isspace(*ap)) 274868350Seric ap++; 274968350Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 275068350Seric continue; 275168350Seric if (*p != '\0') 275268350Seric *p++ = '\0'; 275368350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 275468350Seric p++; 275568350Seric if (*ap == '\0') 275668350Seric { 275768350Seric ap = p; 275868350Seric continue; 275968350Seric } 276068350Seric s = stab(ap, ST_MAP, ST_FIND); 276168350Seric if (s == NULL) 276268350Seric { 276368350Seric syserr("Sequence map %s: unknown member map %s", 276468350Seric map->map_mname, ap); 276568350Seric } 276668350Seric else if (maxmap == MAXMAPSTACK) 276768350Seric { 276868350Seric syserr("Sequence map %s: too many member maps (%d max)", 276968350Seric map->map_mname, MAXMAPSTACK); 277068350Seric maxmap++; 277168350Seric } 277268350Seric else if (maxmap < MAXMAPSTACK) 277368350Seric { 277468350Seric map->map_stack[maxmap++] = &s->s_map; 277568350Seric } 277668350Seric ap = p; 277768350Seric } 277868350Seric return TRUE; 277968350Seric } 278068350Seric 278168350Seric 278268350Seric /* 278368350Seric ** SWITCH_MAP_OPEN -- open a switched map 278468350Seric ** 278568350Seric ** This looks at the system-dependent configuration and builds 278668350Seric ** a sequence map that does the same thing. 278768350Seric ** 278868350Seric ** Every system must define a switch_map_find routine in conf.c 278968350Seric ** that will return the list of service types associated with a 279068350Seric ** given service class. 279168350Seric */ 279268350Seric 279368350Seric bool 279468350Seric switch_map_open(map, mode) 279568350Seric MAP *map; 279668350Seric int mode; 279768350Seric { 279868350Seric int mapno; 279968350Seric int nmaps; 280068350Seric char *maptype[MAXMAPSTACK]; 280168350Seric 280268350Seric if (tTd(38, 2)) 280368350Seric printf("switch_map_open(%s, %s, %d)\n", 280468350Seric map->map_mname, map->map_file, mode); 280568350Seric 280668350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 280768350Seric if (tTd(38, 19)) 280868350Seric { 280968350Seric printf("\tswitch_map_find => %d\n", nmaps); 281068350Seric for (mapno = 0; mapno < nmaps; mapno++) 281168350Seric printf("\t\t%s\n", maptype[mapno]); 281268350Seric } 281368350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 281468350Seric return FALSE; 281568350Seric 281668350Seric for (mapno = 0; mapno < nmaps; mapno++) 281768350Seric { 281868350Seric register STAB *s; 281968350Seric char nbuf[MAXNAME + 1]; 282068350Seric 282168350Seric if (maptype[mapno] == NULL) 282268350Seric continue; 282368350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 282468350Seric s = stab(nbuf, ST_MAP, ST_FIND); 282568350Seric if (s == NULL) 282668350Seric { 282768350Seric syserr("Switch map %s: unknown member map %s", 282868350Seric map->map_mname, nbuf); 282968350Seric } 283068350Seric else 283168350Seric { 283268350Seric map->map_stack[mapno] = &s->s_map; 283368350Seric if (tTd(38, 4)) 283468350Seric printf("\tmap_stack[%d] = %s:%s\n", 283568350Seric mapno, s->s_map.map_class->map_cname, 283668350Seric nbuf); 283768350Seric } 283868350Seric } 283968350Seric return TRUE; 284068350Seric } 284168350Seric 284268350Seric 284368350Seric /* 284468350Seric ** SEQ_MAP_CLOSE -- close all underlying maps 284568350Seric */ 284668350Seric 284769748Seric void 284868350Seric seq_map_close(map) 284968350Seric MAP *map; 285068350Seric { 285168350Seric int mapno; 285268350Seric 285368350Seric if (tTd(38, 20)) 285468350Seric printf("seq_map_close(%s)\n", map->map_mname); 285568350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 285668350Seric { 285768350Seric MAP *mm = map->map_stack[mapno]; 285868350Seric 285968350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 286068350Seric continue; 286168350Seric mm->map_class->map_close(mm); 286268798Seric mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 286368350Seric } 286468350Seric } 286568350Seric 286668350Seric 286768350Seric /* 286868350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 286968350Seric */ 287068350Seric 287168350Seric char * 287268350Seric seq_map_lookup(map, key, args, pstat) 287368350Seric MAP *map; 287468350Seric char *key; 287568350Seric char **args; 287668350Seric int *pstat; 287768350Seric { 287868350Seric int mapno; 287968350Seric int mapbit = 0x01; 288068350Seric 288168350Seric if (tTd(38, 20)) 288268350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 288368350Seric 288468350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 288568350Seric { 288668350Seric MAP *mm = map->map_stack[mapno]; 288768350Seric int stat = 0; 288868350Seric char *rv; 288968350Seric 289068350Seric if (mm == NULL) 289168350Seric continue; 289268350Seric if (!bitset(MF_OPEN, mm->map_mflags)) 289368350Seric { 289468350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 289568350Seric { 289668350Seric *pstat = EX_UNAVAILABLE; 289768350Seric return NULL; 289868350Seric } 289968350Seric continue; 290068350Seric } 290168350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 290268350Seric if (rv != NULL) 290368350Seric return rv; 290468350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 290568350Seric return NULL; 290668350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 290768350Seric { 290868350Seric *pstat = stat; 290968350Seric return NULL; 291068350Seric } 291168350Seric } 291268350Seric return NULL; 291368350Seric } 291468350Seric 291568350Seric 291668350Seric /* 291768350Seric ** SEQ_MAP_STORE -- sequenced map store 291868350Seric */ 291968350Seric 292068350Seric void 292168350Seric seq_map_store(map, key, val) 292268350Seric MAP *map; 292368350Seric char *key; 292468350Seric char *val; 292568350Seric { 292668350Seric int mapno; 292768350Seric 292868350Seric if (tTd(38, 12)) 292968350Seric printf("seq_map_store(%s, %s, %s)\n", 293068350Seric map->map_mname, key, val); 293168350Seric 293268350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 293368350Seric { 293468350Seric MAP *mm = map->map_stack[mapno]; 293568350Seric 293668350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 293768350Seric continue; 293868350Seric 293968350Seric mm->map_class->map_store(mm, key, val); 294068350Seric return; 294168350Seric } 294268350Seric syserr("seq_map_store(%s, %s, %s): no writable map", 294368350Seric map->map_mname, key, val); 294468350Seric } 294568350Seric /* 294660207Seric ** NULL stubs 294760089Seric */ 294860089Seric 294960207Seric bool 295060207Seric null_map_open(map, mode) 295160089Seric MAP *map; 295260207Seric int mode; 295360089Seric { 295460207Seric return TRUE; 295560089Seric } 295660089Seric 295760207Seric void 295860207Seric null_map_close(map) 295960207Seric MAP *map; 296060089Seric { 296160207Seric return; 296260207Seric } 296360089Seric 296460207Seric void 296560207Seric null_map_store(map, key, val) 296660207Seric MAP *map; 296760207Seric char *key; 296860207Seric char *val; 296960089Seric { 297060207Seric return; 297160089Seric } 297268350Seric 297368350Seric 297468350Seric /* 297568350Seric ** BOGUS stubs 297668350Seric */ 297768350Seric 297868350Seric char * 297968350Seric bogus_map_lookup(map, key, args, pstat) 298068350Seric MAP *map; 298168350Seric char *key; 298268350Seric char **args; 298368350Seric int *pstat; 298468350Seric { 298568350Seric *pstat = EX_TEMPFAIL; 298668350Seric return NULL; 298768350Seric } 298868350Seric 298968350Seric MAPCLASS BogusMapClass = 299068350Seric { 299168350Seric "bogus-map", NULL, 0, 299268350Seric NULL, bogus_map_lookup, null_map_store, 299368350Seric null_map_open, null_map_close, 299468350Seric }; 2995