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*67726Seric static char sccsid[] = "@(#)map.c 8.29 (Berkeley) 08/21/94"; 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 11860089Seric case 'a': 11960089Seric map->map_app = ++p; 12060089Seric break; 121*67726Seric 122*67726Seric case 'k': 123*67726Seric while (isascii(*++p) && isspace(*p)) 124*67726Seric continue; 125*67726Seric map->map_keycolnm = p; 126*67726Seric break; 127*67726Seric 128*67726Seric case 'v': 129*67726Seric while (isascii(*++p) && isspace(*p)) 130*67726Seric continue; 131*67726Seric map->map_valcolnm = p; 132*67726Seric break; 133*67726Seric 134*67726Seric case 'z': 135*67726Seric if (*++p != '\\') 136*67726Seric map->map_coldelim = *p; 137*67726Seric else 138*67726Seric { 139*67726Seric switch (*++p) 140*67726Seric { 141*67726Seric case 'n': 142*67726Seric map->map_coldelim = '\n'; 143*67726Seric break; 144*67726Seric 145*67726Seric case 't': 146*67726Seric map->map_coldelim = '\t'; 147*67726Seric break; 148*67726Seric 149*67726Seric default: 150*67726Seric map->map_coldelim = '\\'; 151*67726Seric } 152*67726Seric } 153*67726Seric break; 15460089Seric } 15560089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 15660089Seric p++; 15760089Seric if (*p != '\0') 15860089Seric *p++ = '\0'; 15960089Seric } 16060089Seric if (map->map_app != NULL) 16160089Seric map->map_app = newstr(map->map_app); 162*67726Seric if (map->map_keycolnm != NULL) 163*67726Seric map->map_keycolnm = newstr(map->map_keycolnm); 164*67726Seric if (map->map_valcolnm != NULL) 165*67726Seric map->map_valcolnm = newstr(map->map_valcolnm); 16660089Seric 16760089Seric if (*p != '\0') 16860089Seric { 16960089Seric map->map_file = p; 17060089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 17160089Seric p++; 17260089Seric if (*p != '\0') 17360089Seric *p++ = '\0'; 17460089Seric map->map_file = newstr(map->map_file); 17560089Seric } 17660089Seric 17760089Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 17860089Seric p++; 17960089Seric if (*p != '\0') 18060089Seric map->map_rebuild = newstr(p); 18160089Seric 18256822Seric if (map->map_file == NULL) 18357208Seric { 18460089Seric syserr("No file name for %s map %s", 18560089Seric map->map_class->map_cname, map->map_mname); 18656822Seric return FALSE; 18757208Seric } 18860089Seric return TRUE; 18960089Seric } 19060089Seric /* 19160089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 19260089Seric ** 19360089Seric ** It also adds the map_app string. It can be used as a utility 19460089Seric ** in the map_lookup method. 19560089Seric ** 19660089Seric ** Parameters: 19760089Seric ** map -- the map that causes this. 19860089Seric ** s -- the string to rewrite, NOT necessarily null terminated. 19960089Seric ** slen -- the length of s. 20060089Seric ** av -- arguments to interpolate into buf. 20160089Seric ** 20260089Seric ** Returns: 20360089Seric ** Pointer to rewritten result. 20460089Seric ** 20560089Seric ** Side Effects: 20660089Seric ** none. 20760089Seric */ 20860089Seric 20960492Seric struct rwbuf 21060492Seric { 21160492Seric int rwb_len; /* size of buffer */ 21260492Seric char *rwb_buf; /* ptr to buffer */ 21360492Seric }; 21460492Seric 21560492Seric struct rwbuf RwBufs[2]; /* buffers for rewriting output */ 21660492Seric 21760089Seric char * 21860089Seric map_rewrite(map, s, slen, av) 21960089Seric register MAP *map; 22060089Seric register char *s; 22160089Seric int slen; 22260089Seric char **av; 22360089Seric { 22460089Seric register char *bp; 22560089Seric register char c; 22660089Seric char **avp; 22760089Seric register char *ap; 22860492Seric register struct rwbuf *rwb; 22960089Seric int i; 23060089Seric int len; 23160089Seric 23260537Seric if (tTd(39, 1)) 23360089Seric { 23460256Seric printf("map_rewrite(%.*s), av =", slen, s); 23560256Seric if (av == NULL) 23660256Seric printf(" (nullv)"); 23760256Seric else 23860256Seric { 23960256Seric for (avp = av; *avp != NULL; avp++) 24060256Seric printf("\n\t%s", *avp); 24160256Seric } 24260256Seric printf("\n"); 24360089Seric } 24460089Seric 24560492Seric rwb = RwBufs; 24660492Seric if (av == NULL) 24760492Seric rwb++; 24860492Seric 24960089Seric /* count expected size of output (can safely overestimate) */ 25060089Seric i = len = slen; 25160089Seric if (av != NULL) 25260089Seric { 25360089Seric bp = s; 25460089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 25560089Seric { 25660089Seric if (c != '%') 25760089Seric continue; 25860089Seric if (--i < 0) 25960089Seric break; 26060089Seric c = *bp++; 26160089Seric if (!(isascii(c) && isdigit(c))) 26260089Seric continue; 26363937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 26460089Seric continue; 26560089Seric if (*avp == NULL) 26660089Seric continue; 26760089Seric len += strlen(*avp); 26860089Seric } 26960089Seric } 27060089Seric if (map->map_app != NULL) 27160089Seric len += strlen(map->map_app); 27260492Seric if (rwb->rwb_len < ++len) 27360089Seric { 27460089Seric /* need to malloc additional space */ 27560492Seric rwb->rwb_len = len; 27660492Seric if (rwb->rwb_buf != NULL) 27760492Seric free(rwb->rwb_buf); 27860492Seric rwb->rwb_buf = xalloc(rwb->rwb_len); 27960089Seric } 28060089Seric 28160492Seric bp = rwb->rwb_buf; 28260089Seric if (av == NULL) 28360089Seric { 28460089Seric bcopy(s, bp, slen); 28560089Seric bp += slen; 28660089Seric } 28760089Seric else 28860089Seric { 28960089Seric while (--slen >= 0 && (c = *s++) != '\0') 29060089Seric { 29160089Seric if (c != '%') 29260089Seric { 29360089Seric pushc: 29460089Seric *bp++ = c; 29560089Seric continue; 29660089Seric } 29760089Seric if (--slen < 0 || (c = *s++) == '\0') 29860089Seric c = '%'; 29960089Seric if (c == '%') 30060089Seric goto pushc; 30160089Seric if (!(isascii(c) && isdigit(c))) 30260089Seric { 30360089Seric *bp++ = '%'; 30460089Seric goto pushc; 30560089Seric } 30663937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++) 30760089Seric continue; 30860089Seric if (*avp == NULL) 30960089Seric continue; 31060089Seric 31160089Seric /* transliterate argument into output string */ 31260089Seric for (ap = *avp; (c = *ap++) != '\0'; ) 31360089Seric *bp++ = c; 31460089Seric } 31560089Seric } 31660089Seric if (map->map_app != NULL) 31760089Seric strcpy(bp, map->map_app); 31860089Seric else 31960089Seric *bp = '\0'; 32060537Seric if (tTd(39, 1)) 32160492Seric printf("map_rewrite => %s\n", rwb->rwb_buf); 32260492Seric return rwb->rwb_buf; 32360089Seric } 32460089Seric /* 32560537Seric ** INITMAPS -- initialize for aliasing 32660537Seric ** 32760537Seric ** Parameters: 32860537Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 32960537Seric ** e -- current envelope. 33060537Seric ** 33160537Seric ** Returns: 33260537Seric ** none. 33360537Seric ** 33460537Seric ** Side Effects: 33560537Seric ** initializes aliases: 33660537Seric ** if NDBM: opens the database. 33760537Seric ** if ~NDBM: reads the aliases into the symbol table. 33860537Seric */ 33960537Seric 34060537Seric initmaps(rebuild, e) 34160537Seric bool rebuild; 34260537Seric register ENVELOPE *e; 34360537Seric { 34460537Seric extern void map_init(); 34560537Seric 34664671Seric #ifdef XDEBUG 34764671Seric checkfd012("entering initmaps"); 34864671Seric #endif 34960537Seric CurEnv = e; 35065085Seric if (rebuild) 35165085Seric { 35265085Seric stabapply(map_init, 1); 35365085Seric stabapply(map_init, 2); 35465085Seric } 35565085Seric else 35665085Seric { 35765085Seric stabapply(map_init, 0); 35865085Seric } 35964671Seric #ifdef XDEBUG 36064671Seric checkfd012("exiting initmaps"); 36164671Seric #endif 36260537Seric } 36360537Seric 36460537Seric void 36560537Seric map_init(s, rebuild) 36660537Seric register STAB *s; 36760537Seric int rebuild; 36860537Seric { 36960537Seric register MAP *map; 37060537Seric 37160537Seric /* has to be a map */ 37260537Seric if (s->s_type != ST_MAP) 37360537Seric return; 37460537Seric 37560537Seric map = &s->s_map; 37660537Seric if (!bitset(MF_VALID, map->map_mflags)) 37760537Seric return; 37860537Seric 37960537Seric if (tTd(38, 2)) 380*67726Seric printf("map_init(%s:%s, %s, %d)\n", 38164690Seric map->map_class->map_cname == NULL ? "NULL" : 38264690Seric map->map_class->map_cname, 383*67726Seric map->map_mname == NULL ? "NULL" : map->map_mname, 38465085Seric map->map_file == NULL ? "NULL" : map->map_file, 38565085Seric rebuild); 38660537Seric 38765085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && 38865085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) 38965085Seric { 39065085Seric if (tTd(38, 3)) 39165085Seric printf("\twrong pass\n"); 39265085Seric return; 39365085Seric } 39465085Seric 39560537Seric /* if already open, close it (for nested open) */ 39660537Seric if (bitset(MF_OPEN, map->map_mflags)) 39760537Seric { 39860537Seric map->map_class->map_close(map); 39960537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 40060537Seric } 40160537Seric 40265085Seric if (rebuild == 2) 40360537Seric { 40465085Seric rebuildaliases(map, FALSE); 40560537Seric } 40660537Seric else 40760537Seric { 40860537Seric if (map->map_class->map_open(map, O_RDONLY)) 40960537Seric { 41060537Seric if (tTd(38, 4)) 411*67726Seric printf("\t%s:%s %s: valid\n", 41264690Seric map->map_class->map_cname == NULL ? "NULL" : 41364690Seric map->map_class->map_cname, 414*67726Seric map->map_mname == NULL ? "NULL" : 415*67726Seric map->map_mname, 41664690Seric map->map_file == NULL ? "NULL" : 41764690Seric map->map_file); 41860537Seric map->map_mflags |= MF_OPEN; 41960537Seric } 42060537Seric else if (tTd(38, 4)) 421*67726Seric printf("\t%s:%s %s: invalid: %s\n", 42264690Seric map->map_class->map_cname == NULL ? "NULL" : 42364690Seric map->map_class->map_cname, 424*67726Seric map->map_mname == NULL ? "NULL" : 425*67726Seric map->map_mname, 42664690Seric map->map_file == NULL ? "NULL" : 42764690Seric map->map_file, 42860537Seric errstring(errno)); 42960537Seric } 43060537Seric } 43160537Seric /* 43260089Seric ** NDBM modules 43360089Seric */ 43460089Seric 43560089Seric #ifdef NDBM 43660089Seric 43760089Seric /* 43860089Seric ** DBM_MAP_OPEN -- DBM-style map open 43960089Seric */ 44060089Seric 44160089Seric bool 44260089Seric ndbm_map_open(map, mode) 44360089Seric MAP *map; 44460089Seric int mode; 44560089Seric { 44664284Seric register DBM *dbm; 44764284Seric struct stat st; 44860089Seric 44960537Seric if (tTd(38, 2)) 450*67726Seric printf("ndbm_map_open(%s, %s, %d)\n", 451*67726Seric map->map_mname, map->map_file, mode); 45260089Seric 45360207Seric if (mode == O_RDWR) 45460207Seric mode |= O_CREAT|O_TRUNC; 45560207Seric 45660089Seric /* open the database */ 45760089Seric dbm = dbm_open(map->map_file, mode, DBMMODE); 45856822Seric if (dbm == NULL) 45956822Seric { 46064718Seric #ifdef MAYBENEXTRELEASE 46164718Seric if (aliaswait(map, ".pag", FALSE)) 46264718Seric return TRUE; 46364718Seric #endif 46460207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 46556836Seric syserr("Cannot open DBM database %s", map->map_file); 46656822Seric return FALSE; 46756822Seric } 46860089Seric map->map_db1 = (void *) dbm; 46964964Seric if (mode == O_RDONLY) 47064964Seric { 47164964Seric if (bitset(MF_ALIAS, map->map_mflags) && 47264964Seric !aliaswait(map, ".pag", TRUE)) 47364718Seric return FALSE; 47464964Seric } 47564964Seric else 47664964Seric { 47764964Seric int fd; 47864964Seric 47964964Seric /* exclusive lock for duration of rebuild */ 48064964Seric fd = dbm_dirfno((DBM *) map->map_db1); 48164964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && 48264964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX)) 48364964Seric map->map_mflags |= MF_LOCKED; 48464964Seric } 48564718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) 48664284Seric map->map_mtime = st.st_mtime; 48756822Seric return TRUE; 48856822Seric } 48960089Seric 49060089Seric 49160089Seric /* 49256822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 49356822Seric */ 49456822Seric 49556822Seric char * 49660089Seric ndbm_map_lookup(map, name, av, statp) 49756822Seric MAP *map; 49860089Seric char *name; 49956822Seric char **av; 50059084Seric int *statp; 50156822Seric { 50256822Seric datum key, val; 50364373Seric int fd; 50460089Seric char keybuf[MAXNAME + 1]; 50556822Seric 50660537Seric if (tTd(38, 20)) 507*67726Seric printf("ndbm_map_lookup(%s, %s)\n", 508*67726Seric map->map_mname, name); 50960089Seric 51060089Seric key.dptr = name; 51160089Seric key.dsize = strlen(name); 51260207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 51357014Seric { 51460089Seric if (key.dsize > sizeof keybuf - 1) 51560089Seric key.dsize = sizeof keybuf - 1; 51660089Seric bcopy(key.dptr, keybuf, key.dsize + 1); 51760089Seric makelower(keybuf); 51860089Seric key.dptr = keybuf; 51957014Seric } 52064373Seric fd = dbm_dirfno((DBM *) map->map_db1); 52164388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 52264373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 52363753Seric val.dptr = NULL; 52463753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 52563753Seric { 52663753Seric val = dbm_fetch((DBM *) map->map_db1, key); 52763753Seric if (val.dptr != NULL) 52863753Seric map->map_mflags &= ~MF_TRY1NULL; 52963753Seric } 53063753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 53163753Seric { 53256822Seric key.dsize++; 53363753Seric val = dbm_fetch((DBM *) map->map_db1, key); 53463753Seric if (val.dptr != NULL) 53563753Seric map->map_mflags &= ~MF_TRY0NULL; 53663753Seric } 53764388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 53864373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 53956822Seric if (val.dptr == NULL) 54056822Seric return NULL; 54160207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 54263753Seric return map_rewrite(map, name, strlen(name), NULL); 54363753Seric else 54463753Seric return map_rewrite(map, val.dptr, val.dsize, av); 54556822Seric } 54656822Seric 54756822Seric 54856822Seric /* 54960089Seric ** DBM_MAP_STORE -- store a datum in the database 55056822Seric */ 55156822Seric 55260089Seric void 55360089Seric ndbm_map_store(map, lhs, rhs) 55460089Seric register MAP *map; 55560089Seric char *lhs; 55660089Seric char *rhs; 55760089Seric { 55860089Seric datum key; 55960089Seric datum data; 56060089Seric int stat; 56160089Seric 56260537Seric if (tTd(38, 12)) 563*67726Seric printf("ndbm_map_store(%s, %s, %s)\n", 564*67726Seric map->map_mname, lhs, rhs); 56560089Seric 56660089Seric key.dsize = strlen(lhs); 56760089Seric key.dptr = lhs; 56860089Seric 56960089Seric data.dsize = strlen(rhs); 57060089Seric data.dptr = rhs; 57160089Seric 57260207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 57360089Seric { 57460089Seric key.dsize++; 57560089Seric data.dsize++; 57660089Seric } 57760089Seric 57860089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 57960089Seric if (stat > 0) 58060089Seric { 58160089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 58260089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 58360089Seric } 58460089Seric if (stat != 0) 58560089Seric syserr("readaliases: dbm put (%s)", lhs); 58660089Seric } 58760089Seric 58860089Seric 58960089Seric /* 59060207Seric ** NDBM_MAP_CLOSE -- close the database 59160089Seric */ 59260089Seric 59360089Seric void 59460089Seric ndbm_map_close(map) 59560089Seric register MAP *map; 59660089Seric { 59766773Seric if (tTd(38, 9)) 598*67726Seric printf("ndbm_map_close(%s, %s, %x)\n", 599*67726Seric map->map_mname, map->map_file, map->map_mflags); 60066773Seric 60160207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 60260089Seric { 60364250Seric #ifdef NIS 60464075Seric bool inclnull; 60560089Seric char buf[200]; 60660089Seric 60764075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags); 60864075Seric map->map_mflags &= ~MF_INCLNULL; 60964075Seric 61060089Seric (void) sprintf(buf, "%010ld", curtime()); 61160089Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 61260089Seric 61364941Seric (void) gethostname(buf, sizeof buf); 61460089Seric ndbm_map_store(map, "YP_MASTER_NAME", buf); 61564075Seric 61664075Seric if (inclnull) 61764075Seric map->map_mflags |= MF_INCLNULL; 61860089Seric #endif 61960089Seric 62060089Seric /* write out the distinguished alias */ 62160089Seric ndbm_map_store(map, "@", "@"); 62260089Seric } 62360089Seric dbm_close((DBM *) map->map_db1); 62460089Seric } 62560089Seric 62660089Seric #endif 62760089Seric /* 62860582Seric ** NEWDB (Hash and BTree) Modules 62960089Seric */ 63060089Seric 63160089Seric #ifdef NEWDB 63260089Seric 63360089Seric /* 63460582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 63560582Seric ** 63660582Seric ** These do rather bizarre locking. If you can lock on open, 63760582Seric ** do that to avoid the condition of opening a database that 63860582Seric ** is being rebuilt. If you don't, we'll try to fake it, but 63960582Seric ** there will be a race condition. If opening for read-only, 64060582Seric ** we immediately release the lock to avoid freezing things up. 64160582Seric ** We really ought to hold the lock, but guarantee that we won't 64260582Seric ** be pokey about it. That's hard to do. 64360089Seric */ 64460089Seric 64556822Seric bool 64660089Seric bt_map_open(map, mode) 64756822Seric MAP *map; 64860089Seric int mode; 64956822Seric { 65056822Seric DB *db; 65160228Seric int i; 65260582Seric int omode; 65364373Seric int fd; 65464284Seric struct stat st; 65560089Seric char buf[MAXNAME]; 65656822Seric 65760537Seric if (tTd(38, 2)) 658*67726Seric printf("bt_map_open(%s, %s, %d)\n", 659*67726Seric map->map_mname, map->map_file, mode); 66060089Seric 66160582Seric omode = mode; 66260582Seric if (omode == O_RDWR) 66360582Seric { 66460582Seric omode |= O_CREAT|O_TRUNC; 66565830Seric #if defined(O_EXLOCK) && HASFLOCK 66660582Seric omode |= O_EXLOCK; 66766843Seric # if !OLD_NEWDB 66860582Seric } 66960582Seric else 67060582Seric { 67160582Seric omode |= O_SHLOCK; 67260582Seric # endif 67360582Seric #endif 67460582Seric } 67560207Seric 67660228Seric (void) strcpy(buf, map->map_file); 67760228Seric i = strlen(buf); 67860228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 67960228Seric (void) strcat(buf, ".db"); 68060582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 68156822Seric if (db == NULL) 68256822Seric { 68364718Seric #ifdef MAYBENEXTRELEASE 68464718Seric if (aliaswait(map, ".db", FALSE)) 68564718Seric return TRUE; 68664718Seric #endif 68760207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 68856836Seric syserr("Cannot open BTREE database %s", map->map_file); 68956822Seric return FALSE; 69056822Seric } 69167173Seric #if !OLD_NEWDB 69264373Seric fd = db->fd(db); 69367187Seric # if HASFLOCK 69467187Seric # if !defined(O_EXLOCK) 69564373Seric if (mode == O_RDWR && fd >= 0) 69664388Seric { 69764388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 69864388Seric map->map_mflags |= MF_LOCKED; 69964388Seric } 70067187Seric # else 70164373Seric if (mode == O_RDONLY && fd >= 0) 70264373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 70364388Seric else 70464388Seric map->map_mflags |= MF_LOCKED; 70567187Seric # endif 70660582Seric # endif 70760582Seric #endif 70860585Seric 70960585Seric /* try to make sure that at least the database header is on disk */ 71060585Seric if (mode == O_RDWR) 71166843Seric #if OLD_NEWDB 71264373Seric (void) db->sync(db); 71364373Seric #else 71460585Seric (void) db->sync(db, 0); 71560585Seric 71664373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 71764284Seric map->map_mtime = st.st_mtime; 71864284Seric #endif 71964284Seric 72060089Seric map->map_db2 = (void *) db; 72160207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 72264718Seric if (!aliaswait(map, ".db", TRUE)) 72364718Seric return FALSE; 72456822Seric return TRUE; 72556822Seric } 72656822Seric 72756822Seric 72856822Seric /* 72956822Seric ** HASH_MAP_INIT -- HASH-style map initialization 73056822Seric */ 73156822Seric 73256822Seric bool 73360089Seric hash_map_open(map, mode) 73456822Seric MAP *map; 73560089Seric int mode; 73656822Seric { 73756822Seric DB *db; 73860228Seric int i; 73960582Seric int omode; 74064373Seric int fd; 74164284Seric struct stat st; 74260089Seric char buf[MAXNAME]; 74356822Seric 74460537Seric if (tTd(38, 2)) 745*67726Seric printf("hash_map_open(%s, %s, %d)\n", 746*67726Seric map->map_mname, map->map_file, mode); 74760089Seric 74860582Seric omode = mode; 74960582Seric if (omode == O_RDWR) 75060582Seric { 75160582Seric omode |= O_CREAT|O_TRUNC; 75265830Seric #if defined(O_EXLOCK) && HASFLOCK 75360582Seric omode |= O_EXLOCK; 75466843Seric # if !OLD_NEWDB 75560582Seric } 75660582Seric else 75760582Seric { 75860582Seric omode |= O_SHLOCK; 75960582Seric # endif 76060582Seric #endif 76160582Seric } 76260207Seric 76360228Seric (void) strcpy(buf, map->map_file); 76460228Seric i = strlen(buf); 76560228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 76660228Seric (void) strcat(buf, ".db"); 76760582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 76856822Seric if (db == NULL) 76956822Seric { 77064718Seric #ifdef MAYBENEXTRELEASE 77164718Seric if (aliaswait(map, ".db", FALSE)) 77264718Seric return TRUE; 77364718Seric #endif 77460207Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 77556836Seric syserr("Cannot open HASH database %s", map->map_file); 77656822Seric return FALSE; 77756822Seric } 77867173Seric #if !OLD_NEWDB 77964373Seric fd = db->fd(db); 78067187Seric # if HASFLOCK 78167187Seric # if !defined(O_EXLOCK) 78264373Seric if (mode == O_RDWR && fd >= 0) 78364388Seric { 78464388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX)) 78564388Seric map->map_mflags |= MF_LOCKED; 78664388Seric } 78767187Seric # else 78864373Seric if (mode == O_RDONLY && fd >= 0) 78964373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 79064388Seric else 79164388Seric map->map_mflags |= MF_LOCKED; 79267187Seric # endif 79360582Seric # endif 79460582Seric #endif 79560585Seric 79660585Seric /* try to make sure that at least the database header is on disk */ 79760585Seric if (mode == O_RDWR) 79866843Seric #if OLD_NEWDB 79964373Seric (void) db->sync(db); 80064373Seric #else 80160585Seric (void) db->sync(db, 0); 80260585Seric 80364373Seric if (fd >= 0 && fstat(fd, &st) >= 0) 80464284Seric map->map_mtime = st.st_mtime; 80564284Seric #endif 80664284Seric 80760089Seric map->map_db2 = (void *) db; 80860207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 80964718Seric if (!aliaswait(map, ".db", TRUE)) 81064718Seric return FALSE; 81156822Seric return TRUE; 81256822Seric } 81356822Seric 81456822Seric 81556822Seric /* 81656822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 81756822Seric */ 81856822Seric 81956822Seric char * 82060089Seric db_map_lookup(map, name, av, statp) 82156822Seric MAP *map; 82260089Seric char *name; 82356822Seric char **av; 82459084Seric int *statp; 82556822Seric { 82656822Seric DBT key, val; 82760422Seric register DB *db = (DB *) map->map_db2; 82860422Seric int st; 82960422Seric int saveerrno; 83064373Seric int fd; 83160089Seric char keybuf[MAXNAME + 1]; 83256822Seric 83360537Seric if (tTd(38, 20)) 834*67726Seric printf("db_map_lookup(%s, %s)\n", 835*67726Seric map->map_mname, name); 83660089Seric 83760089Seric key.size = strlen(name); 83860089Seric if (key.size > sizeof keybuf - 1) 83960089Seric key.size = sizeof keybuf - 1; 84060089Seric key.data = keybuf; 84160089Seric bcopy(name, keybuf, key.size + 1); 84260207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 84360089Seric makelower(keybuf); 84466843Seric #if !OLD_NEWDB 84564388Seric fd = db->fd(db); 84664388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 84764388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); 84860422Seric #endif 84963753Seric st = 1; 85063753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 85163753Seric { 85263753Seric st = db->get(db, &key, &val, 0); 85363753Seric if (st == 0) 85463753Seric map->map_mflags &= ~MF_TRY1NULL; 85563753Seric } 85663753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 85763753Seric { 85863753Seric key.size++; 85963753Seric st = db->get(db, &key, &val, 0); 86063753Seric if (st == 0) 86163753Seric map->map_mflags &= ~MF_TRY0NULL; 86263753Seric } 86360422Seric saveerrno = errno; 86466843Seric #if !OLD_NEWDB 86564388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 86664373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN); 86760422Seric #endif 86860422Seric if (st != 0) 86960422Seric { 87060422Seric errno = saveerrno; 87160422Seric if (st < 0) 87260422Seric syserr("db_map_lookup: get (%s)", name); 87356822Seric return NULL; 87460422Seric } 87560207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 87663753Seric return map_rewrite(map, name, strlen(name), NULL); 87763753Seric else 87863753Seric return map_rewrite(map, val.data, val.size, av); 87956822Seric } 88056822Seric 88160089Seric 88260089Seric /* 88360089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database 88456822Seric */ 88556822Seric 88660089Seric void 88760089Seric db_map_store(map, lhs, rhs) 88860089Seric register MAP *map; 88960089Seric char *lhs; 89060089Seric char *rhs; 89156822Seric { 89260089Seric int stat; 89360089Seric DBT key; 89460089Seric DBT data; 89560089Seric register DB *db = map->map_db2; 89656822Seric 89760537Seric if (tTd(38, 20)) 898*67726Seric printf("db_map_store(%s, %s, %s)\n", 899*67726Seric map->map_mname, lhs, rhs); 90060089Seric 90160089Seric key.size = strlen(lhs); 90260089Seric key.data = lhs; 90360089Seric 90460089Seric data.size = strlen(rhs); 90560089Seric data.data = rhs; 90660089Seric 90760207Seric if (bitset(MF_INCLNULL, map->map_mflags)) 90856822Seric { 90960089Seric key.size++; 91060089Seric data.size++; 91160089Seric } 91256836Seric 91360089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE); 91460089Seric if (stat > 0) 91560089Seric { 91660089Seric usrerr("050 Warning: duplicate alias name %s", lhs); 91760089Seric stat = db->put(db, &key, &data, 0); 91860089Seric } 91960089Seric if (stat != 0) 92060089Seric syserr("readaliases: db put (%s)", lhs); 92160089Seric } 92256836Seric 92356847Seric 92460089Seric /* 92560089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database 92660089Seric */ 92760089Seric 92860089Seric void 92960089Seric db_map_close(map) 93060089Seric MAP *map; 93160089Seric { 93260089Seric register DB *db = map->map_db2; 93360089Seric 93460537Seric if (tTd(38, 9)) 935*67726Seric printf("db_map_close(%s, %s, %x)\n", 936*67726Seric map->map_mname, map->map_file, map->map_mflags); 93760089Seric 93860207Seric if (bitset(MF_WRITABLE, map->map_mflags)) 93958804Seric { 94060089Seric /* write out the distinguished alias */ 94160089Seric db_map_store(map, "@", "@"); 94258804Seric } 94358963Seric 94460089Seric if (db->close(db) != 0) 94560089Seric syserr("readaliases: db close failure"); 94656822Seric } 94757208Seric 94860089Seric #endif 94960089Seric /* 95060089Seric ** NIS Modules 95160089Seric */ 95260089Seric 95360089Seric # ifdef NIS 95460089Seric 95564369Seric # ifndef YPERR_BUSY 95664369Seric # define YPERR_BUSY 16 95764369Seric # endif 95864369Seric 95957208Seric /* 96060089Seric ** NIS_MAP_OPEN -- open DBM map 96157208Seric */ 96257208Seric 96357208Seric bool 96460089Seric nis_map_open(map, mode) 96557208Seric MAP *map; 96660089Seric int mode; 96757208Seric { 96857216Seric int yperr; 96960215Seric register char *p; 97060215Seric auto char *vp; 97160215Seric auto int vsize; 97257216Seric char *master; 97357216Seric 97460537Seric if (tTd(38, 2)) 975*67726Seric printf("nis_map_open(%s, %s)\n", 976*67726Seric map->map_mname, map->map_file); 97760089Seric 97860207Seric if (mode != O_RDONLY) 97960207Seric { 98064650Seric /* issue a pseudo-error message */ 98164650Seric #ifdef ENOSYS 98264650Seric errno = ENOSYS; 98364650Seric #else 98464650Seric # ifdef EFTYPE 98564650Seric errno = EFTYPE; 98664650Seric # else 98764650Seric errno = ENXIO; 98864650Seric # endif 98964650Seric #endif 99060207Seric return FALSE; 99160207Seric } 99260207Seric 99360089Seric p = strchr(map->map_file, '@'); 99460089Seric if (p != NULL) 99560089Seric { 99660089Seric *p++ = '\0'; 99760089Seric if (*p != '\0') 99860089Seric map->map_domain = p; 99960089Seric } 100060215Seric 100160089Seric if (*map->map_file == '\0') 100260089Seric map->map_file = "mail.aliases"; 100360089Seric 100466157Seric if (map->map_domain == NULL) 100566157Seric { 100666157Seric yperr = yp_get_default_domain(&map->map_domain); 100766157Seric if (yperr != 0) 100866157Seric { 100966744Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 101066744Seric syserr("NIS map %s specified, but NIS not running\n", 101166744Seric map->map_file); 101266157Seric return FALSE; 101366157Seric } 101466157Seric } 101566157Seric 101660215Seric /* check to see if this map actually exists */ 101760089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1, 101860089Seric &vp, &vsize); 101960537Seric if (tTd(38, 10)) 102060089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n", 102160089Seric map->map_domain, map->map_file, yperr_string(yperr)); 102260089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 102360089Seric return TRUE; 102460215Seric 102560215Seric if (!bitset(MF_OPTIONAL, map->map_mflags)) 102660215Seric syserr("Cannot bind to domain %s: %s", map->map_domain, 102760215Seric yperr_string(yperr)); 102860215Seric 102960089Seric return FALSE; 103060089Seric } 103160089Seric 103260089Seric 103360089Seric /* 103457208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 103557208Seric */ 103657208Seric 103757208Seric char * 103860089Seric nis_map_lookup(map, name, av, statp) 103957208Seric MAP *map; 104060089Seric char *name; 104157208Seric char **av; 104259084Seric int *statp; 104357208Seric { 104457208Seric char *vp; 104557642Seric auto int vsize; 104659274Seric int buflen; 104760215Seric int yperr; 104860089Seric char keybuf[MAXNAME + 1]; 104957208Seric 105060537Seric if (tTd(38, 20)) 1051*67726Seric printf("nis_map_lookup(%s, %s)\n", 1052*67726Seric map->map_mname, name); 105360089Seric 105460089Seric buflen = strlen(name); 105560089Seric if (buflen > sizeof keybuf - 1) 105660089Seric buflen = sizeof keybuf - 1; 105760089Seric bcopy(name, keybuf, buflen + 1); 105860207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 105960089Seric makelower(keybuf); 106063753Seric yperr = YPERR_KEY; 106163753Seric if (bitset(MF_TRY0NULL, map->map_mflags)) 106263753Seric { 106363753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 106463753Seric &vp, &vsize); 106563753Seric if (yperr == 0) 106663753Seric map->map_mflags &= ~MF_TRY1NULL; 106763753Seric } 106863753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 106963753Seric { 107059274Seric buflen++; 107163753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 107263753Seric &vp, &vsize); 107363753Seric if (yperr == 0) 107463753Seric map->map_mflags &= ~MF_TRY0NULL; 107563753Seric } 107660089Seric if (yperr != 0) 107760089Seric { 107860089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 107960215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN); 108057208Seric return NULL; 108160089Seric } 108260207Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 108363753Seric return map_rewrite(map, name, strlen(name), NULL); 108463753Seric else 108563753Seric return map_rewrite(map, vp, vsize, av); 108657208Seric } 108757208Seric 1088*67726Seric #endif 108957208Seric /* 109060089Seric ** STAB (Symbol Table) Modules 109160089Seric */ 109260089Seric 109360089Seric 109460089Seric /* 109560207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table 109660089Seric */ 109760089Seric 109860089Seric char * 109961707Seric stab_map_lookup(map, name, av, pstat) 110060089Seric register MAP *map; 110160089Seric char *name; 110261707Seric char **av; 110361707Seric int *pstat; 110460089Seric { 110560089Seric register STAB *s; 110660089Seric 110760537Seric if (tTd(38, 20)) 1108*67726Seric printf("stab_lookup(%s, %s)\n", 1109*67726Seric map->map_mname, name); 111060089Seric 111160089Seric s = stab(name, ST_ALIAS, ST_FIND); 111260089Seric if (s != NULL) 111360089Seric return (s->s_alias); 111460089Seric return (NULL); 111560089Seric } 111660089Seric 111760089Seric 111860089Seric /* 111960207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 112060089Seric */ 112160089Seric 112260089Seric void 112360089Seric stab_map_store(map, lhs, rhs) 112460089Seric register MAP *map; 112560089Seric char *lhs; 112660089Seric char *rhs; 112760089Seric { 112860089Seric register STAB *s; 112960089Seric 113060089Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 113160089Seric s->s_alias = newstr(rhs); 113260089Seric } 113360089Seric 113460089Seric 113560089Seric /* 113660207Seric ** STAB_MAP_OPEN -- initialize (reads data file) 113760207Seric ** 113860207Seric ** This is a wierd case -- it is only intended as a fallback for 113960207Seric ** aliases. For this reason, opens for write (only during a 114060207Seric ** "newaliases") always fails, and opens for read open the 114160207Seric ** actual underlying text file instead of the database. 114260089Seric */ 114360089Seric 114460089Seric bool 114560089Seric stab_map_open(map, mode) 114660089Seric register MAP *map; 114760089Seric int mode; 114860089Seric { 114963835Seric FILE *af; 115064284Seric struct stat st; 115163835Seric 115260537Seric if (tTd(38, 2)) 1153*67726Seric printf("stab_map_open(%s, %s)\n", 1154*67726Seric map->map_mname, map->map_file); 115560089Seric 115660089Seric if (mode != O_RDONLY) 115760207Seric { 115860207Seric errno = ENODEV; 115960089Seric return FALSE; 116060207Seric } 116160089Seric 116263835Seric af = fopen(map->map_file, "r"); 116363835Seric if (af == NULL) 116463835Seric return FALSE; 116567263Seric readaliases(map, af, FALSE, FALSE); 116664284Seric 116764284Seric if (fstat(fileno(af), &st) >= 0) 116864284Seric map->map_mtime = st.st_mtime; 116963835Seric fclose(af); 117063835Seric 117160089Seric return TRUE; 117260089Seric } 117360089Seric /* 117460089Seric ** Implicit Modules 117556822Seric ** 117660089Seric ** Tries several types. For back compatibility of aliases. 117756822Seric */ 117856822Seric 117960089Seric 118060089Seric /* 118160207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database 118260089Seric */ 118360089Seric 118460089Seric char * 118560089Seric impl_map_lookup(map, name, av, pstat) 118660089Seric MAP *map; 118760089Seric char *name; 118856822Seric char **av; 118960089Seric int *pstat; 119056822Seric { 119160537Seric if (tTd(38, 20)) 1192*67726Seric printf("impl_map_lookup(%s, %s)\n", 1193*67726Seric map->map_mname, name); 119456822Seric 119560089Seric #ifdef NEWDB 119660207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 119760089Seric return db_map_lookup(map, name, av, pstat); 119860089Seric #endif 119960089Seric #ifdef NDBM 120060207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 120160089Seric return ndbm_map_lookup(map, name, av, pstat); 120260089Seric #endif 120360089Seric return stab_map_lookup(map, name, av, pstat); 120460089Seric } 120560089Seric 120660089Seric /* 120760207Seric ** IMPL_MAP_STORE -- store in open databases 120860089Seric */ 120960089Seric 121060089Seric void 121160089Seric impl_map_store(map, lhs, rhs) 121260089Seric MAP *map; 121360089Seric char *lhs; 121460089Seric char *rhs; 121560089Seric { 121660089Seric #ifdef NEWDB 121760207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 121860089Seric db_map_store(map, lhs, rhs); 121960089Seric #endif 122060089Seric #ifdef NDBM 122160207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 122260089Seric ndbm_map_store(map, lhs, rhs); 122360089Seric #endif 122460089Seric stab_map_store(map, lhs, rhs); 122560089Seric } 122660089Seric 122760089Seric /* 122860089Seric ** IMPL_MAP_OPEN -- implicit database open 122960089Seric */ 123060089Seric 123160089Seric bool 123260089Seric impl_map_open(map, mode) 123360089Seric MAP *map; 123460089Seric int mode; 123560089Seric { 123660089Seric struct stat stb; 123760089Seric 123860537Seric if (tTd(38, 2)) 1239*67726Seric printf("impl_map_open(%s, %s, %d)\n", 1240*67726Seric map->map_mname, map->map_file, mode); 124160089Seric 124260089Seric if (stat(map->map_file, &stb) < 0) 124356822Seric { 124460089Seric /* no alias file at all */ 124564718Seric if (tTd(38, 3)) 124664718Seric printf("no map file\n"); 124760089Seric return FALSE; 124856822Seric } 124956822Seric 125060089Seric #ifdef NEWDB 125160207Seric map->map_mflags |= MF_IMPL_HASH; 125260089Seric if (hash_map_open(map, mode)) 125356822Seric { 125464250Seric #if defined(NDBM) && defined(NIS) 125560561Seric if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 125660207Seric #endif 125760207Seric return TRUE; 125860089Seric } 125960207Seric else 126060207Seric map->map_mflags &= ~MF_IMPL_HASH; 126160089Seric #endif 126260089Seric #ifdef NDBM 126360207Seric map->map_mflags |= MF_IMPL_NDBM; 126460089Seric if (ndbm_map_open(map, mode)) 126560089Seric { 126660089Seric return TRUE; 126760089Seric } 126860207Seric else 126960207Seric map->map_mflags &= ~MF_IMPL_NDBM; 127060089Seric #endif 127156822Seric 127264650Seric #if defined(NEWDB) || defined(NDBM) 127360089Seric if (Verbose) 127460089Seric message("WARNING: cannot open alias database %s", map->map_file); 127564964Seric #else 127664964Seric if (mode != O_RDONLY) 127764964Seric usrerr("Cannot rebuild aliases: no database format defined"); 127860207Seric #endif 127960089Seric 128060207Seric return stab_map_open(map, mode); 128156822Seric } 128260089Seric 128360207Seric 128460089Seric /* 128560207Seric ** IMPL_MAP_CLOSE -- close any open database(s) 128660089Seric */ 128760089Seric 128860089Seric void 128960207Seric impl_map_close(map) 129060089Seric MAP *map; 129160089Seric { 129260089Seric #ifdef NEWDB 129360207Seric if (bitset(MF_IMPL_HASH, map->map_mflags)) 129460089Seric { 129560207Seric db_map_close(map); 129660207Seric map->map_mflags &= ~MF_IMPL_HASH; 129760089Seric } 129860089Seric #endif 129960089Seric 130060089Seric #ifdef NDBM 130160207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags)) 130260089Seric { 130360207Seric ndbm_map_close(map); 130460207Seric map->map_mflags &= ~MF_IMPL_NDBM; 130560089Seric } 130660089Seric #endif 130760089Seric } 130860207Seric /* 1309*67726Seric ** User map class. 1310*67726Seric ** 1311*67726Seric ** Provides access to the system password file. 1312*67726Seric */ 1313*67726Seric 1314*67726Seric /* 1315*67726Seric ** USER_MAP_OPEN -- open user map 1316*67726Seric ** 1317*67726Seric ** Really just binds field names to field numbers. 1318*67726Seric */ 1319*67726Seric 1320*67726Seric bool 1321*67726Seric user_map_open(map, mode) 1322*67726Seric MAP *map; 1323*67726Seric int mode; 1324*67726Seric { 1325*67726Seric if (tTd(38, 2)) 1326*67726Seric printf("user_map_open(%s)\n", map->map_mname); 1327*67726Seric 1328*67726Seric if (mode != O_RDONLY) 1329*67726Seric { 1330*67726Seric /* issue a pseudo-error message */ 1331*67726Seric #ifdef ENOSYS 1332*67726Seric errno = ENOSYS; 1333*67726Seric #else 1334*67726Seric # ifdef EFTYPE 1335*67726Seric errno = EFTYPE; 1336*67726Seric # else 1337*67726Seric errno = ENXIO; 1338*67726Seric # endif 1339*67726Seric #endif 1340*67726Seric return FALSE; 1341*67726Seric } 1342*67726Seric if (map->map_valcolnm == NULL) 1343*67726Seric /* nothing */ ; 1344*67726Seric else if (strcasecmp(map->map_valcolnm, "name") == 0) 1345*67726Seric map->map_valcolno = 1; 1346*67726Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 1347*67726Seric map->map_valcolno = 2; 1348*67726Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0) 1349*67726Seric map->map_valcolno = 3; 1350*67726Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0) 1351*67726Seric map->map_valcolno = 4; 1352*67726Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 1353*67726Seric map->map_valcolno = 5; 1354*67726Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0) 1355*67726Seric map->map_valcolno = 6; 1356*67726Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0) 1357*67726Seric map->map_valcolno = 7; 1358*67726Seric else 1359*67726Seric { 1360*67726Seric syserr("User map %s: unknown column name %s", 1361*67726Seric map->map_mname, map->map_valcolnm); 1362*67726Seric return FALSE; 1363*67726Seric } 1364*67726Seric return TRUE; 1365*67726Seric } 1366*67726Seric 1367*67726Seric 1368*67726Seric /* 1369*67726Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file. 1370*67726Seric */ 1371*67726Seric 1372*67726Seric #include <pwd.h> 1373*67726Seric 1374*67726Seric char * 1375*67726Seric user_map_lookup(map, key, av, statp) 1376*67726Seric MAP *map; 1377*67726Seric char *key; 1378*67726Seric char **av; 1379*67726Seric int *statp; 1380*67726Seric { 1381*67726Seric struct passwd *pw; 1382*67726Seric 1383*67726Seric if (tTd(38, 20)) 1384*67726Seric printf("user_map_lookup(%s, %s)\n", 1385*67726Seric map->map_mname, key); 1386*67726Seric 1387*67726Seric pw = getpwnam(key); 1388*67726Seric if (pw == NULL) 1389*67726Seric return NULL; 1390*67726Seric if (bitset(MF_MATCHONLY, map->map_mflags)) 1391*67726Seric return map_rewrite(map, key, strlen(key), NULL); 1392*67726Seric else 1393*67726Seric { 1394*67726Seric char *rwval; 1395*67726Seric char buf[30]; 1396*67726Seric 1397*67726Seric switch (map->map_valcolno) 1398*67726Seric { 1399*67726Seric case 0: 1400*67726Seric case 1: 1401*67726Seric rwval = key; 1402*67726Seric break; 1403*67726Seric 1404*67726Seric case 2: 1405*67726Seric rwval = pw->pw_passwd; 1406*67726Seric break; 1407*67726Seric 1408*67726Seric case 3: 1409*67726Seric sprintf(buf, "%d", pw->pw_uid); 1410*67726Seric rwval = buf; 1411*67726Seric break; 1412*67726Seric 1413*67726Seric case 4: 1414*67726Seric sprintf(buf, "%d", pw->pw_gid); 1415*67726Seric rwval = buf; 1416*67726Seric break; 1417*67726Seric 1418*67726Seric case 5: 1419*67726Seric rwval = pw->pw_gecos; 1420*67726Seric break; 1421*67726Seric 1422*67726Seric case 6: 1423*67726Seric rwval = pw->pw_dir; 1424*67726Seric break; 1425*67726Seric 1426*67726Seric case 7: 1427*67726Seric rwval = pw->pw_shell; 1428*67726Seric break; 1429*67726Seric } 1430*67726Seric return map_rewrite(map, rwval, strlen(rwval), av); 1431*67726Seric } 1432*67726Seric } 1433*67726Seric /* 1434*67726Seric ** Sequenced map type. 1435*67726Seric ** 1436*67726Seric ** Tries each map in order until something matches, much like 1437*67726Seric ** implicit. Stores go to the first map in the list that can 1438*67726Seric ** support storing. 1439*67726Seric */ 1440*67726Seric 1441*67726Seric /* 1442*67726Seric ** SEQ_MAP_PARSE -- Sequenced map parsing 1443*67726Seric */ 1444*67726Seric 1445*67726Seric bool 1446*67726Seric seq_map_parse(map, ap) 1447*67726Seric MAP *map; 1448*67726Seric char *ap; 1449*67726Seric { 1450*67726Seric int maxmap; 1451*67726Seric 1452*67726Seric if (tTd(38, 2)) 1453*67726Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 1454*67726Seric maxmap = 0; 1455*67726Seric while (*ap != '\0') 1456*67726Seric { 1457*67726Seric register char *p; 1458*67726Seric STAB *s; 1459*67726Seric 1460*67726Seric /* find beginning of map name */ 1461*67726Seric while (isascii(*ap) && isspace(*ap)) 1462*67726Seric ap++; 1463*67726Seric for (p = ap; isascii(*p) && isalnum(*p); p++) 1464*67726Seric continue; 1465*67726Seric if (*p != '\0') 1466*67726Seric *p++ = '\0'; 1467*67726Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 1468*67726Seric p++; 1469*67726Seric if (*ap == '\0') 1470*67726Seric { 1471*67726Seric ap = p; 1472*67726Seric continue; 1473*67726Seric } 1474*67726Seric s = stab(ap, ST_MAP, ST_FIND); 1475*67726Seric if (s == NULL) 1476*67726Seric { 1477*67726Seric syserr("Sequence map %s: unknown member map %s", 1478*67726Seric map->map_mname, ap); 1479*67726Seric } 1480*67726Seric else if (maxmap == MAXMAPSTACK) 1481*67726Seric { 1482*67726Seric syserr("Sequence map %s: too many member maps (%d max)", 1483*67726Seric map->map_mname, MAXMAPSTACK); 1484*67726Seric maxmap++; 1485*67726Seric } 1486*67726Seric else if (maxmap < MAXMAPSTACK) 1487*67726Seric { 1488*67726Seric map->map_stack[maxmap++] = &s->s_map; 1489*67726Seric } 1490*67726Seric ap = p; 1491*67726Seric } 1492*67726Seric return TRUE; 1493*67726Seric } 1494*67726Seric 1495*67726Seric 1496*67726Seric /* 1497*67726Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup 1498*67726Seric */ 1499*67726Seric 1500*67726Seric char * 1501*67726Seric seq_map_lookup(map, key, args, pstat) 1502*67726Seric MAP *map; 1503*67726Seric char *key; 1504*67726Seric char **args; 1505*67726Seric int *pstat; 1506*67726Seric { 1507*67726Seric int mapno; 1508*67726Seric int mapbit = 0x01; 1509*67726Seric 1510*67726Seric if (tTd(38, 20)) 1511*67726Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 1512*67726Seric 1513*67726Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 1514*67726Seric { 1515*67726Seric MAP *mm = map->map_stack[mapno]; 1516*67726Seric int stat = 0; 1517*67726Seric char *rv; 1518*67726Seric 1519*67726Seric if (mm == NULL) 1520*67726Seric continue; 1521*67726Seric if (!bitset(MF_OPEN, mm->map_mflags)) 1522*67726Seric { 1523*67726Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 1524*67726Seric return NULL; 1525*67726Seric continue; 1526*67726Seric } 1527*67726Seric rv = mm->map_class->map_lookup(mm, key, args, &stat); 1528*67726Seric if (rv != NULL) 1529*67726Seric return rv; 1530*67726Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND])) 1531*67726Seric return NULL; 1532*67726Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN])) 1533*67726Seric { 1534*67726Seric *pstat = stat; 1535*67726Seric return NULL; 1536*67726Seric } 1537*67726Seric } 1538*67726Seric return NULL; 1539*67726Seric } 1540*67726Seric 1541*67726Seric 1542*67726Seric /* 1543*67726Seric ** SEQ_MAP_STORE -- sequenced map store 1544*67726Seric */ 1545*67726Seric 1546*67726Seric void 1547*67726Seric seq_map_store(map, key, val) 1548*67726Seric MAP *map; 1549*67726Seric char *key; 1550*67726Seric char *val; 1551*67726Seric { 1552*67726Seric int mapno; 1553*67726Seric 1554*67726Seric if (tTd(38, 12)) 1555*67726Seric printf("seq_map_store(%s, %s, %s)\n", 1556*67726Seric map->map_mname, key, val); 1557*67726Seric 1558*67726Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 1559*67726Seric { 1560*67726Seric MAP *mm = map->map_stack[mapno]; 1561*67726Seric 1562*67726Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 1563*67726Seric continue; 1564*67726Seric 1565*67726Seric mm->map_class->map_store(mm, key, val); 1566*67726Seric return; 1567*67726Seric } 1568*67726Seric syserr("seq_map_store(%s, %s, %s): no writable map", 1569*67726Seric map->map_mname, key, val); 1570*67726Seric } 1571*67726Seric /* 157260207Seric ** NULL stubs 157360089Seric */ 157460089Seric 157560207Seric bool 157660207Seric null_map_open(map, mode) 157760089Seric MAP *map; 157860207Seric int mode; 157960089Seric { 158060207Seric return TRUE; 158160089Seric } 158260089Seric 158360207Seric void 158460207Seric null_map_close(map) 158560207Seric MAP *map; 158660089Seric { 158760207Seric return; 158860207Seric } 158960089Seric 159060207Seric void 159160207Seric null_map_store(map, key, val) 159260207Seric MAP *map; 159360207Seric char *key; 159460207Seric char *val; 159560089Seric { 159660207Seric return; 159760089Seric } 1598