156822Seric /* 256822Seric * Copyright (c) 1992 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*68497Seric static char sccsid[] = "@(#)map.c 8.46 (Berkeley) 03/07/95"; 1156822Seric #endif /* not lint */ 1256822Seric 1356822Seric #include "sendmail.h" 1456822Seric 1560089Seric #ifdef NDBM 1656822Seric #include <ndbm.h> 1756822Seric #endif 1860089Seric #ifdef NEWDB 1956822Seric #include <db.h> 2056822Seric #endif 2160089Seric #ifdef NIS 2257208Seric #include <rpcsvc/ypclnt.h> 2357208Seric #endif 2456822Seric 2556822Seric /* 2660089Seric ** MAP.C -- implementations for various map classes. 2756822Seric ** 2860089Seric ** Each map class implements a series of functions: 2960089Seric ** 3060089Seric ** bool map_parse(MAP *map, char *args) 3160089Seric ** Parse the arguments from the config file. Return TRUE 3260089Seric ** if they were ok, FALSE otherwise. Fill in map with the 3360089Seric ** values. 3460089Seric ** 3560222Seric ** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 3660222Seric ** Look up the key in the given map. If found, do any 3760222Seric ** rewriting the map wants (including "args" if desired) 3860089Seric ** and return the value. Set *pstat to the appropriate status 3960222Seric ** on error and return NULL. Args will be NULL if called 4060222Seric ** from the alias routines, although this should probably 4160222Seric ** not be relied upon. It is suggested you call map_rewrite 4260222Seric ** to return the results -- it takes care of null termination 4360222Seric ** and uses a dynamically expanded buffer as needed. 4460089Seric ** 4560089Seric ** void map_store(MAP *map, char *key, char *value) 4660089Seric ** Store the key:value pair in the map. 4760089Seric ** 4860089Seric ** bool map_open(MAP *map, int mode) 4960222Seric ** Open the map for the indicated mode. Mode should 5060222Seric ** be either O_RDONLY or O_RDWR. Return TRUE if it 5160222Seric ** was opened successfully, FALSE otherwise. If the open 5260222Seric ** failed an the MF_OPTIONAL flag is not set, it should 5360222Seric ** also print an error. If the MF_ALIAS bit is set 5460222Seric ** and this map class understands the @:@ convention, it 5560222Seric ** should call aliaswait() before returning. 5660089Seric ** 5760089Seric ** void map_close(MAP *map) 5860089Seric ** Close the map. 5960089Seric */ 6060089Seric 6160089Seric #define DBMMODE 0644 6264718Seric 6364718Seric extern bool aliaswait __P((MAP *, char *, int)); 6460089Seric /* 6560089Seric ** MAP_PARSEARGS -- parse config line arguments for database lookup 6660089Seric ** 6760089Seric ** This is a generic version of the map_parse method. 6860089Seric ** 6956822Seric ** Parameters: 7060089Seric ** map -- the map being initialized. 7160089Seric ** ap -- a pointer to the args on the config line. 7256822Seric ** 7356822Seric ** Returns: 7460089Seric ** TRUE -- if everything parsed OK. 7556822Seric ** FALSE -- otherwise. 7656822Seric ** 7756822Seric ** Side Effects: 7860089Seric ** null terminates the filename; stores it in map 7956822Seric */ 8056822Seric 8156822Seric bool 8260089Seric map_parseargs(map, ap) 8356822Seric MAP *map; 8460089Seric char *ap; 8556822Seric { 8660089Seric register char *p = ap; 8756822Seric 8863753Seric map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; 8960089Seric for (;;) 9060089Seric { 9160089Seric while (isascii(*p) && isspace(*p)) 9260089Seric p++; 9360089Seric if (*p != '-') 9460089Seric break; 9560089Seric switch (*++p) 9660089Seric { 9760089Seric case 'N': 9860207Seric map->map_mflags |= MF_INCLNULL; 9963753Seric map->map_mflags &= ~MF_TRY0NULL; 10060089Seric break; 10160089Seric 10263753Seric case 'O': 10363753Seric map->map_mflags &= ~MF_TRY1NULL; 10463753Seric break; 10563753Seric 10660089Seric case 'o': 10760207Seric map->map_mflags |= MF_OPTIONAL; 10860089Seric break; 10960089Seric 11060089Seric case 'f': 11160207Seric map->map_mflags |= MF_NOFOLDCASE; 11260089Seric break; 11360089Seric 11460089Seric case 'm': 11560207Seric map->map_mflags |= MF_MATCHONLY; 11660089Seric break; 11760089Seric 118*68497Seric case 'A': 119*68497Seric map->map_mflags |= MF_APPEND; 120*68497Seric break; 121*68497Seric 12260089Seric case 'a': 12360089Seric map->map_app = ++p; 12460089Seric break; 12568350Seric 12668350Seric case 'k': 12768350Seric while (isascii(*++p) && isspace(*p)) 12868350Seric continue; 12968350Seric map->map_keycolnm = p; 13068350Seric break; 13168350Seric 13268350Seric case 'v': 13368350Seric while (isascii(*++p) && isspace(*p)) 13468350Seric continue; 13568350Seric map->map_valcolnm = p; 13668350Seric break; 13768350Seric 13868350Seric case 'z': 13968350Seric if (*++p != '\\') 14068350Seric map->map_coldelim = *p; 14168350Seric else 14268350Seric { 14368350Seric switch (*++p) 14468350Seric { 14568350Seric case 'n': 14668350Seric map->map_coldelim = '\n'; 14768350Seric break; 14868350Seric 14968350Seric case 't': 15068350Seric map->map_coldelim = '\t'; 15168350Seric break; 15268350Seric 15368350Seric default: 15468350Seric map->map_coldelim = '\\'; 15568350Seric } 15668350Seric } 15768350Seric break; 158*68497Seric #ifdef RESERVED_FOR_SUN 159*68497Seric case 'd': 160*68497Seric map->map_mflags |= MF_DOMAIN_WIDE; 161*68497Seric break; 162*68497Seric 163*68497Seric case 's': 164*68497Seric /* info type */ 165*68497Seric break; 166*68497Seric #endif 16760089Seric } 16860089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 16960089Seric p++; 17060089Seric if (*p != '\0') 17160089Seric *p++ = '\0'; 17260089Seric } 17360089Seric if (map->map_app != NULL) 17460089Seric map->map_app = newstr(map->map_app); 17568350Seric if (map->map_keycolnm != NULL) 17668350Seric map->map_keycolnm = newstr(map->map_keycolnm); 17768350Seric if (map->map_valcolnm != NULL) 17868350Seric map->map_valcolnm = newstr(map->map_valcolnm); 17960089Seric 18060089Seric if (*p != '\0') 18160089Seric { 18260089Seric map->map_file = p; 18360089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 18460089Seric p++; 18560089Seric if (*p != '\0') 18660089Seric *p++ = '\0'; 18760089Seric map->map_file = newstr(map->map_file); 18860089Seric } 18960089Seric 19060089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 19160089Seric p++; 19260089Seric if (*p != '\0') 19360089Seric map->map_rebuild = newstr(p); 19460089Seric 19568350Seric if (map->map_file == NULL && 19668350Seric !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 19757208Seric { 19860089Seric syserr("No file name for %s map %s", 19960089Seric map->map_class->map_cname, map->map_mname); 20056822Seric return FALSE; 20157208Seric } 20260089Seric return TRUE; 20360089Seric } 20460089Seric /* 20560089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 20660089Seric ** 20760089Seric ** It also adds the map_app string. It can be used as a utility 20860089Seric ** in the map_lookup method. 20960089Seric ** 21060089Seric ** Parameters: 21160089Seric ** map -- the map that causes this. 21260089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 21360089Seric ** slen -- the length of s. 21460089Seric ** av -- arguments to interpolate into buf. 21560089Seric ** 21660089Seric ** Returns: 21767895Seric ** Pointer to rewritten result. This is static data that 21867895Seric ** should be copied if it is to be saved! 21960089Seric ** 22060089Seric ** Side Effects: 22160089Seric ** none. 22260089Seric */ 22360089Seric 22460089Seric char * 22560089Seric map_rewrite(map, s, slen, av) 22660089Seric register MAP *map; 22760089Seric register char *s; 22860089Seric int slen; 22960089Seric char **av; 23060089Seric { 23160089Seric register char *bp; 23260089Seric register char c; 23360089Seric char **avp; 23460089Seric register char *ap; 23560089Seric int i; 23660089Seric int len; 23767895Seric static int buflen = -1; 23867895Seric static char *buf = NULL; 23960089Seric 24060537Seric if (tTd(39, 1)) 24160089Seric { 24260256Seric printf("map_rewrite(%.*s), av =", slen, s); 24360256Seric if (av == NULL) 24460256Seric printf(" (nullv)"); 24560256Seric else 24660256Seric { 24760256Seric for (avp = av; *avp != NULL; avp++) 24860256Seric printf("\n\t%s", *avp); 24960256Seric } 25060256Seric printf("\n"); 25160089Seric } 25260089Seric 25360089Seric /* count expected size of output (can safely overestimate) */ 25460089Seric i = len = slen; 25560089Seric if (av != NULL) 25660089Seric { 25760089Seric bp = s; 25860089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 25960089Seric { 26060089Seric if (c != '%') 26160089Seric continue; 26260089Seric if (--i < 0) 26360089Seric break; 26460089Seric c = *bp++; 26560089Seric if (!(isascii(c) && isdigit(c))) 26660089Seric continue; 26763937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 26860089Seric continue; 26960089Seric if (*avp == NULL) 27060089Seric continue; 27160089Seric len += strlen(*avp); 27260089Seric } 27360089Seric } 27460089Seric if (map->map_app != NULL) 27560089Seric len += strlen(map->map_app); 27667895Seric if (buflen < ++len) 27760089Seric { 27860089Seric /* need to malloc additional space */ 27967895Seric buflen = len; 28067895Seric if (buf != NULL) 28167895Seric free(buf); 28267895Seric buf = xalloc(buflen); 28360089Seric } 28460089Seric 28567895Seric bp = buf; 28660089Seric if (av == NULL) 28760089Seric { 28860089Seric bcopy(s, bp, slen); 28960089Seric bp += slen; 29060089Seric } 29160089Seric else 29260089Seric { 29360089Seric while (--slen >= 0 && (c = *s++) != '\0') 29460089Seric { 29560089Seric if (c != '%') 29660089Seric { 29760089Seric pushc: 29860089Seric *bp++ = c; 29960089Seric continue; 30060089Seric } 30160089Seric if (--slen < 0 || (c = *s++) == '\0') 30260089Seric c = '%'; 30360089Seric if (c == '%') 30460089Seric goto pushc; 30560089Seric if (!(isascii(c) && isdigit(c))) 30660089Seric { 30760089Seric *bp++ = '%'; 30860089Seric goto pushc; 30960089Seric } 31063937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 31160089Seric continue; 31260089Seric if (*avp == NULL) 31360089Seric continue; 31460089Seric 31560089Seric /* transliterate argument into output string */ 31660089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 31760089Seric *bp++ = c; 31860089Seric } 31960089Seric } 32060089Seric if (map->map_app != NULL) 32160089Seric strcpy(bp, map->map_app); 32260089Seric else 32360089Seric *bp = '\0'; 32460537Seric if (tTd(39, 1)) 32567895Seric printf("map_rewrite => %s\n", buf); 32667895Seric return buf; 32760089Seric } 32860089Seric /* 32960537Seric ** INITMAPS -- initialize for aliasing 33060537Seric ** 33160537Seric ** Parameters: 33260537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 33360537Seric ** e -- current envelope. 33460537Seric ** 33560537Seric ** Returns: 33660537Seric ** none. 33760537Seric ** 33860537Seric ** Side Effects: 33960537Seric ** initializes aliases: 34060537Seric ** if NDBM: opens the database. 34160537Seric ** if ~NDBM: reads the aliases into the symbol table. 34260537Seric */ 34360537Seric 34460537Seric initmaps(rebuild, e) 34560537Seric bool rebuild; 34660537Seric register ENVELOPE *e; 34760537Seric { 34860537Seric extern void map_init(); 34960537Seric 35064671Seric #ifdef XDEBUG 35164671Seric checkfd012("entering initmaps"); 35264671Seric #endif 35360537Seric CurEnv = e; 35465085Seric if (rebuild) 35565085Seric { 35665085Seric stabapply(map_init, 1); 35765085Seric stabapply(map_init, 2); 35865085Seric } 35965085Seric else 36065085Seric { 36165085Seric stabapply(map_init, 0); 36265085Seric } 36364671Seric #ifdef XDEBUG 36464671Seric checkfd012("exiting initmaps"); 36564671Seric #endif 36660537Seric } 36760537Seric 36860537Seric void 36960537Seric map_init(s, rebuild) 37060537Seric register STAB *s; 37160537Seric int rebuild; 37260537Seric { 37360537Seric register MAP *map; 37460537Seric 37560537Seric /* has to be a map */ 37660537Seric if (s->s_type != ST_MAP) 37760537Seric return; 37860537Seric 37960537Seric map = &s->s_map; 38060537Seric if (!bitset(MF_VALID, map->map_mflags)) 38160537Seric return; 38260537Seric 38360537Seric if (tTd(38, 2)) 38468350Seric printf("map_init(%s:%s, %s, %d)\n", 38564690Seric map->map_class->map_cname == NULL ? "NULL" : 38664690Seric map->map_class->map_cname, 38768350Seric map->map_mname == NULL ? "NULL" : map->map_mname, 38865085Seric map->map_file == NULL ? "NULL" : map->map_file, 38965085Seric rebuild); 39060537Seric 39165085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && 39265085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) 39365085Seric { 39465085Seric if (tTd(38, 3)) 39565085Seric printf("\twrong pass\n"); 39665085Seric return; 39765085Seric } 39865085Seric 39960537Seric /* if already open, close it (for nested open) */ 40060537Seric if (bitset(MF_OPEN, map->map_mflags)) 40160537Seric { 40260537Seric map->map_class->map_close(map); 40360537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 40460537Seric } 40560537Seric 40665085Seric if (rebuild == 2) 40760537Seric { 40865085Seric rebuildaliases(map, FALSE); 40960537Seric } 41060537Seric else 41160537Seric { 41260537Seric if (map->map_class->map_open(map, O_RDONLY)) 41360537Seric { 41460537Seric if (tTd(38, 4)) 41568350Seric printf("\t%s:%s %s: valid\n", 41664690Seric map->map_class->map_cname == NULL ? "NULL" : 41764690Seric map->map_class->map_cname, 41868350Seric map->map_mname == NULL ? "NULL" : 41968350Seric map->map_mname, 42064690Seric map->map_file == NULL ? "NULL" : 42164690Seric map->map_file); 42260537Seric map->map_mflags |= MF_OPEN; 42360537Seric } 42468350Seric else 42568350Seric { 42668350Seric if (tTd(38, 4)) 42768350Seric printf("\t%s:%s %s: invalid: %s\n", 42868350Seric map->map_class->map_cname == NULL ? "NULL" : 42968350Seric map->map_class->map_cname, 43068350Seric map->map_mname == NULL ? "NULL" : 43168350Seric map->map_mname, 43268350Seric map->map_file == NULL ? "NULL" : 43368350Seric map->map_file, 43468350Seric errstring(errno)); 43568350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 43668350Seric { 43768350Seric extern MAPCLASS BogusMapClass; 43868350Seric 43968350Seric map->map_class = &BogusMapClass; 44068350Seric map->map_mflags |= MF_OPEN; 44168350Seric } 44268350Seric } 44360537Seric } 44460537Seric } 44560537Seric /* 44660089Seric ** NDBM modules 44760089Seric */ 44860089Seric 44960089Seric #ifdef NDBM 45060089Seric 45160089Seric /* 45260089Seric ** DBM_MAP_OPEN -- DBM-style map open 45360089Seric */ 45460089Seric 45560089Seric bool 45660089Seric ndbm_map_open(map, mode) 45760089Seric MAP *map; 45860089Seric int mode; 45960089Seric { 46064284Seric register DBM *dbm; 46164284Seric struct stat st; 46260089Seric 46360537Seric if (tTd(38, 2)) 46468350Seric printf("ndbm_map_open(%s, %s, %d)\n", 46568350Seric map->map_mname, map->map_file, mode); 46660089Seric 46760207Seric if (mode == O_RDWR) 46860207Seric mode |= O_CREAT|O_TRUNC; 46960207Seric 47060089Seric /* open the database */ 47160089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 47256822Seric if (dbm == NULL) 47356822Seric { 47464718Seric if (aliaswait(map, ".pag", FALSE)) 47564718Seric return TRUE; 47660207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 47756836Seric syserr("Cannot open DBM database %s", map->map_file); 47856822Seric return FALSE; 47956822Seric } 48060089Seric map->map_db1 = (void *) dbm; 48164964Seric if (mode == O_RDONLY) 48264964Seric { 48364964Seric if (bitset(MF_ALIAS, map->map_mflags) && 48464964Seric !aliaswait(map, ".pag", TRUE)) 48564718Seric return FALSE; 48664964Seric } 48764964Seric else 48864964Seric { 48964964Seric int fd; 49064964Seric 49164964Seric /* exclusive lock for duration of rebuild */ 49264964Seric fd = dbm_dirfno((DBM *) map->map_db1); 49364964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 49464964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 49564964Seric map->map_mflags |= MF_LOCKED; 49664964Seric } 49764718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 49864284Seric map->map_mtime = st.st_mtime; 49956822Seric return TRUE; 50056822Seric } 50160089Seric 50260089Seric 50360089Seric /* 50456822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 50556822Seric */ 50656822Seric 50756822Seric char * 50860089Seric ndbm_map_lookup(map, name, av, statp) 50956822Seric MAP *map; 51060089Seric char *name; 51156822Seric char **av; 51259084Seric int *statp; 51356822Seric { 51456822Seric datum key, val; 51564373Seric int fd; 51660089Seric char keybuf[MAXNAME + 1]; 51756822Seric 51860537Seric if (tTd(38, 20)) 51968350Seric printf("ndbm_map_lookup(%s, %s)\n", 52068350Seric map->map_mname, name); 52160089Seric 52260089Seric key.dptr = name; 52360089Seric key.dsize = strlen(name); 52460207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 52557014Seric { 52660089Seric if (key.dsize > sizeof keybuf - 1) 52760089Seric key.dsize = sizeof keybuf - 1; 52860089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 52960089Seric makelower(keybuf); 53060089Seric key.dptr = keybuf; 53157014Seric } 53264373Seric fd = dbm_dirfno((DBM *) map->map_db1); 53364388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 53464373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 53563753Seric val.dptr = NULL; 53663753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 53763753Seric { 53863753Seric val = dbm_fetch((DBM *) map->map_db1, key); 53963753Seric if (val.dptr != NULL) 54063753Seric map->map_mflags &= ~MF_TRY1NULL; 54163753Seric } 54263753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 54363753Seric { 54456822Seric key.dsize++; 54563753Seric val = dbm_fetch((DBM *) map->map_db1, key); 54663753Seric if (val.dptr != NULL) 54763753Seric map->map_mflags &= ~MF_TRY0NULL; 54863753Seric } 54964388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 55064373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 55156822Seric if (val.dptr == NULL) 55256822Seric return NULL; 55360207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 55463753Seric return map_rewrite(map, name, strlen(name), NULL); 55563753Seric else 55663753Seric return map_rewrite(map, val.dptr, val.dsize, av); 55756822Seric } 55856822Seric 55956822Seric 56056822Seric /* 56160089Seric ** DBM_MAP_STORE -- store a datum in the database 56256822Seric */ 56356822Seric 56460089Seric void 56560089Seric ndbm_map_store(map, lhs, rhs) 56660089Seric register MAP *map; 56760089Seric char *lhs; 56860089Seric char *rhs; 56960089Seric { 57060089Seric datum key; 57160089Seric datum data; 57260089Seric int stat; 57360089Seric 57460537Seric if (tTd(38, 12)) 57568350Seric printf("ndbm_map_store(%s, %s, %s)\n", 57668350Seric map->map_mname, lhs, rhs); 57760089Seric 57860089Seric key.dsize = strlen(lhs); 57960089Seric key.dptr = lhs; 58060089Seric 58160089Seric data.dsize = strlen(rhs); 58260089Seric data.dptr = rhs; 58360089Seric 58460207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 58560089Seric { 58660089Seric key.dsize++; 58760089Seric data.dsize++; 58860089Seric } 58960089Seric 59060089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 59160089Seric if (stat > 0) 59260089Seric { 593*68497Seric if (!bitset(MF_APPEND, map->map_mflags)) 594*68497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 595*68497Seric else 596*68497Seric { 597*68497Seric static char *buf = NULL; 598*68497Seric static int bufsiz = 0; 599*68497Seric datum old; 600*68497Seric 601*68497Seric old.dptr = ndbm_map_lookup(map, key.dptr, NULL); 602*68497Seric if (old.dptr != NULL && *old.dptr != '\0') 603*68497Seric { 604*68497Seric old.dsize = strlen(old.dptr); 605*68497Seric if (data.dsize + old.dsize + 2 > bufsiz) 606*68497Seric { 607*68497Seric if (buf != NULL) 608*68497Seric (void) free(buf); 609*68497Seric bufsiz = data.dsize + old.dsize + 2; 610*68497Seric buf = xalloc(bufsiz); 611*68497Seric } 612*68497Seric sprintf(buf, "%s,%s", data.dptr, old.dptr); 613*68497Seric data.dsize = data.dsize + old.dsize + 1; 614*68497Seric data.dptr = buf; 615*68497Seric if (tTd(38, 9)) 616*68497Seric printf("ndbm_map_store append=%s\n", data.dptr); 617*68497Seric } 618*68497Seric } 61960089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 62060089Seric } 62160089Seric if (stat != 0) 62260089Seric syserr("readaliases: dbm put (%s)", lhs); 62360089Seric } 62460089Seric 62560089Seric 62660089Seric /* 62760207Seric ** NDBM_MAP_CLOSE -- close the database 62860089Seric */ 62960089Seric 63060089Seric void 63160089Seric ndbm_map_close(map) 63260089Seric register MAP *map; 63360089Seric { 63466773Seric if (tTd(38, 9)) 63568350Seric printf("ndbm_map_close(%s, %s, %x)\n", 63668350Seric map->map_mname, map->map_file, map->map_mflags); 63766773Seric 63860207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 63960089Seric { 64064250Seric #ifdef NIS 64164075Seric bool inclnull; 64260089Seric char buf[200]; 64360089Seric 64464075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 64564075Seric map->map_mflags &= ~MF_INCLNULL; 64664075Seric 64760089Seric (void) sprintf(buf, "%010ld", curtime()); 64860089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 64960089Seric 65064941Seric (void) gethostname(buf, sizeof buf); 65160089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 65264075Seric 65364075Seric if (inclnull) 65464075Seric map->map_mflags |= MF_INCLNULL; 65560089Seric #endif 65660089Seric 65760089Seric /* write out the distinguished alias */ 65860089Seric ndbm_map_store(map, "@", "@"); 65960089Seric } 66060089Seric dbm_close((DBM *) map->map_db1); 66160089Seric } 66260089Seric 66360089Seric #endif 66460089Seric /* 66560582Seric ** NEWDB (Hash and BTree) Modules 66660089Seric */ 66760089Seric 66860089Seric #ifdef NEWDB 66960089Seric 67060089Seric /* 67160582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 67260582Seric ** 67360582Seric ** These do rather bizarre locking. If you can lock on open, 67460582Seric ** do that to avoid the condition of opening a database that 67560582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 67660582Seric ** there will be a race condition. If opening for read-only, 67760582Seric ** we immediately release the lock to avoid freezing things up. 67860582Seric ** We really ought to hold the lock, but guarantee that we won't 67960582Seric ** be pokey about it. That's hard to do. 68060089Seric */ 68160089Seric 68256822Seric bool 68360089Seric bt_map_open(map, mode) 68456822Seric MAP *map; 68560089Seric int mode; 68656822Seric { 68756822Seric DB *db; 68860228Seric int i; 68960582Seric int omode; 69064373Seric int fd; 69164284Seric struct stat st; 69260089Seric char buf[MAXNAME]; 69356822Seric 69460537Seric if (tTd(38, 2)) 69568350Seric printf("bt_map_open(%s, %s, %d)\n", 69668350Seric map->map_mname, map->map_file, mode); 69760089Seric 69860582Seric omode = mode; 69960582Seric if (omode == O_RDWR) 70060582Seric { 70160582Seric omode |= O_CREAT|O_TRUNC; 70265830Seric #if defined(O_EXLOCK) && HASFLOCK 70360582Seric omode |= O_EXLOCK; 70466843Seric # if !OLD_NEWDB 70560582Seric } 70660582Seric else 70760582Seric { 70860582Seric omode |= O_SHLOCK; 70960582Seric # endif 71060582Seric #endif 71160582Seric } 71260207Seric 71360228Seric (void) strcpy(buf, map->map_file); 71460228Seric i = strlen(buf); 71560228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 71660228Seric (void) strcat(buf, ".db"); 71760582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 71856822Seric if (db == NULL) 71956822Seric { 72064718Seric #ifdef MAYBENEXTRELEASE 72164718Seric if (aliaswait(map, ".db", FALSE)) 72264718Seric return TRUE; 72364718Seric #endif 72460207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 72556836Seric syserr("Cannot open BTREE database %s", map->map_file); 72656822Seric return FALSE; 72756822Seric } 72868350Seric #if !OLD_NEWDB 72964373Seric fd = db->fd(db); 73068350Seric # if HASFLOCK 73168350Seric # if !defined(O_EXLOCK) 73264373Seric if (mode == O_RDWR && fd >= 0) 73364388Seric { 73464388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 73564388Seric map->map_mflags |= MF_LOCKED; 73664388Seric } 73768350Seric # else 73864373Seric if (mode == O_RDONLY && fd >= 0) 73964373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 74064388Seric else 74164388Seric map->map_mflags |= MF_LOCKED; 74268350Seric # endif 74360582Seric # endif 74460582Seric #endif 74560585Seric 74660585Seric /* try to make sure that at least the database header is on disk */ 74760585Seric if (mode == O_RDWR) 74866843Seric #if OLD_NEWDB 74964373Seric (void) db->sync(db); 75064373Seric #else 75160585Seric (void) db->sync(db, 0); 75260585Seric 75364373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 75464284Seric map->map_mtime = st.st_mtime; 75564284Seric #endif 75664284Seric 75760089Seric map->map_db2 = (void *) db; 75860207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 75964718Seric if (!aliaswait(map, ".db", TRUE)) 76064718Seric return FALSE; 76156822Seric return TRUE; 76256822Seric } 76356822Seric 76456822Seric 76556822Seric /* 76656822Seric ** HASH_MAP_INIT -- HASH-style map initialization 76756822Seric */ 76856822Seric 76956822Seric bool 77060089Seric hash_map_open(map, mode) 77156822Seric MAP *map; 77260089Seric int mode; 77356822Seric { 77456822Seric DB *db; 77560228Seric int i; 77660582Seric int omode; 77764373Seric int fd; 77864284Seric struct stat st; 77960089Seric char buf[MAXNAME]; 78056822Seric 78160537Seric if (tTd(38, 2)) 78268350Seric printf("hash_map_open(%s, %s, %d)\n", 78368350Seric map->map_mname, map->map_file, mode); 78460089Seric 78560582Seric omode = mode; 78660582Seric if (omode == O_RDWR) 78760582Seric { 78860582Seric omode |= O_CREAT|O_TRUNC; 78965830Seric #if defined(O_EXLOCK) && HASFLOCK 79060582Seric omode |= O_EXLOCK; 79166843Seric # if !OLD_NEWDB 79260582Seric } 79360582Seric else 79460582Seric { 79560582Seric omode |= O_SHLOCK; 79660582Seric # endif 79760582Seric #endif 79860582Seric } 79960207Seric 80060228Seric (void) strcpy(buf, map->map_file); 80160228Seric i = strlen(buf); 80260228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 80360228Seric (void) strcat(buf, ".db"); 80460582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 80556822Seric if (db == NULL) 80656822Seric { 80764718Seric #ifdef MAYBENEXTRELEASE 80864718Seric if (aliaswait(map, ".db", FALSE)) 80964718Seric return TRUE; 81064718Seric #endif 81160207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 81256836Seric syserr("Cannot open HASH database %s", map->map_file); 81356822Seric return FALSE; 81456822Seric } 81568350Seric #if !OLD_NEWDB 81664373Seric fd = db->fd(db); 81768350Seric # if HASFLOCK 81868350Seric # if !defined(O_EXLOCK) 81964373Seric if (mode == O_RDWR && fd >= 0) 82064388Seric { 82164388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 82264388Seric map->map_mflags |= MF_LOCKED; 82364388Seric } 82468350Seric # else 82564373Seric if (mode == O_RDONLY && fd >= 0) 82664373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 82764388Seric else 82864388Seric map->map_mflags |= MF_LOCKED; 82968350Seric # endif 83060582Seric # endif 83160582Seric #endif 83260585Seric 83360585Seric /* try to make sure that at least the database header is on disk */ 83460585Seric if (mode == O_RDWR) 83566843Seric #if OLD_NEWDB 83664373Seric (void) db->sync(db); 83764373Seric #else 83860585Seric (void) db->sync(db, 0); 83960585Seric 84064373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 84164284Seric map->map_mtime = st.st_mtime; 84264284Seric #endif 84364284Seric 84460089Seric map->map_db2 = (void *) db; 84560207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 84664718Seric if (!aliaswait(map, ".db", TRUE)) 84764718Seric return FALSE; 84856822Seric return TRUE; 84956822Seric } 85056822Seric 85156822Seric 85256822Seric /* 85356822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 85456822Seric */ 85556822Seric 85656822Seric char * 85760089Seric db_map_lookup(map, name, av, statp) 85856822Seric MAP *map; 85960089Seric char *name; 86056822Seric char **av; 86159084Seric int *statp; 86256822Seric { 86356822Seric DBT key, val; 86460422Seric register DB *db = (DB *) map->map_db2; 86560422Seric int st; 86660422Seric int saveerrno; 86764373Seric int fd; 86860089Seric char keybuf[MAXNAME + 1]; 86956822Seric 87060537Seric if (tTd(38, 20)) 87168350Seric printf("db_map_lookup(%s, %s)\n", 87268350Seric map->map_mname, name); 87360089Seric 87460089Seric key.size = strlen(name); 87560089Seric if (key.size > sizeof keybuf - 1) 87660089Seric key.size = sizeof keybuf - 1; 87760089Seric key.data = keybuf; 87860089Seric bcopy(name, keybuf, key.size + 1); 87960207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 88060089Seric makelower(keybuf); 88166843Seric #if !OLD_NEWDB 88264388Seric fd = db->fd(db); 88364388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 88464388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 88560422Seric #endif 88663753Seric st = 1; 88763753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 88863753Seric { 88963753Seric st = db->get(db, &key, &val, 0); 89063753Seric if (st == 0) 89163753Seric map->map_mflags &= ~MF_TRY1NULL; 89263753Seric } 89363753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 89463753Seric { 89563753Seric key.size++; 89663753Seric st = db->get(db, &key, &val, 0); 89763753Seric if (st == 0) 89863753Seric map->map_mflags &= ~MF_TRY0NULL; 89963753Seric } 90060422Seric saveerrno = errno; 90166843Seric #if !OLD_NEWDB 90264388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 90364373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 90460422Seric #endif 90560422Seric if (st != 0) 90660422Seric { 90760422Seric errno = saveerrno; 90860422Seric if (st < 0) 90960422Seric syserr("db_map_lookup: get (%s)", name); 91056822Seric return NULL; 91160422Seric } 91260207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 91363753Seric return map_rewrite(map, name, strlen(name), NULL); 91463753Seric else 91563753Seric return map_rewrite(map, val.data, val.size, av); 91656822Seric } 91756822Seric 91860089Seric 91960089Seric /* 92060089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 92156822Seric */ 92256822Seric 92360089Seric void 92460089Seric db_map_store(map, lhs, rhs) 92560089Seric register MAP *map; 92660089Seric char *lhs; 92760089Seric char *rhs; 92856822Seric { 92960089Seric int stat; 93060089Seric DBT key; 93160089Seric DBT data; 93260089Seric register DB *db = map->map_db2; 93356822Seric 93460537Seric if (tTd(38, 20)) 93568350Seric printf("db_map_store(%s, %s, %s)\n", 93668350Seric map->map_mname, lhs, rhs); 93760089Seric 93860089Seric key.size = strlen(lhs); 93960089Seric key.data = lhs; 94060089Seric 94160089Seric data.size = strlen(rhs); 94260089Seric data.data = rhs; 94360089Seric 94460207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 94556822Seric { 94660089Seric key.size++; 94760089Seric data.size++; 94860089Seric } 94956836Seric 95060089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 95160089Seric if (stat > 0) 95260089Seric { 953*68497Seric if (!bitset(MF_APPEND, map->map_mflags)) 954*68497Seric usrerr("050 Warning: duplicate alias name %s", lhs); 955*68497Seric else 956*68497Seric { 957*68497Seric static char *buf = NULL; 958*68497Seric static int bufsiz = 0; 959*68497Seric DBT old; 960*68497Seric 961*68497Seric old.data = db_map_lookup(map, key.data, NULL, &stat); 962*68497Seric if (old.data != NULL) 963*68497Seric { 964*68497Seric old.size = strlen(old.data); 965*68497Seric if (data.size + old.size + 2 > bufsiz) 966*68497Seric { 967*68497Seric if (buf != NULL) 968*68497Seric (void) free(buf); 969*68497Seric bufsiz = data.size + old.size + 2; 970*68497Seric buf = xalloc(bufsiz); 971*68497Seric } 972*68497Seric sprintf(buf, "%s,%s", data.data, old.data); 973*68497Seric data.size = data.size + old.size + 1; 974*68497Seric data.data = buf; 975*68497Seric if (tTd(38, 9)) 976*68497Seric printf("db_map_store append=%s\n", data.data); 977*68497Seric } 978*68497Seric } 97960089Seric stat = db->put(db, &key, &data, 0); 98060089Seric } 98160089Seric if (stat != 0) 98260089Seric syserr("readaliases: db put (%s)", lhs); 98360089Seric } 98456836Seric 98556847Seric 98660089Seric /* 98760089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 98860089Seric */ 98960089Seric 99060089Seric void 99160089Seric db_map_close(map) 99260089Seric MAP *map; 99360089Seric { 99460089Seric register DB *db = map->map_db2; 99560089Seric 99660537Seric if (tTd(38, 9)) 99768350Seric printf("db_map_close(%s, %s, %x)\n", 99868350Seric map->map_mname, map->map_file, map->map_mflags); 99960089Seric 100060207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 100158804Seric { 100260089Seric /* write out the distinguished alias */ 100360089Seric db_map_store(map, "@", "@"); 100458804Seric } 100558963Seric 100660089Seric if (db->close(db) != 0) 100760089Seric syserr("readaliases: db close failure"); 100856822Seric } 100957208Seric 101060089Seric #endif 101160089Seric /* 101260089Seric ** NIS Modules 101360089Seric */ 101460089Seric 101560089Seric # ifdef NIS 101660089Seric 101764369Seric # ifndef YPERR_BUSY 101864369Seric # define YPERR_BUSY 16 101964369Seric # endif 102064369Seric 102157208Seric /* 102260089Seric ** NIS_MAP_OPEN -- open DBM map 102357208Seric */ 102457208Seric 102557208Seric bool 102660089Seric nis_map_open(map, mode) 102757208Seric MAP *map; 102860089Seric int mode; 102957208Seric { 103057216Seric int yperr; 103160215Seric register char *p; 103260215Seric auto char *vp; 103360215Seric auto int vsize; 103457216Seric char *master; 103557216Seric 103660537Seric if (tTd(38, 2)) 103768350Seric printf("nis_map_open(%s, %s)\n", 103868350Seric map->map_mname, map->map_file); 103960089Seric 104060207Seric if (mode != O_RDONLY) 104160207Seric { 104264650Seric /* issue a pseudo-error message */ 104364650Seric #ifdef ENOSYS 104464650Seric errno = ENOSYS; 104564650Seric #else 104664650Seric # ifdef EFTYPE 104764650Seric errno = EFTYPE; 104864650Seric # else 104964650Seric errno = ENXIO; 105064650Seric # endif 105164650Seric #endif 105260207Seric return FALSE; 105360207Seric } 105460207Seric 105560089Seric p = strchr(map->map_file, '@'); 105660089Seric if (p != NULL) 105760089Seric { 105860089Seric *p++ = '\0'; 105960089Seric if (*p != '\0') 106060089Seric map->map_domain = p; 106160089Seric } 106260215Seric 106360089Seric if (*map->map_file == '\0') 106460089Seric map->map_file = "mail.aliases"; 106560089Seric 106666157Seric if (map->map_domain == NULL) 106766157Seric { 106866157Seric yperr = yp_get_default_domain(&map->map_domain); 106966157Seric if (yperr != 0) 107066157Seric { 107166744Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 107268350Seric syserr("421 NIS map %s specified, but NIS not running\n", 107366744Seric map->map_file); 107466157Seric return FALSE; 107566157Seric } 107666157Seric } 107766157Seric 107860215Seric /* check to see if this map actually exists */ 107960089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 108060089Seric &vp, &vsize); 108160537Seric if (tTd(38, 10)) 108260089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 108360089Seric map->map_domain, map->map_file, yperr_string(yperr)); 108460089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 108568350Seric { 108668350Seric if (!bitset(MF_ALIAS, map->map_mflags) || 108768350Seric aliaswait(map, NULL, TRUE)) 108868350Seric return TRUE; 108968350Seric } 109060215Seric 109160215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 109268350Seric syserr("421 Cannot bind to domain %s: %s", map->map_domain, 109360215Seric yperr_string(yperr)); 109460215Seric 109560089Seric return FALSE; 109660089Seric } 109760089Seric 109860089Seric 109960089Seric /* 110057208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 110157208Seric */ 110257208Seric 110357208Seric char * 110460089Seric nis_map_lookup(map, name, av, statp) 110557208Seric MAP *map; 110660089Seric char *name; 110757208Seric char **av; 110859084Seric int *statp; 110957208Seric { 111057208Seric char *vp; 111157642Seric auto int vsize; 111259274Seric int buflen; 111360215Seric int yperr; 111460089Seric char keybuf[MAXNAME + 1]; 111557208Seric 111660537Seric if (tTd(38, 20)) 111768350Seric printf("nis_map_lookup(%s, %s)\n", 111868350Seric map->map_mname, name); 111960089Seric 112060089Seric buflen = strlen(name); 112160089Seric if (buflen > sizeof keybuf - 1) 112260089Seric buflen = sizeof keybuf - 1; 112360089Seric bcopy(name, keybuf, buflen + 1); 112460207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 112560089Seric makelower(keybuf); 112663753Seric yperr = YPERR_KEY; 112763753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 112863753Seric { 112963753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 113063753Seric &vp, &vsize); 113163753Seric if (yperr == 0) 113263753Seric map->map_mflags &= ~MF_TRY1NULL; 113363753Seric } 113463753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 113563753Seric { 113659274Seric buflen++; 113763753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 113863753Seric &vp, &vsize); 113963753Seric if (yperr == 0) 114063753Seric map->map_mflags &= ~MF_TRY0NULL; 114163753Seric } 114260089Seric if (yperr != 0) 114360089Seric { 114460089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 114560215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 114657208Seric return NULL; 114760089Seric } 114860207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 114963753Seric return map_rewrite(map, name, strlen(name), NULL); 115063753Seric else 115163753Seric return map_rewrite(map, vp, vsize, av); 115257208Seric } 115357208Seric 115468350Seric #endif 115568350Seric /* 115668350Seric ** NISPLUS Modules 115768350Seric ** 115868350Seric ** This code donated by Sun Microsystems. 115968350Seric */ 116067848Seric 116168350Seric #ifdef NISPLUS 116268350Seric 116368350Seric #undef NIS /* symbol conflict in nis.h */ 116468350Seric #include <rpcsvc/nis.h> 116568350Seric #include <rpcsvc/nislib.h> 116668350Seric 116768350Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 116868350Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 116968350Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 117068350Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 117168350Seric 117267848Seric /* 117368350Seric ** NISPLUS_MAP_OPEN -- open nisplus table 117467848Seric */ 117567848Seric 117668350Seric bool 117768350Seric nisplus_map_open(map, mode) 117867848Seric MAP *map; 117968350Seric int mode; 118067848Seric { 118168350Seric register char *p; 118268350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 118368350Seric nis_result *res = NULL; 118468350Seric u_int objs_len; 118568350Seric nis_object *obj_ptr; 118668350Seric int retry_cnt, max_col, i; 118768350Seric 118868350Seric if (tTd(38, 2)) 118968350Seric printf("nisplus_map_open(%s, %s, %d)\n", 119068350Seric map->map_mname, map->map_file, mode); 119168350Seric 119268350Seric if (mode != O_RDONLY) 119368350Seric { 119468350Seric errno = ENODEV; 119568350Seric return FALSE; 119668350Seric } 119768350Seric 119868350Seric if (*map->map_file == '\0') 119968350Seric map->map_file = "mail_aliases.org_dir"; 120068350Seric 120168350Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 120268350Seric { 120368350Seric /* set default NISPLUS Domain to $m */ 120468350Seric extern char *nisplus_default_domain(); 120568350Seric 120668350Seric map->map_domain = newstr(nisplus_default_domain()); 120768350Seric if (tTd(38, 2)) 120868350Seric printf("nisplus_map_open(%s): using domain %s\n", 120968350Seric map->map_file, map->map_domain); 121068350Seric } 121168350Seric if (!PARTIAL_NAME(map->map_file)) 121268350Seric map->map_domain = newstr(""); 121368350Seric 121468350Seric /* check to see if this map actually exists */ 121568350Seric if (PARTIAL_NAME(map->map_file)) 121668350Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain); 121768350Seric else 121868350Seric strcpy(qbuf, map->map_file); 121968350Seric 122068350Seric retry_cnt = 0; 122168350Seric while (res == NULL || res->status != NIS_SUCCESS) 122268350Seric { 122368350Seric res = nis_lookup(qbuf, FOLLOW_LINKS); 122468350Seric switch (res->status) 122568350Seric { 122668350Seric case NIS_SUCCESS: 122768350Seric case NIS_TRYAGAIN: 122868350Seric case NIS_RPCERROR: 122968350Seric case NIS_NAMEUNREACHABLE: 123068350Seric break; 123168350Seric 123268350Seric default: /* all other nisplus errors */ 123368350Seric #if 0 123468350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 123568350Seric syserr("421 Cannot find table %s.%s: %s", 123668350Seric map->map_file, map->map_domain, 123768350Seric nis_sperrno(res->status)); 123868350Seric #endif 123968350Seric errno = EBADR; 124068350Seric return FALSE; 124168350Seric } 124268350Seric sleep(2); /* try not to overwhelm hosed server */ 124368350Seric if (retry_cnt++ > 4) 124468350Seric { 124568350Seric errno = EBADR; 124668350Seric return FALSE; 124768350Seric } 124868350Seric } 124968350Seric 125068350Seric if (NIS_RES_NUMOBJ(res) != 1 || 125168350Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 125268350Seric { 125368350Seric if (tTd(38, 10)) 125468350Seric printf("nisplus_map_open: %s is not a table\n", qbuf); 125568350Seric #if 0 125668350Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 125768350Seric syserr("421 %s.%s: %s is not a table", 125868350Seric map->map_file, map->map_domain, 125968350Seric nis_sperrno(res->status)); 126068350Seric #endif 126168350Seric errno = EBADR; 126268350Seric return FALSE; 126368350Seric } 126468350Seric /* default key column is column 0 */ 126568350Seric if (map->map_keycolnm == NULL) 126668350Seric map->map_keycolnm = newstr(COL_NAME(res,0)); 126768350Seric 126868350Seric max_col = COL_MAX(res); 126968350Seric 127068350Seric /* verify the key column exist */ 127168350Seric for (i=0; i< max_col; i++) 127268350Seric { 127368350Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 127468350Seric break; 127568350Seric } 127668350Seric if (i == max_col) 127768350Seric { 127868350Seric if (tTd(38, 2)) 127968350Seric printf("nisplus_map_open(%s): can not find key column %s\n", 128068350Seric map->map_file, map->map_keycolnm); 128168350Seric errno = EBADR; 128268350Seric return FALSE; 128368350Seric } 128468350Seric 128568350Seric /* default value column is the last column */ 128668350Seric if (map->map_valcolnm == NULL) 128768350Seric { 128868350Seric map->map_valcolno = max_col - 1; 128968350Seric return TRUE; 129068350Seric } 129168350Seric 129268350Seric for (i=0; i< max_col; i++) 129368350Seric { 129468350Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 129568350Seric { 129668350Seric map->map_valcolno = i; 129768350Seric return TRUE; 129868350Seric } 129968350Seric } 130068350Seric 130168350Seric if (tTd(38, 2)) 130268350Seric printf("nisplus_map_open(%s): can not find column %s\n", 130368350Seric map->map_file, map->map_keycolnm); 130468350Seric errno = EBADR; 130568350Seric return FALSE; 130667848Seric } 130767848Seric 130867848Seric 130967848Seric /* 131068350Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 131167848Seric */ 131267848Seric 131368350Seric char * 131468350Seric nisplus_map_lookup(map, name, av, statp) 131567848Seric MAP *map; 131668350Seric char *name; 131768350Seric char **av; 131868350Seric int *statp; 131967848Seric { 132068350Seric char *vp; 132168350Seric auto int vsize; 132268350Seric int buflen; 132368350Seric char search_key[MAXNAME + 1]; 132468350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN]; 132568350Seric nis_result *result; 132668350Seric 132768350Seric if (tTd(38, 20)) 132868350Seric printf("nisplus_map_lookup(%s, %s)\n", 132968350Seric map->map_mname, name); 133068350Seric 133168350Seric if (!bitset(MF_OPEN, map->map_mflags)) 133268350Seric { 133368350Seric if (nisplus_map_open(map, O_RDONLY)) 133468350Seric map->map_mflags |= MF_OPEN; 133568350Seric else 133668350Seric { 133768350Seric *statp = EX_UNAVAILABLE; 133868350Seric return NULL; 133968350Seric } 134068350Seric } 134168350Seric 134268350Seric buflen = strlen(name); 134368350Seric if (buflen > sizeof search_key - 1) 134468350Seric buflen = sizeof search_key - 1; 134568350Seric bcopy(name, search_key, buflen + 1); 134668350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 134768350Seric makelower(search_key); 134868350Seric 134968350Seric /* construct the query */ 135068350Seric if (PARTIAL_NAME(map->map_file)) 135168350Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm, 135268350Seric search_key, map->map_file, map->map_domain); 135368350Seric else 135468350Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm, 135568350Seric search_key, map->map_file); 135668350Seric 135768350Seric if (tTd(38, 20)) 135868350Seric printf("qbuf=%s\n", qbuf); 135968350Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 136068350Seric if (result->status == NIS_SUCCESS) 136168350Seric { 136268350Seric int count; 136368350Seric char *str; 136468350Seric 136568350Seric if ((count = NIS_RES_NUMOBJ(result)) != 1) 136668350Seric { 136768350Seric if (LogLevel > 10) 136868350Seric syslog(LOG_WARNING, 136968350Seric "%s:Lookup error, expected 1 entry, got (%d)", 137068350Seric map->map_file, count); 137168350Seric 137268350Seric /* ignore second entry */ 137368350Seric if (tTd(38, 20)) 137468350Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 137568350Seric name, count); 137668350Seric } 137768350Seric 137868350Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 137968350Seric /* set the length of the result */ 138068350Seric if (vp == NULL) 138168350Seric vp = ""; 138268350Seric vsize = strlen(vp); 138368350Seric if (tTd(38, 20)) 138468350Seric printf("nisplus_map_lookup(%s), found %s\n", 138568350Seric name, vp); 138668350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 138768350Seric str = map_rewrite(map, name, strlen(name), NULL); 138868350Seric else 138968350Seric str = map_rewrite(map, vp, vsize, av); 139068350Seric nis_freeresult(result); 139168350Seric #ifdef MAP_EXIT_STAT 139268350Seric *statp = EX_OK; 139368350Seric #endif 139468350Seric return str; 139568350Seric } 139668350Seric else 139768350Seric { 139868350Seric #ifdef MAP_EXIT_STAT 139968350Seric if (result->status == NIS_NOTFOUND) 140068350Seric *statp = EX_NOTFOUND; 140168350Seric else if (result->status == NIS_TRYAGAIN) 140268350Seric *statp = EX_TEMPFAIL; 140368350Seric else 140468350Seric { 140568350Seric *statp = EX_UNAVAILABLE; 140668350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 140768350Seric } 140868350Seric #else 140968350Seric if ((result->status != NIS_NOTFOUND) && 141068350Seric (result->status != NIS_TRYAGAIN)) 141168350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 141268350Seric #endif 141368350Seric } 141468350Seric if (tTd(38, 20)) 141568350Seric printf("nisplus_map_lookup(%s), failed\n", name); 141668350Seric nis_freeresult(result); 141768350Seric return NULL; 141867848Seric } 141967848Seric 142068350Seric 142168350Seric char * 142268350Seric nisplus_default_domain() 142368350Seric { 142468350Seric static char default_domain[MAXNAME] = ""; 142568350Seric char *p; 142668350Seric 142768350Seric if (default_domain[0] != '\0') 142868350Seric return(default_domain); 142968350Seric 143068458Seric p = nis_local_directory(); 143168350Seric strcpy(default_domain, p); 143268458Seric return default_domain; 143368350Seric } 143468350Seric 143568350Seric #endif /* NISPLUS */ 143667848Seric /* 143768350Seric ** HESIOD Modules 143868350Seric */ 143968350Seric 144068350Seric #ifdef HESIOD 144168350Seric 144268350Seric #include <hesiod.h> 144368350Seric 144468350Seric char * 144568350Seric hes_map_lookup(map, name, av, statp) 144668350Seric MAP *map; 144768350Seric char *name; 144868350Seric char **av; 144968350Seric int *statp; 145068350Seric { 145168350Seric char **hp; 145268350Seric char *retdata = NULL; 145368350Seric int i; 145468350Seric 145568350Seric if (tTd(38, 20)) 145668350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 145768350Seric 145868350Seric hp = hes_resolve(name, map->map_file); 145968350Seric if (hp == NULL) 146068350Seric return NULL; 146168350Seric 146268350Seric if (hp[0] != NULL) 146368350Seric { 146468350Seric if (tTd(38, 20)) 146568395Seric printf(" %d %s\n", i, hp[0]); 146668350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 146768350Seric retdata = map_rewrite(map, name, strlen(name), NULL); 146868350Seric else 146968350Seric retdata = map_rewrite(map, hp[0], strlen(hp[0]), av); 147068350Seric } 147168350Seric 147268350Seric for (i = 0; hp[i] != NULL; i++) 147368350Seric free(hp[i]); 147468350Seric free(hp); 147568350Seric return retdata; 147668350Seric } 147768350Seric 147868350Seric #endif 147968350Seric /* 148068350Seric ** NeXT NETINFO Modules 148168350Seric */ 148268350Seric 148368350Seric #ifdef NETINFO 148468350Seric 148568350Seric #define NETINFO_DEFAULT_DIR "/aliases" 148668350Seric #define NETINFO_DEFAULT_PROPERTY "members" 148768350Seric 148868350Seric 148968350Seric /* 149068350Seric ** NI_MAP_OPEN -- open NetInfo Aliases 149168350Seric */ 149268350Seric 149368350Seric bool 149468350Seric ni_map_open(map, mode) 149568350Seric MAP *map; 149668350Seric int mode; 149768350Seric { 149868350Seric char *p; 149968350Seric 150068350Seric if (tTd(38, 20)) 150168350Seric printf("ni_map_open: %s\n", map->map_file); 150268350Seric 150368350Seric if (*map->map_file == '\0') 150468350Seric map->map_file = NETINFO_DEFAULT_DIR; 150568350Seric 150668350Seric if (map->map_valcolnm == NULL) 150768350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 150868350Seric 150968350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 151068350Seric map->map_coldelim = ','; 151168350Seric 151268350Seric return TRUE; 151368350Seric } 151468350Seric 151568350Seric 151668350Seric /* 151768350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo 151868350Seric */ 151968350Seric 152068350Seric char * 152168350Seric ni_map_lookup(map, name, av, statp) 152268350Seric MAP *map; 152368350Seric char *name; 152468350Seric char **av; 152568350Seric int *statp; 152668350Seric { 152768350Seric char *res; 152868350Seric char *propval; 152968350Seric extern char *ni_propval(); 153068350Seric 153168350Seric if (tTd(38, 20)) 153268350Seric printf("ni_map_lookup(%s, %s)\n", 153368350Seric map->map_mname, name); 153468350Seric 153568350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name, 153668350Seric map->map_valcolnm, map->map_coldelim); 153768350Seric 153868350Seric if (propval == NULL) 153968350Seric return NULL; 154068350Seric 154168350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 154268350Seric res = map_rewrite(map, name, strlen(name), NULL); 154368350Seric else 154468350Seric res = map_rewrite(map, propval, strlen(propval), av); 154568350Seric free(propval); 154668350Seric return res; 154768350Seric } 154868350Seric 154968350Seric #endif 155068350Seric /* 155168350Seric ** TEXT (unindexed text file) Modules 155268350Seric ** 155368350Seric ** This code donated by Sun Microsystems. 155468350Seric */ 155568350Seric 155668350Seric 155768350Seric /* 155868350Seric ** TEXT_MAP_OPEN -- open text table 155968350Seric */ 156068350Seric 156168350Seric bool 156268350Seric text_map_open(map, mode) 156368350Seric MAP *map; 156468350Seric int mode; 156568350Seric { 156668350Seric struct stat sbuf; 156768350Seric 156868350Seric if (tTd(38, 2)) 156968350Seric printf("text_map_open(%s, %s, %d)\n", 157068350Seric map->map_mname, map->map_file, mode); 157168350Seric 157268350Seric if (mode != O_RDONLY) 157368350Seric { 157468350Seric errno = ENODEV; 157568350Seric return FALSE; 157668350Seric } 157768350Seric 157868350Seric if (*map->map_file == '\0') 157968350Seric { 158068350Seric if (tTd(38, 2)) 158168350Seric printf("text_map_open: file name required\n"); 158268350Seric return FALSE; 158368350Seric } 158468350Seric 158568350Seric if (map->map_file[0] != '/') 158668350Seric { 158768350Seric if (tTd(38, 2)) 158868350Seric printf("text_map_open(%s): file name must be fully qualified\n", 158968350Seric map->map_file); 159068350Seric return FALSE; 159168350Seric } 159268350Seric /* check to see if this map actually accessable */ 159368350Seric if (access(map->map_file, R_OK) <0) 159468350Seric return FALSE; 159568350Seric 159668350Seric /* check to see if this map actually exist */ 159768350Seric if (stat(map->map_file, &sbuf) <0) 159868350Seric { 159968350Seric if (tTd(38, 2)) 160068350Seric printf("text_map_open(%s): can not stat %s\n", 160168350Seric map->map_file, map->map_file); 160268350Seric return FALSE; 160368350Seric } 160468350Seric 160568350Seric if (!S_ISREG(sbuf.st_mode)) 160668350Seric { 160768350Seric if (tTd(38, 2)) 160868350Seric printf("text_map_open(%s): %s is not a file\n", 160968350Seric map->map_file, map->map_file); 161068350Seric return FALSE; 161168350Seric } 161268350Seric 161368350Seric if (map->map_keycolnm == NULL) 161468350Seric map->map_keycolno = 0; 161568350Seric else 161668350Seric { 161768350Seric if (!isdigit(*map->map_keycolnm)) 161868350Seric { 161968350Seric if (tTd(38, 2)) 162068350Seric printf("text_map_open(%s): -k should specify a number, not %s\n", 162168350Seric map->map_file, map->map_keycolnm); 162268350Seric return FALSE; 162368350Seric } 162468350Seric map->map_keycolno = atoi(map->map_keycolnm); 162568350Seric } 162668350Seric 162768350Seric if (map->map_valcolnm == NULL) 162868350Seric map->map_valcolno = 0; 162968350Seric else 163068350Seric { 163168350Seric if (!isdigit(*map->map_valcolnm)) 163268350Seric { 163368350Seric if (tTd(38, 2)) 163468350Seric printf("text_map_open(%s): -v should specify a number, not %s\n", 163568350Seric map->map_file, map->map_valcolnm); 163668350Seric return FALSE; 163768350Seric } 163868350Seric map->map_valcolno = atoi(map->map_valcolnm); 163968350Seric } 164068350Seric 164168350Seric if (map->map_coldelim == '\0') 164268350Seric map->map_coldelim = ':'; 164368350Seric 164468350Seric if (tTd(38, 2)) 164568350Seric { 164668350Seric printf("text_map_open(%s): delimiter = %c\n", 164768350Seric map->map_file, map->map_coldelim); 164868350Seric } 164968350Seric 165068350Seric return TRUE; 165168350Seric } 165268350Seric 165368350Seric 165468350Seric /* 165568350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 165668350Seric */ 165768350Seric 165868350Seric char * 165968350Seric text_map_lookup(map, name, av, statp) 166068350Seric MAP *map; 166168350Seric char *name; 166268350Seric char **av; 166368350Seric int *statp; 166468350Seric { 166568350Seric char *vp; 166668350Seric auto int vsize; 166768350Seric int buflen; 166868350Seric char search_key[MAXNAME + 1]; 166968350Seric char linebuf[MAXLINE]; 167068350Seric FILE *f; 167168350Seric char buf[MAXNAME+1]; 167268350Seric char delim; 167368350Seric int key_idx; 167468350Seric bool found_it; 167568350Seric extern char *get_column(); 167668350Seric 167768350Seric 167868350Seric found_it = FALSE; 167968350Seric if (tTd(38, 20)) 168068350Seric printf("text_map_lookup(%s)\n", name); 168168350Seric 168268350Seric buflen = strlen(name); 168368350Seric if (buflen > sizeof search_key - 1) 168468350Seric buflen = sizeof search_key - 1; 168568350Seric bcopy(name, search_key, buflen + 1); 168668350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 168768350Seric makelower(search_key); 168868350Seric 168968350Seric f = fopen(map->map_file, "r"); 169068350Seric if (f == NULL) 169168350Seric { 169268350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 169368350Seric *statp = EX_UNAVAILABLE; 169468350Seric return NULL; 169568350Seric } 169668350Seric key_idx = map->map_keycolno; 169768350Seric delim = map->map_coldelim; 169868350Seric while (fgets(linebuf, MAXLINE, f)) 169968350Seric { 170068350Seric char *lf; 170168350Seric if (linebuf[0] == '#') 170268350Seric continue; /* skip comment line */ 170368350Seric if (lf = strchr(linebuf, '\n')) 170468350Seric *lf = '\0'; 170568350Seric if (!strcasecmp(search_key, 170668350Seric get_column(linebuf, key_idx, delim, buf))) 170768350Seric { 170868350Seric found_it = TRUE; 170968350Seric break; 171068350Seric } 171168350Seric } 171268350Seric fclose(f); 171368350Seric if (!found_it) 171468350Seric { 171568350Seric #ifdef MAP_EXIT_STAT 171668350Seric *statp = EX_NOTFOUND; 171768350Seric #endif 171868350Seric return(NULL); 171968350Seric } 172068350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf); 172168350Seric vsize = strlen(vp); 172268350Seric #ifdef MAP_EXIT_STAT 172368350Seric *statp = EX_OK; 172468350Seric #endif 172568350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 172668350Seric return map_rewrite(map, name, strlen(name), NULL); 172768350Seric else 172868350Seric return map_rewrite(map, vp, vsize, av); 172968350Seric } 173068350Seric /* 173160089Seric ** STAB (Symbol Table) Modules 173260089Seric */ 173360089Seric 173460089Seric 173560089Seric /* 173660207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 173760089Seric */ 173860089Seric 173960089Seric char * 174061707Seric stab_map_lookup(map, name, av, pstat) 174160089Seric register MAP *map; 174260089Seric char *name; 174361707Seric char **av; 174461707Seric int *pstat; 174560089Seric { 174660089Seric register STAB *s; 174760089Seric 174860537Seric if (tTd(38, 20)) 174968350Seric printf("stab_lookup(%s, %s)\n", 175068350Seric map->map_mname, name); 175160089Seric 175260089Seric s = stab(name, ST_ALIAS, ST_FIND); 175360089Seric if (s != NULL) 175460089Seric return (s->s_alias); 175560089Seric return (NULL); 175660089Seric } 175760089Seric 175860089Seric 175960089Seric /* 176060207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 176160089Seric */ 176260089Seric 176360089Seric void 176460089Seric stab_map_store(map, lhs, rhs) 176560089Seric register MAP *map; 176660089Seric char *lhs; 176760089Seric char *rhs; 176860089Seric { 176960089Seric register STAB *s; 177060089Seric 177160089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 177260089Seric s->s_alias = newstr(rhs); 177360089Seric } 177460089Seric 177560089Seric 177660089Seric /* 177760207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 177860207Seric ** 177960207Seric ** This is a wierd case -- it is only intended as a fallback for 178060207Seric ** aliases. For this reason, opens for write (only during a 178160207Seric ** "newaliases") always fails, and opens for read open the 178260207Seric ** actual underlying text file instead of the database. 178360089Seric */ 178460089Seric 178560089Seric bool 178660089Seric stab_map_open(map, mode) 178760089Seric register MAP *map; 178860089Seric int mode; 178960089Seric { 179063835Seric FILE *af; 179164284Seric struct stat st; 179263835Seric 179360537Seric if (tTd(38, 2)) 179468350Seric printf("stab_map_open(%s, %s)\n", 179568350Seric map->map_mname, map->map_file); 179660089Seric 179760089Seric if (mode != O_RDONLY) 179860207Seric { 179960207Seric errno = ENODEV; 180060089Seric return FALSE; 180160207Seric } 180260089Seric 180363835Seric af = fopen(map->map_file, "r"); 180463835Seric if (af == NULL) 180563835Seric return FALSE; 180668350Seric readaliases(map, af, FALSE, FALSE); 180764284Seric 180864284Seric if (fstat(fileno(af), &st) >= 0) 180964284Seric map->map_mtime = st.st_mtime; 181063835Seric fclose(af); 181163835Seric 181260089Seric return TRUE; 181360089Seric } 181460089Seric /* 181560089Seric ** Implicit Modules 181656822Seric ** 181760089Seric ** Tries several types. For back compatibility of aliases. 181856822Seric */ 181956822Seric 182060089Seric 182160089Seric /* 182260207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 182360089Seric */ 182460089Seric 182560089Seric char * 182660089Seric impl_map_lookup(map, name, av, pstat) 182760089Seric MAP *map; 182860089Seric char *name; 182956822Seric char **av; 183060089Seric int *pstat; 183156822Seric { 183260537Seric if (tTd(38, 20)) 183368350Seric printf("impl_map_lookup(%s, %s)\n", 183468350Seric map->map_mname, name); 183556822Seric 183660089Seric #ifdef NEWDB 183760207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 183860089Seric return db_map_lookup(map, name, av, pstat); 183960089Seric #endif 184060089Seric #ifdef NDBM 184160207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 184260089Seric return ndbm_map_lookup(map, name, av, pstat); 184360089Seric #endif 184460089Seric return stab_map_lookup(map, name, av, pstat); 184560089Seric } 184660089Seric 184760089Seric /* 184860207Seric ** IMPL_MAP_STORE -- store in open databases 184960089Seric */ 185060089Seric 185160089Seric void 185260089Seric impl_map_store(map, lhs, rhs) 185360089Seric MAP *map; 185460089Seric char *lhs; 185560089Seric char *rhs; 185660089Seric { 185760089Seric #ifdef NEWDB 185860207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 185960089Seric db_map_store(map, lhs, rhs); 186060089Seric #endif 186160089Seric #ifdef NDBM 186260207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 186360089Seric ndbm_map_store(map, lhs, rhs); 186460089Seric #endif 186560089Seric stab_map_store(map, lhs, rhs); 186660089Seric } 186760089Seric 186860089Seric /* 186960089Seric ** IMPL_MAP_OPEN -- implicit database open 187060089Seric */ 187160089Seric 187260089Seric bool 187360089Seric impl_map_open(map, mode) 187460089Seric MAP *map; 187560089Seric int mode; 187660089Seric { 187760089Seric struct stat stb; 187860089Seric 187960537Seric if (tTd(38, 2)) 188068350Seric printf("impl_map_open(%s, %s, %d)\n", 188168350Seric map->map_mname, map->map_file, mode); 188260089Seric 188360089Seric if (stat(map->map_file, &stb) < 0) 188456822Seric { 188560089Seric /* no alias file at all */ 188664718Seric if (tTd(38, 3)) 188764718Seric printf("no map file\n"); 188860089Seric return FALSE; 188956822Seric } 189056822Seric 189160089Seric #ifdef NEWDB 189260207Seric map->map_mflags |= MF_IMPL_HASH; 189360089Seric if (hash_map_open(map, mode)) 189456822Seric { 189564250Seric #if defined(NDBM) && defined(NIS) 189660561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 189760207Seric #endif 189860207Seric return TRUE; 189960089Seric } 190060207Seric else 190160207Seric map->map_mflags &= ~MF_IMPL_HASH; 190260089Seric #endif 190360089Seric #ifdef NDBM 190460207Seric map->map_mflags |= MF_IMPL_NDBM; 190560089Seric if (ndbm_map_open(map, mode)) 190660089Seric { 190760089Seric return TRUE; 190860089Seric } 190960207Seric else 191060207Seric map->map_mflags &= ~MF_IMPL_NDBM; 191160089Seric #endif 191256822Seric 191364650Seric #if defined(NEWDB) || defined(NDBM) 191460089Seric if (Verbose) 191560089Seric message("WARNING: cannot open alias database %s", map->map_file); 191664964Seric #else 191764964Seric if (mode != O_RDONLY) 191864964Seric usrerr("Cannot rebuild aliases: no database format defined"); 191960207Seric #endif 192060089Seric 192160207Seric return stab_map_open(map, mode); 192256822Seric } 192360089Seric 192460207Seric 192560089Seric /* 192660207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 192760089Seric */ 192860089Seric 192960089Seric void 193060207Seric impl_map_close(map) 193160089Seric MAP *map; 193260089Seric { 193368350Seric if (tTd(38, 20)) 193468350Seric printf("impl_map_close(%s, %s, %x)\n", 193568350Seric map->map_mname, map->map_file, map->map_mflags); 193660089Seric #ifdef NEWDB 193760207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 193860089Seric { 193960207Seric db_map_close(map); 194060207Seric map->map_mflags &= ~MF_IMPL_HASH; 194160089Seric } 194260089Seric #endif 194360089Seric 194460089Seric #ifdef NDBM 194560207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 194660089Seric { 194760207Seric ndbm_map_close(map); 194860207Seric map->map_mflags &= ~MF_IMPL_NDBM; 194960089Seric } 195060089Seric #endif 195160089Seric } 195260207Seric /* 195368350Seric ** User map class. 195468350Seric ** 195568350Seric ** Provides access to the system password file. 195668350Seric */ 195768350Seric 195868350Seric /* 195968350Seric ** USER_MAP_OPEN -- open user map 196068350Seric ** 196168350Seric ** Really just binds field names to field numbers. 196268350Seric */ 196368350Seric 196468350Seric bool 196568350Seric user_map_open(map, mode) 196668350Seric MAP *map; 196768350Seric int mode; 196868350Seric { 196968350Seric if (tTd(38, 2)) 197068350Seric printf("user_map_open(%s)\n", map->map_mname); 197168350Seric 197268350Seric if (mode != O_RDONLY) 197368350Seric { 197468350Seric /* issue a pseudo-error message */ 197568350Seric #ifdef ENOSYS 197668350Seric errno = ENOSYS; 197768350Seric #else 197868350Seric # ifdef EFTYPE 197968350Seric errno = EFTYPE; 198068350Seric # else 198168350Seric errno = ENXIO; 198268350Seric # endif 198368350Seric #endif 198468350Seric return FALSE; 198568350Seric } 198668350Seric if (map->map_valcolnm == NULL) 198768350Seric /* nothing */ ; 198868350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 198968350Seric map->map_valcolno = 1; 199068350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 199168350Seric map->map_valcolno = 2; 199268350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 199368350Seric map->map_valcolno = 3; 199468350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 199568350Seric map->map_valcolno = 4; 199668350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 199768350Seric map->map_valcolno = 5; 199868350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 199968350Seric map->map_valcolno = 6; 200068350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 200168350Seric map->map_valcolno = 7; 200268350Seric else 200368350Seric { 200468350Seric syserr("User map %s: unknown column name %s", 200568350Seric map->map_mname, map->map_valcolnm); 200668350Seric return FALSE; 200768350Seric } 200868350Seric return TRUE; 200968350Seric } 201068350Seric 201168350Seric 201268350Seric /* 201368350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 201468350Seric */ 201568350Seric 201668350Seric #include <pwd.h> 201768350Seric 201868350Seric char * 201968350Seric user_map_lookup(map, key, av, statp) 202068350Seric MAP *map; 202168350Seric char *key; 202268350Seric char **av; 202368350Seric int *statp; 202468350Seric { 202568350Seric struct passwd *pw; 202668350Seric 202768350Seric if (tTd(38, 20)) 202868350Seric printf("user_map_lookup(%s, %s)\n", 202968350Seric map->map_mname, key); 203068350Seric 203168350Seric pw = getpwnam(key); 203268350Seric if (pw == NULL) 203368350Seric return NULL; 203468350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 203568350Seric return map_rewrite(map, key, strlen(key), NULL); 203668350Seric else 203768350Seric { 203868433Seric char *rwval = NULL; 203968350Seric char buf[30]; 204068350Seric 204168350Seric switch (map->map_valcolno) 204268350Seric { 204368350Seric case 0: 204468350Seric case 1: 204568350Seric rwval = pw->pw_name; 204668350Seric break; 204768350Seric 204868350Seric case 2: 204968350Seric rwval = pw->pw_passwd; 205068350Seric break; 205168350Seric 205268350Seric case 3: 205368350Seric sprintf(buf, "%d", pw->pw_uid); 205468350Seric rwval = buf; 205568350Seric break; 205668350Seric 205768350Seric case 4: 205868350Seric sprintf(buf, "%d", pw->pw_gid); 205968350Seric rwval = buf; 206068350Seric break; 206168350Seric 206268350Seric case 5: 206368350Seric rwval = pw->pw_gecos; 206468350Seric break; 206568350Seric 206668350Seric case 6: 206768350Seric rwval = pw->pw_dir; 206868350Seric break; 206968350Seric 207068350Seric case 7: 207168350Seric rwval = pw->pw_shell; 207268350Seric break; 207368350Seric } 207468350Seric return map_rewrite(map, rwval, strlen(rwval), av); 207568350Seric } 207668350Seric } 207768350Seric /* 207868350Seric ** BESTMX -- find the best MX for a name 207968350Seric ** 208068350Seric ** This is really a hack, but I don't see any obvious way 208168350Seric ** to generalize it at the moment. 208268350Seric */ 208368350Seric 208468350Seric #if NAMED_BIND 208568350Seric 208668350Seric char * 208768350Seric bestmx_map_lookup(map, name, av, statp) 208868350Seric MAP *map; 208968350Seric char *name; 209068350Seric char **av; 209168350Seric int *statp; 209268350Seric { 209368350Seric int nmx; 209468350Seric auto int rcode; 209568350Seric char *mxhosts[MAXMXHOSTS + 1]; 209668350Seric 209768350Seric nmx = getmxrr(name, mxhosts, FALSE, &rcode); 209868350Seric if (nmx <= 0) 209968350Seric return NULL; 210068350Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 210168350Seric return map_rewrite(map, name, strlen(name), NULL); 210268350Seric else 210368350Seric return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 210468350Seric } 210568350Seric 210668350Seric #endif 210768350Seric /* 210868350Seric ** Sequenced map type. 210968350Seric ** 211068350Seric ** Tries each map in order until something matches, much like 211168350Seric ** implicit. Stores go to the first map in the list that can 211268350Seric ** support storing. 211368350Seric ** 211468350Seric ** This is slightly unusual in that there are two interfaces. 211568350Seric ** The "sequence" interface lets you stack maps arbitrarily. 211668350Seric ** The "switch" interface builds a sequence map by looking 211768350Seric ** at a system-dependent configuration file such as 211868350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 211968350Seric ** 212068350Seric ** We don't need an explicit open, since all maps are 212168350Seric ** opened during startup, including underlying maps. 212268350Seric */ 212368350Seric 212468350Seric /* 212568350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 212668350Seric */ 212768350Seric 212868350Seric bool 212968350Seric seq_map_parse(map, ap) 213068350Seric MAP *map; 213168350Seric char *ap; 213268350Seric { 213368350Seric int maxmap; 213468350Seric 213568350Seric if (tTd(38, 2)) 213668350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 213768350Seric maxmap = 0; 213868350Seric while (*ap != '\0') 213968350Seric { 214068350Seric register char *p; 214168350Seric STAB *s; 214268350Seric 214368350Seric /* find beginning of map name */ 214468350Seric while (isascii(*ap) && isspace(*ap)) 214568350Seric ap++; 214668350Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 214768350Seric continue; 214868350Seric if (*p != '\0') 214968350Seric *p++ = '\0'; 215068350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 215168350Seric p++; 215268350Seric if (*ap == '\0') 215368350Seric { 215468350Seric ap = p; 215568350Seric continue; 215668350Seric } 215768350Seric s = stab(ap, ST_MAP, ST_FIND); 215868350Seric if (s == NULL) 215968350Seric { 216068350Seric syserr("Sequence map %s: unknown member map %s", 216168350Seric map->map_mname, ap); 216268350Seric } 216368350Seric else if (maxmap == MAXMAPSTACK) 216468350Seric { 216568350Seric syserr("Sequence map %s: too many member maps (%d max)", 216668350Seric map->map_mname, MAXMAPSTACK); 216768350Seric maxmap++; 216868350Seric } 216968350Seric else if (maxmap < MAXMAPSTACK) 217068350Seric { 217168350Seric map->map_stack[maxmap++] = &s->s_map; 217268350Seric } 217368350Seric ap = p; 217468350Seric } 217568350Seric return TRUE; 217668350Seric } 217768350Seric 217868350Seric 217968350Seric /* 218068350Seric ** SWITCH_MAP_OPEN -- open a switched map 218168350Seric ** 218268350Seric ** This looks at the system-dependent configuration and builds 218368350Seric ** a sequence map that does the same thing. 218468350Seric ** 218568350Seric ** Every system must define a switch_map_find routine in conf.c 218668350Seric ** that will return the list of service types associated with a 218768350Seric ** given service class. 218868350Seric */ 218968350Seric 219068350Seric bool 219168350Seric switch_map_open(map, mode) 219268350Seric MAP *map; 219368350Seric int mode; 219468350Seric { 219568350Seric int mapno; 219668350Seric int nmaps; 219768350Seric char *maptype[MAXMAPSTACK]; 219868350Seric 219968350Seric if (tTd(38, 2)) 220068350Seric printf("switch_map_open(%s, %s, %d)\n", 220168350Seric map->map_mname, map->map_file, mode); 220268350Seric 220368350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return); 220468350Seric if (tTd(38, 19)) 220568350Seric { 220668350Seric printf("\tswitch_map_find => %d\n", nmaps); 220768350Seric for (mapno = 0; mapno < nmaps; mapno++) 220868350Seric printf("\t\t%s\n", maptype[mapno]); 220968350Seric } 221068350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK) 221168350Seric return FALSE; 221268350Seric 221368350Seric for (mapno = 0; mapno < nmaps; mapno++) 221468350Seric { 221568350Seric register STAB *s; 221668350Seric char nbuf[MAXNAME + 1]; 221768350Seric 221868350Seric if (maptype[mapno] == NULL) 221968350Seric continue; 222068350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]); 222168350Seric s = stab(nbuf, ST_MAP, ST_FIND); 222268350Seric if (s == NULL) 222368350Seric { 222468350Seric syserr("Switch map %s: unknown member map %s", 222568350Seric map->map_mname, nbuf); 222668350Seric } 222768350Seric else 222868350Seric { 222968350Seric map->map_stack[mapno] = &s->s_map; 223068350Seric if (tTd(38, 4)) 223168350Seric printf("\tmap_stack[%d] = %s:%s\n", 223268350Seric mapno, s->s_map.map_class->map_cname, 223368350Seric nbuf); 223468350Seric } 223568350Seric } 223668350Seric return TRUE; 223768350Seric } 223868350Seric 223968350Seric 224068350Seric /* 224168350Seric ** SEQ_MAP_CLOSE -- close all underlying maps 224268350Seric */ 224368350Seric 224468350Seric seq_map_close(map) 224568350Seric MAP *map; 224668350Seric { 224768350Seric int mapno; 224868350Seric 224968350Seric if (tTd(38, 20)) 225068350Seric printf("seq_map_close(%s)\n", map->map_mname); 225168350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 225268350Seric { 225368350Seric MAP *mm = map->map_stack[mapno]; 225468350Seric 225568350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 225668350Seric continue; 225768350Seric mm->map_class->map_close(mm); 225868350Seric } 225968350Seric } 226068350Seric 226168350Seric 226268350Seric /* 226368350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 226468350Seric */ 226568350Seric 226668350Seric char * 226768350Seric seq_map_lookup(map, key, args, pstat) 226868350Seric MAP *map; 226968350Seric char *key; 227068350Seric char **args; 227168350Seric int *pstat; 227268350Seric { 227368350Seric int mapno; 227468350Seric int mapbit = 0x01; 227568350Seric 227668350Seric if (tTd(38, 20)) 227768350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 227868350Seric 227968350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 228068350Seric { 228168350Seric MAP *mm = map->map_stack[mapno]; 228268350Seric int stat = 0; 228368350Seric char *rv; 228468350Seric 228568350Seric if (mm == NULL) 228668350Seric continue; 228768350Seric if (!bitset(MF_OPEN, mm->map_mflags)) 228868350Seric { 228968350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 229068350Seric { 229168350Seric *pstat = EX_UNAVAILABLE; 229268350Seric return NULL; 229368350Seric } 229468350Seric continue; 229568350Seric } 229668350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 229768350Seric if (rv != NULL) 229868350Seric return rv; 229968350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 230068350Seric return NULL; 230168350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 230268350Seric { 230368350Seric *pstat = stat; 230468350Seric return NULL; 230568350Seric } 230668350Seric } 230768350Seric return NULL; 230868350Seric } 230968350Seric 231068350Seric 231168350Seric /* 231268350Seric ** SEQ_MAP_STORE -- sequenced map store 231368350Seric */ 231468350Seric 231568350Seric void 231668350Seric seq_map_store(map, key, val) 231768350Seric MAP *map; 231868350Seric char *key; 231968350Seric char *val; 232068350Seric { 232168350Seric int mapno; 232268350Seric 232368350Seric if (tTd(38, 12)) 232468350Seric printf("seq_map_store(%s, %s, %s)\n", 232568350Seric map->map_mname, key, val); 232668350Seric 232768350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 232868350Seric { 232968350Seric MAP *mm = map->map_stack[mapno]; 233068350Seric 233168350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 233268350Seric continue; 233368350Seric 233468350Seric mm->map_class->map_store(mm, key, val); 233568350Seric return; 233668350Seric } 233768350Seric syserr("seq_map_store(%s, %s, %s): no writable map", 233868350Seric map->map_mname, key, val); 233968350Seric } 234068350Seric /* 234160207Seric ** NULL stubs 234260089Seric */ 234360089Seric 234460207Seric bool 234560207Seric null_map_open(map, mode) 234660089Seric MAP *map; 234760207Seric int mode; 234860089Seric { 234960207Seric return TRUE; 235060089Seric } 235160089Seric 235260207Seric void 235360207Seric null_map_close(map) 235460207Seric MAP *map; 235560089Seric { 235660207Seric return; 235760207Seric } 235860089Seric 235960207Seric void 236060207Seric null_map_store(map, key, val) 236160207Seric MAP *map; 236260207Seric char *key; 236360207Seric char *val; 236460089Seric { 236560207Seric return; 236660089Seric } 236768350Seric 236868350Seric 236968350Seric /* 237068350Seric ** BOGUS stubs 237168350Seric */ 237268350Seric 237368350Seric char * 237468350Seric bogus_map_lookup(map, key, args, pstat) 237568350Seric MAP *map; 237668350Seric char *key; 237768350Seric char **args; 237868350Seric int *pstat; 237968350Seric { 238068350Seric *pstat = EX_TEMPFAIL; 238168350Seric return NULL; 238268350Seric } 238368350Seric 238468350Seric MAPCLASS BogusMapClass = 238568350Seric { 238668350Seric "bogus-map", NULL, 0, 238768350Seric NULL, bogus_map_lookup, null_map_store, 238868350Seric null_map_open, null_map_close, 238968350Seric }; 2390