map.c revision 38032
138032Speter/* 238032Speter * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 338032Speter * Copyright (c) 1992, 1995-1997 Eric P. Allman. All rights reserved. 438032Speter * Copyright (c) 1992, 1993 538032Speter * The Regents of the University of California. All rights reserved. 638032Speter * 738032Speter * By using this file, you agree to the terms and conditions set 838032Speter * forth in the LICENSE file which can be found at the top level of 938032Speter * the sendmail distribution. 1038032Speter * 1138032Speter */ 1238032Speter 1338032Speter#ifndef lint 1438032Speterstatic char sccsid[] = "@(#)map.c 8.239 (Berkeley) 6/5/98"; 1538032Speter#endif /* not lint */ 1638032Speter 1738032Speter#include "sendmail.h" 1838032Speter 1938032Speter#ifdef NDBM 2038032Speter# include <ndbm.h> 2138032Speter# ifdef R_FIRST 2238032Speter ERROR README: You are running the Berkeley DB version of ndbm.h. See 2338032Speter ERROR README: the README file about tweaking Berkeley DB so it can 2438032Speter ERROR README: coexist with NDBM, or delete -DNDBM from the Makefile 2538032Speter ERROR README: and use -DNEWDB instead. 2638032Speter# endif 2738032Speter#endif 2838032Speter#ifdef NEWDB 2938032Speter# include <db.h> 3038032Speter# ifndef DB_VERSION_MAJOR 3138032Speter# define DB_VERSION_MAJOR 1 3238032Speter# endif 3338032Speter#endif 3438032Speter#ifdef NIS 3538032Speter struct dom_binding; /* forward reference needed on IRIX */ 3638032Speter# include <rpcsvc/ypclnt.h> 3738032Speter# ifdef NDBM 3838032Speter# define NDBM_YP_COMPAT /* create YP-compatible NDBM files */ 3938032Speter# endif 4038032Speter#endif 4138032Speter 4238032Speter/* 4338032Speter** MAP.C -- implementations for various map classes. 4438032Speter** 4538032Speter** Each map class implements a series of functions: 4638032Speter** 4738032Speter** bool map_parse(MAP *map, char *args) 4838032Speter** Parse the arguments from the config file. Return TRUE 4938032Speter** if they were ok, FALSE otherwise. Fill in map with the 5038032Speter** values. 5138032Speter** 5238032Speter** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 5338032Speter** Look up the key in the given map. If found, do any 5438032Speter** rewriting the map wants (including "args" if desired) 5538032Speter** and return the value. Set *pstat to the appropriate status 5638032Speter** on error and return NULL. Args will be NULL if called 5738032Speter** from the alias routines, although this should probably 5838032Speter** not be relied upon. It is suggested you call map_rewrite 5938032Speter** to return the results -- it takes care of null termination 6038032Speter** and uses a dynamically expanded buffer as needed. 6138032Speter** 6238032Speter** void map_store(MAP *map, char *key, char *value) 6338032Speter** Store the key:value pair in the map. 6438032Speter** 6538032Speter** bool map_open(MAP *map, int mode) 6638032Speter** Open the map for the indicated mode. Mode should 6738032Speter** be either O_RDONLY or O_RDWR. Return TRUE if it 6838032Speter** was opened successfully, FALSE otherwise. If the open 6938032Speter** failed an the MF_OPTIONAL flag is not set, it should 7038032Speter** also print an error. If the MF_ALIAS bit is set 7138032Speter** and this map class understands the @:@ convention, it 7238032Speter** should call aliaswait() before returning. 7338032Speter** 7438032Speter** void map_close(MAP *map) 7538032Speter** Close the map. 7638032Speter** 7738032Speter** This file also includes the implementation for getcanonname. 7838032Speter** It is currently implemented in a pretty ad-hoc manner; it ought 7938032Speter** to be more properly integrated into the map structure. 8038032Speter*/ 8138032Speter 8238032Speter#define DBMMODE 0644 8338032Speter 8438032Speter#ifndef EX_NOTFOUND 8538032Speter# define EX_NOTFOUND EX_NOHOST 8638032Speter#endif 8738032Speter 8838032Speterextern bool aliaswait __P((MAP *, char *, int)); 8938032Speterextern bool extract_canonname __P((char *, char *, char[], int)); 9038032Speter 9138032Speter#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL 9238032Speter# define LOCK_ON_OPEN 1 /* we can open/create a locked file */ 9338032Speter#else 9438032Speter# define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */ 9538032Speter#endif 9638032Speter 9738032Speter#ifndef O_ACCMODE 9838032Speter# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) 9938032Speter#endif 10038032Speter/* 10138032Speter** MAP_PARSEARGS -- parse config line arguments for database lookup 10238032Speter** 10338032Speter** This is a generic version of the map_parse method. 10438032Speter** 10538032Speter** Parameters: 10638032Speter** map -- the map being initialized. 10738032Speter** ap -- a pointer to the args on the config line. 10838032Speter** 10938032Speter** Returns: 11038032Speter** TRUE -- if everything parsed OK. 11138032Speter** FALSE -- otherwise. 11238032Speter** 11338032Speter** Side Effects: 11438032Speter** null terminates the filename; stores it in map 11538032Speter*/ 11638032Speter 11738032Speterbool 11838032Spetermap_parseargs(map, ap) 11938032Speter MAP *map; 12038032Speter char *ap; 12138032Speter{ 12238032Speter register char *p = ap; 12338032Speter 12438032Speter map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; 12538032Speter for (;;) 12638032Speter { 12738032Speter while (isascii(*p) && isspace(*p)) 12838032Speter p++; 12938032Speter if (*p != '-') 13038032Speter break; 13138032Speter switch (*++p) 13238032Speter { 13338032Speter case 'N': 13438032Speter map->map_mflags |= MF_INCLNULL; 13538032Speter map->map_mflags &= ~MF_TRY0NULL; 13638032Speter break; 13738032Speter 13838032Speter case 'O': 13938032Speter map->map_mflags &= ~MF_TRY1NULL; 14038032Speter break; 14138032Speter 14238032Speter case 'o': 14338032Speter map->map_mflags |= MF_OPTIONAL; 14438032Speter break; 14538032Speter 14638032Speter case 'f': 14738032Speter map->map_mflags |= MF_NOFOLDCASE; 14838032Speter break; 14938032Speter 15038032Speter case 'm': 15138032Speter map->map_mflags |= MF_MATCHONLY; 15238032Speter break; 15338032Speter 15438032Speter case 'A': 15538032Speter map->map_mflags |= MF_APPEND; 15638032Speter break; 15738032Speter 15838032Speter case 'q': 15938032Speter map->map_mflags |= MF_KEEPQUOTES; 16038032Speter break; 16138032Speter 16238032Speter case 'a': 16338032Speter map->map_app = ++p; 16438032Speter break; 16538032Speter 16638032Speter case 'T': 16738032Speter map->map_tapp = ++p; 16838032Speter break; 16938032Speter 17038032Speter case 'k': 17138032Speter while (isascii(*++p) && isspace(*p)) 17238032Speter continue; 17338032Speter map->map_keycolnm = p; 17438032Speter break; 17538032Speter 17638032Speter case 'v': 17738032Speter while (isascii(*++p) && isspace(*p)) 17838032Speter continue; 17938032Speter map->map_valcolnm = p; 18038032Speter break; 18138032Speter 18238032Speter case 'z': 18338032Speter if (*++p != '\\') 18438032Speter map->map_coldelim = *p; 18538032Speter else 18638032Speter { 18738032Speter switch (*++p) 18838032Speter { 18938032Speter case 'n': 19038032Speter map->map_coldelim = '\n'; 19138032Speter break; 19238032Speter 19338032Speter case 't': 19438032Speter map->map_coldelim = '\t'; 19538032Speter break; 19638032Speter 19738032Speter default: 19838032Speter map->map_coldelim = '\\'; 19938032Speter } 20038032Speter } 20138032Speter break; 20238032Speter 20338032Speter case 't': 20438032Speter map->map_mflags |= MF_NODEFER; 20538032Speter break; 20638032Speter 20738032Speter#ifdef RESERVED_FOR_SUN 20838032Speter case 'd': 20938032Speter map->map_mflags |= MF_DOMAIN_WIDE; 21038032Speter break; 21138032Speter 21238032Speter case 's': 21338032Speter /* info type */ 21438032Speter break; 21538032Speter#endif 21638032Speter } 21738032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 21838032Speter p++; 21938032Speter if (*p != '\0') 22038032Speter *p++ = '\0'; 22138032Speter } 22238032Speter if (map->map_app != NULL) 22338032Speter map->map_app = newstr(map->map_app); 22438032Speter if (map->map_tapp != NULL) 22538032Speter map->map_tapp = newstr(map->map_tapp); 22638032Speter if (map->map_keycolnm != NULL) 22738032Speter map->map_keycolnm = newstr(map->map_keycolnm); 22838032Speter if (map->map_valcolnm != NULL) 22938032Speter map->map_valcolnm = newstr(map->map_valcolnm); 23038032Speter 23138032Speter if (*p != '\0') 23238032Speter { 23338032Speter map->map_file = p; 23438032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 23538032Speter p++; 23638032Speter if (*p != '\0') 23738032Speter *p++ = '\0'; 23838032Speter map->map_file = newstr(map->map_file); 23938032Speter } 24038032Speter 24138032Speter while (*p != '\0' && isascii(*p) && isspace(*p)) 24238032Speter p++; 24338032Speter if (*p != '\0') 24438032Speter map->map_rebuild = newstr(p); 24538032Speter 24638032Speter if (map->map_file == NULL && 24738032Speter !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 24838032Speter { 24938032Speter syserr("No file name for %s map %s", 25038032Speter map->map_class->map_cname, map->map_mname); 25138032Speter return FALSE; 25238032Speter } 25338032Speter return TRUE; 25438032Speter} 25538032Speter/* 25638032Speter** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 25738032Speter** 25838032Speter** It also adds the map_app string. It can be used as a utility 25938032Speter** in the map_lookup method. 26038032Speter** 26138032Speter** Parameters: 26238032Speter** map -- the map that causes this. 26338032Speter** s -- the string to rewrite, NOT necessarily null terminated. 26438032Speter** slen -- the length of s. 26538032Speter** av -- arguments to interpolate into buf. 26638032Speter** 26738032Speter** Returns: 26838032Speter** Pointer to rewritten result. This is static data that 26938032Speter** should be copied if it is to be saved! 27038032Speter** 27138032Speter** Side Effects: 27238032Speter** none. 27338032Speter*/ 27438032Speter 27538032Speterchar * 27638032Spetermap_rewrite(map, s, slen, av) 27738032Speter register MAP *map; 27838032Speter register const char *s; 27938032Speter size_t slen; 28038032Speter char **av; 28138032Speter{ 28238032Speter register char *bp; 28338032Speter register char c; 28438032Speter char **avp; 28538032Speter register char *ap; 28638032Speter size_t l; 28738032Speter size_t len; 28838032Speter static size_t buflen = 0; 28938032Speter static char *buf = NULL; 29038032Speter 29138032Speter if (tTd(39, 1)) 29238032Speter { 29338032Speter printf("map_rewrite(%.*s), av =", (int)slen, s); 29438032Speter if (av == NULL) 29538032Speter printf(" (nullv)"); 29638032Speter else 29738032Speter { 29838032Speter for (avp = av; *avp != NULL; avp++) 29938032Speter printf("\n\t%s", *avp); 30038032Speter } 30138032Speter printf("\n"); 30238032Speter } 30338032Speter 30438032Speter /* count expected size of output (can safely overestimate) */ 30538032Speter l = len = slen; 30638032Speter if (av != NULL) 30738032Speter { 30838032Speter const char *sp = s; 30938032Speter 31038032Speter while (l-- > 0 && (c = *sp++) != '\0') 31138032Speter { 31238032Speter if (c != '%') 31338032Speter continue; 31438032Speter if (l-- <= 0) 31538032Speter break; 31638032Speter c = *sp++; 31738032Speter if (!(isascii(c) && isdigit(c))) 31838032Speter continue; 31938032Speter for (avp = av; --c >= '0' && *avp != NULL; avp++) 32038032Speter continue; 32138032Speter if (*avp == NULL) 32238032Speter continue; 32338032Speter len += strlen(*avp); 32438032Speter } 32538032Speter } 32638032Speter if (map->map_app != NULL) 32738032Speter len += strlen(map->map_app); 32838032Speter if (buflen < ++len) 32938032Speter { 33038032Speter /* need to malloc additional space */ 33138032Speter buflen = len; 33238032Speter if (buf != NULL) 33338032Speter free(buf); 33438032Speter buf = xalloc(buflen); 33538032Speter } 33638032Speter 33738032Speter bp = buf; 33838032Speter if (av == NULL) 33938032Speter { 34038032Speter bcopy(s, bp, slen); 34138032Speter bp += slen; 34238032Speter } 34338032Speter else 34438032Speter { 34538032Speter while (slen-- > 0 && (c = *s++) != '\0') 34638032Speter { 34738032Speter if (c != '%') 34838032Speter { 34938032Speter pushc: 35038032Speter *bp++ = c; 35138032Speter continue; 35238032Speter } 35338032Speter if (slen-- <= 0 || (c = *s++) == '\0') 35438032Speter c = '%'; 35538032Speter if (c == '%') 35638032Speter goto pushc; 35738032Speter if (!(isascii(c) && isdigit(c))) 35838032Speter { 35938032Speter *bp++ = '%'; 36038032Speter goto pushc; 36138032Speter } 36238032Speter for (avp = av; --c >= '0' && *avp != NULL; avp++) 36338032Speter continue; 36438032Speter if (*avp == NULL) 36538032Speter continue; 36638032Speter 36738032Speter /* transliterate argument into output string */ 36838032Speter for (ap = *avp; (c = *ap++) != '\0'; ) 36938032Speter *bp++ = c; 37038032Speter } 37138032Speter } 37238032Speter if (map->map_app != NULL) 37338032Speter strcpy(bp, map->map_app); 37438032Speter else 37538032Speter *bp = '\0'; 37638032Speter if (tTd(39, 1)) 37738032Speter printf("map_rewrite => %s\n", buf); 37838032Speter return buf; 37938032Speter} 38038032Speter/* 38138032Speter** INITMAPS -- initialize for aliasing 38238032Speter** 38338032Speter** Parameters: 38438032Speter** rebuild -- if TRUE, this rebuilds the cached versions. 38538032Speter** e -- current envelope. 38638032Speter** 38738032Speter** Returns: 38838032Speter** none. 38938032Speter** 39038032Speter** Side Effects: 39138032Speter** initializes aliases: 39238032Speter** if alias database: opens the database. 39338032Speter** if no database available: reads aliases into the symbol table. 39438032Speter*/ 39538032Speter 39638032Spetervoid 39738032Speterinitmaps(rebuild, e) 39838032Speter bool rebuild; 39938032Speter register ENVELOPE *e; 40038032Speter{ 40138032Speter extern void map_init __P((STAB *, int)); 40238032Speter 40338032Speter#if XDEBUG 40438032Speter checkfd012("entering initmaps"); 40538032Speter#endif 40638032Speter CurEnv = e; 40738032Speter 40838032Speter stabapply(map_init, 0); 40938032Speter stabapply(map_init, rebuild ? 2 : 1); 41038032Speter#if XDEBUG 41138032Speter checkfd012("exiting initmaps"); 41238032Speter#endif 41338032Speter} 41438032Speter 41538032Spetervoid 41638032Spetermap_init(s, pass) 41738032Speter register STAB *s; 41838032Speter int pass; 41938032Speter{ 42038032Speter bool rebuildable; 42138032Speter register MAP *map; 42238032Speter 42338032Speter /* has to be a map */ 42438032Speter if (s->s_type != ST_MAP) 42538032Speter return; 42638032Speter 42738032Speter map = &s->s_map; 42838032Speter if (!bitset(MF_VALID, map->map_mflags)) 42938032Speter return; 43038032Speter 43138032Speter if (tTd(38, 2)) 43238032Speter printf("map_init(%s:%s, %s, %d)\n", 43338032Speter map->map_class->map_cname == NULL ? "NULL" : 43438032Speter map->map_class->map_cname, 43538032Speter map->map_mname == NULL ? "NULL" : map->map_mname, 43638032Speter map->map_file == NULL ? "NULL" : map->map_file, 43738032Speter pass); 43838032Speter 43938032Speter /* 44038032Speter ** Pass 0 opens all non-rebuildable maps. 44138032Speter ** Pass 1 opens all rebuildable maps for read. 44238032Speter ** Pass 2 rebuilds all rebuildable maps. 44338032Speter */ 44438032Speter 44538032Speter rebuildable = (bitset(MF_ALIAS, map->map_mflags) && 44638032Speter bitset(MCF_REBUILDABLE, map->map_class->map_cflags)); 44738032Speter 44838032Speter if ((pass == 0 && rebuildable) || 44938032Speter ((pass == 1 || pass == 2) && !rebuildable)) 45038032Speter { 45138032Speter if (tTd(38, 3)) 45238032Speter printf("\twrong pass (pass = %d, rebuildable = %d)\n", 45338032Speter pass, rebuildable); 45438032Speter return; 45538032Speter } 45638032Speter 45738032Speter /* if already open, close it (for nested open) */ 45838032Speter if (bitset(MF_OPEN, map->map_mflags)) 45938032Speter { 46038032Speter map->map_class->map_close(map); 46138032Speter map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 46238032Speter } 46338032Speter 46438032Speter if (pass == 2) 46538032Speter { 46638032Speter (void) rebuildaliases(map, FALSE); 46738032Speter return; 46838032Speter } 46938032Speter 47038032Speter if (map->map_class->map_open(map, O_RDONLY)) 47138032Speter { 47238032Speter if (tTd(38, 4)) 47338032Speter printf("\t%s:%s %s: valid\n", 47438032Speter map->map_class->map_cname == NULL ? "NULL" : 47538032Speter map->map_class->map_cname, 47638032Speter map->map_mname == NULL ? "NULL" : 47738032Speter map->map_mname, 47838032Speter map->map_file == NULL ? "NULL" : 47938032Speter map->map_file); 48038032Speter map->map_mflags |= MF_OPEN; 48138032Speter } 48238032Speter else 48338032Speter { 48438032Speter if (tTd(38, 4)) 48538032Speter printf("\t%s:%s %s: invalid: %s\n", 48638032Speter map->map_class->map_cname == NULL ? "NULL" : 48738032Speter map->map_class->map_cname, 48838032Speter map->map_mname == NULL ? "NULL" : 48938032Speter map->map_mname, 49038032Speter map->map_file == NULL ? "NULL" : 49138032Speter map->map_file, 49238032Speter errstring(errno)); 49338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 49438032Speter { 49538032Speter extern MAPCLASS BogusMapClass; 49638032Speter 49738032Speter map->map_class = &BogusMapClass; 49838032Speter map->map_mflags |= MF_OPEN; 49938032Speter } 50038032Speter } 50138032Speter} 50238032Speter/* 50338032Speter** GETCANONNAME -- look up name using service switch 50438032Speter** 50538032Speter** Parameters: 50638032Speter** host -- the host name to look up. 50738032Speter** hbsize -- the size of the host buffer. 50838032Speter** trymx -- if set, try MX records. 50938032Speter** 51038032Speter** Returns: 51138032Speter** TRUE -- if the host was found. 51238032Speter** FALSE -- otherwise. 51338032Speter*/ 51438032Speter 51538032Speterbool 51638032Spetergetcanonname(host, hbsize, trymx) 51738032Speter char *host; 51838032Speter int hbsize; 51938032Speter bool trymx; 52038032Speter{ 52138032Speter int nmaps; 52238032Speter int mapno; 52338032Speter bool found = FALSE; 52438032Speter bool got_tempfail = FALSE; 52538032Speter auto int stat; 52638032Speter char *maptype[MAXMAPSTACK]; 52738032Speter short mapreturn[MAXMAPACTIONS]; 52838032Speter 52938032Speter nmaps = switch_map_find("hosts", maptype, mapreturn); 53038032Speter for (mapno = 0; mapno < nmaps; mapno++) 53138032Speter { 53238032Speter int i; 53338032Speter 53438032Speter if (tTd(38, 20)) 53538032Speter printf("getcanonname(%s), trying %s\n", 53638032Speter host, maptype[mapno]); 53738032Speter if (strcmp("files", maptype[mapno]) == 0) 53838032Speter { 53938032Speter extern bool text_getcanonname __P((char *, int, int *)); 54038032Speter 54138032Speter found = text_getcanonname(host, hbsize, &stat); 54238032Speter } 54338032Speter#ifdef NIS 54438032Speter else if (strcmp("nis", maptype[mapno]) == 0) 54538032Speter { 54638032Speter extern bool nis_getcanonname __P((char *, int, int *)); 54738032Speter 54838032Speter found = nis_getcanonname(host, hbsize, &stat); 54938032Speter } 55038032Speter#endif 55138032Speter#ifdef NISPLUS 55238032Speter else if (strcmp("nisplus", maptype[mapno]) == 0) 55338032Speter { 55438032Speter extern bool nisplus_getcanonname __P((char *, int, int *)); 55538032Speter 55638032Speter found = nisplus_getcanonname(host, hbsize, &stat); 55738032Speter } 55838032Speter#endif 55938032Speter#if NAMED_BIND 56038032Speter else if (strcmp("dns", maptype[mapno]) == 0) 56138032Speter { 56238032Speter extern bool dns_getcanonname __P((char *, int, bool, int *)); 56338032Speter 56438032Speter found = dns_getcanonname(host, hbsize, trymx, &stat); 56538032Speter } 56638032Speter#endif 56738032Speter#if NETINFO 56838032Speter else if (strcmp("netinfo", maptype[mapno]) == 0) 56938032Speter { 57038032Speter extern bool ni_getcanonname __P((char *, int, int *)); 57138032Speter 57238032Speter found = ni_getcanonname(host, hbsize, &stat); 57338032Speter } 57438032Speter#endif 57538032Speter else 57638032Speter { 57738032Speter found = FALSE; 57838032Speter stat = EX_UNAVAILABLE; 57938032Speter } 58038032Speter 58138032Speter /* 58238032Speter ** Heuristic: if $m is not set, we are running during system 58338032Speter ** startup. In this case, when a name is apparently found 58438032Speter ** but has no dot, treat is as not found. This avoids 58538032Speter ** problems if /etc/hosts has no FQDN but is listed first 58638032Speter ** in the service switch. 58738032Speter */ 58838032Speter 58938032Speter if (found && 59038032Speter (macvalue('m', CurEnv) != NULL || strchr(host, '.') != NULL)) 59138032Speter break; 59238032Speter 59338032Speter /* see if we should continue */ 59438032Speter if (stat == EX_TEMPFAIL) 59538032Speter { 59638032Speter i = MA_TRYAGAIN; 59738032Speter got_tempfail = TRUE; 59838032Speter } 59938032Speter else if (stat == EX_NOTFOUND) 60038032Speter i = MA_NOTFOUND; 60138032Speter else 60238032Speter i = MA_UNAVAIL; 60338032Speter if (bitset(1 << mapno, mapreturn[i])) 60438032Speter break; 60538032Speter } 60638032Speter 60738032Speter if (found) 60838032Speter { 60938032Speter char *d; 61038032Speter 61138032Speter if (tTd(38, 20)) 61238032Speter printf("getcanonname(%s), found\n", host); 61338032Speter 61438032Speter /* 61538032Speter ** If returned name is still single token, compensate 61638032Speter ** by tagging on $m. This is because some sites set 61738032Speter ** up their DNS or NIS databases wrong. 61838032Speter */ 61938032Speter 62038032Speter if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 62138032Speter { 62238032Speter d = macvalue('m', CurEnv); 62338032Speter if (d != NULL && 62438032Speter hbsize > (int) (strlen(host) + strlen(d) + 1)) 62538032Speter { 62638032Speter if (host[strlen(host) - 1] != '.') 62738032Speter strcat(host, "."); 62838032Speter strcat(host, d); 62938032Speter } 63038032Speter else 63138032Speter { 63238032Speter return FALSE; 63338032Speter } 63438032Speter } 63538032Speter return TRUE; 63638032Speter } 63738032Speter 63838032Speter if (tTd(38, 20)) 63938032Speter printf("getcanonname(%s), failed, stat=%d\n", host, stat); 64038032Speter 64138032Speter#if NAMED_BIND 64238032Speter if (got_tempfail) 64338032Speter h_errno = TRY_AGAIN; 64438032Speter else 64538032Speter h_errno = HOST_NOT_FOUND; 64638032Speter#endif 64738032Speter 64838032Speter return FALSE; 64938032Speter} 65038032Speter/* 65138032Speter** EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry 65238032Speter** 65338032Speter** Parameters: 65438032Speter** name -- the name against which to match. 65538032Speter** line -- the /etc/hosts line. 65638032Speter** cbuf -- the location to store the result. 65738032Speter** cbuflen -- the size of cbuf. 65838032Speter** 65938032Speter** Returns: 66038032Speter** TRUE -- if the line matched the desired name. 66138032Speter** FALSE -- otherwise. 66238032Speter*/ 66338032Speter 66438032Speterbool 66538032Speterextract_canonname(name, line, cbuf, cbuflen) 66638032Speter char *name; 66738032Speter char *line; 66838032Speter char cbuf[]; 66938032Speter int cbuflen; 67038032Speter{ 67138032Speter int i; 67238032Speter char *p; 67338032Speter bool found = FALSE; 67438032Speter extern char *get_column __P((char *, int, char, char *, int)); 67538032Speter 67638032Speter cbuf[0] = '\0'; 67738032Speter if (line[0] == '#') 67838032Speter return FALSE; 67938032Speter 68038032Speter for (i = 1; ; i++) 68138032Speter { 68238032Speter char nbuf[MAXNAME + 1]; 68338032Speter 68438032Speter p = get_column(line, i, '\0', nbuf, sizeof nbuf); 68538032Speter if (p == NULL) 68638032Speter break; 68738032Speter if (*p == '\0') 68838032Speter continue; 68938032Speter if (cbuf[0] == '\0' || 69038032Speter (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL)) 69138032Speter { 69238032Speter snprintf(cbuf, cbuflen, "%s", p); 69338032Speter } 69438032Speter if (strcasecmp(name, p) == 0) 69538032Speter found = TRUE; 69638032Speter } 69738032Speter if (found && strchr(cbuf, '.') == NULL) 69838032Speter { 69938032Speter /* try to add a domain on the end of the name */ 70038032Speter char *domain = macvalue('m', CurEnv); 70138032Speter 70238032Speter if (domain != NULL && 70338032Speter strlen(domain) + strlen(cbuf) + 1 < cbuflen) 70438032Speter { 70538032Speter p = &cbuf[strlen(cbuf)]; 70638032Speter *p++ = '.'; 70738032Speter strcpy(p, domain); 70838032Speter } 70938032Speter } 71038032Speter return found; 71138032Speter} 71238032Speter/* 71338032Speter** NDBM modules 71438032Speter*/ 71538032Speter 71638032Speter#ifdef NDBM 71738032Speter 71838032Speter/* 71938032Speter** NDBM_MAP_OPEN -- DBM-style map open 72038032Speter*/ 72138032Speter 72238032Speterbool 72338032Speterndbm_map_open(map, mode) 72438032Speter MAP *map; 72538032Speter int mode; 72638032Speter{ 72738032Speter register DBM *dbm; 72838032Speter struct stat st; 72938032Speter int dfd; 73038032Speter int pfd; 73138032Speter int sff; 73238032Speter int ret; 73338032Speter int smode = S_IREAD; 73438032Speter char dirfile[MAXNAME + 1]; 73538032Speter char pagfile[MAXNAME + 1]; 73638032Speter struct stat std, stp; 73738032Speter 73838032Speter if (tTd(38, 2)) 73938032Speter printf("ndbm_map_open(%s, %s, %d)\n", 74038032Speter map->map_mname, map->map_file, mode); 74138032Speter map->map_lockfd = -1; 74238032Speter mode &= O_ACCMODE; 74338032Speter 74438032Speter /* do initial file and directory checks */ 74538032Speter snprintf(dirfile, sizeof dirfile, "%s.dir", map->map_file); 74638032Speter snprintf(pagfile, sizeof pagfile, "%s.pag", map->map_file); 74738032Speter sff = SFF_ROOTOK|SFF_REGONLY; 74838032Speter if (mode == O_RDWR) 74938032Speter { 75038032Speter sff |= SFF_CREAT; 75138032Speter if (!bitset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 75238032Speter sff |= SFF_NOSLINK; 75338032Speter if (!bitset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 75438032Speter sff |= SFF_NOHLINK; 75538032Speter smode = S_IWRITE; 75638032Speter } 75738032Speter else 75838032Speter { 75938032Speter if (!bitset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 76038032Speter sff |= SFF_NOWLINK; 76138032Speter } 76238032Speter if (!bitset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 76338032Speter sff |= SFF_SAFEDIRPATH; 76438032Speter ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName, 76538032Speter sff, smode, &std); 76638032Speter if (ret == 0) 76738032Speter ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName, 76838032Speter sff, smode, &stp); 76938032Speter if (ret == ENOENT && AutoRebuild && 77038032Speter bitset(MCF_REBUILDABLE, map->map_class->map_cflags) && 77138032Speter (bitset(MF_IMPL_NDBM, map->map_mflags) || 77238032Speter bitset(MF_ALIAS, map->map_mflags)) && 77338032Speter mode == O_RDONLY) 77438032Speter { 77538032Speter bool impl = bitset(MF_IMPL_NDBM, map->map_mflags); 77638032Speter extern bool impl_map_open __P((MAP *, int)); 77738032Speter 77838032Speter /* may be able to rebuild */ 77938032Speter map->map_mflags &= ~MF_IMPL_NDBM; 78038032Speter if (!rebuildaliases(map, TRUE)) 78138032Speter return FALSE; 78238032Speter if (impl) 78338032Speter return impl_map_open(map, O_RDONLY); 78438032Speter else 78538032Speter return ndbm_map_open(map, O_RDONLY); 78638032Speter } 78738032Speter if (ret != 0) 78838032Speter { 78938032Speter char *prob = "unsafe"; 79038032Speter 79138032Speter /* cannot open this map */ 79238032Speter if (ret == ENOENT) 79338032Speter prob = "missing"; 79438032Speter if (tTd(38, 2)) 79538032Speter printf("\t%s map file: %d\n", prob, ret); 79638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 79738032Speter syserr("dbm map \"%s\": %s map file %s", 79838032Speter map->map_mname, prob, map->map_file); 79938032Speter return FALSE; 80038032Speter } 80138032Speter if (std.st_mode == ST_MODE_NOFILE) 80238032Speter mode |= O_CREAT|O_EXCL; 80338032Speter 80438032Speter#if LOCK_ON_OPEN 80538032Speter if (mode == O_RDONLY) 80638032Speter mode |= O_SHLOCK; 80738032Speter else 80838032Speter mode |= O_TRUNC|O_EXLOCK; 80938032Speter#else 81038032Speter if ((mode & O_ACCMODE) == O_RDWR) 81138032Speter { 81238032Speter# if NOFTRUNCATE 81338032Speter /* 81438032Speter ** Warning: race condition. Try to lock the file as 81538032Speter ** quickly as possible after opening it. 81638032Speter ** This may also have security problems on some systems, 81738032Speter ** but there isn't anything we can do about it. 81838032Speter */ 81938032Speter 82038032Speter mode |= O_TRUNC; 82138032Speter# else 82238032Speter /* 82338032Speter ** This ugly code opens the map without truncating it, 82438032Speter ** locks the file, then truncates it. Necessary to 82538032Speter ** avoid race conditions. 82638032Speter */ 82738032Speter 82838032Speter int dirfd; 82938032Speter int pagfd; 83038032Speter int sff = SFF_CREAT|SFF_OPENASROOT; 83138032Speter 83238032Speter if (!bitset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 83338032Speter sff |= SFF_NOSLINK; 83438032Speter if (!bitset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 83538032Speter sff |= SFF_NOHLINK; 83638032Speter 83738032Speter dirfd = safeopen(dirfile, mode, DBMMODE, sff); 83838032Speter pagfd = safeopen(pagfile, mode, DBMMODE, sff); 83938032Speter 84038032Speter if (dirfd < 0 || pagfd < 0) 84138032Speter { 84238032Speter int save_errno = errno; 84338032Speter 84438032Speter if (dirfd >= 0) 84538032Speter (void) close(dirfd); 84638032Speter if (pagfd >= 0) 84738032Speter (void) close(pagfd); 84838032Speter errno = save_errno; 84938032Speter syserr("ndbm_map_open: cannot create database %s", 85038032Speter map->map_file); 85138032Speter return FALSE; 85238032Speter } 85338032Speter if (ftruncate(dirfd, (off_t) 0) < 0 || 85438032Speter ftruncate(pagfd, (off_t) 0) < 0) 85538032Speter { 85638032Speter int save_errno = errno; 85738032Speter 85838032Speter (void) close(dirfd); 85938032Speter (void) close(pagfd); 86038032Speter errno = save_errno; 86138032Speter syserr("ndbm_map_open: cannot truncate %s.{dir,pag}", 86238032Speter map->map_file); 86338032Speter return FALSE; 86438032Speter } 86538032Speter 86638032Speter /* if new file, get "before" bits for later filechanged check */ 86738032Speter if (std.st_mode == ST_MODE_NOFILE && 86838032Speter (fstat(dirfd, &std) < 0 || fstat(pagfd, &stp) < 0)) 86938032Speter { 87038032Speter int save_errno = errno; 87138032Speter 87238032Speter (void) close(dirfd); 87338032Speter (void) close(pagfd); 87438032Speter errno = save_errno; 87538032Speter syserr("ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file", 87638032Speter map->map_file); 87738032Speter return FALSE; 87838032Speter } 87938032Speter 88038032Speter /* have to save the lock for the duration (bletch) */ 88138032Speter map->map_lockfd = dirfd; 88238032Speter close(pagfd); 88338032Speter 88438032Speter /* twiddle bits for dbm_open */ 88538032Speter mode &= ~(O_CREAT|O_EXCL); 88638032Speter# endif 88738032Speter } 88838032Speter#endif 88938032Speter 89038032Speter /* open the database */ 89138032Speter dbm = dbm_open(map->map_file, mode, DBMMODE); 89238032Speter if (dbm == NULL) 89338032Speter { 89438032Speter int save_errno = errno; 89538032Speter 89638032Speter if (bitset(MF_ALIAS, map->map_mflags) && 89738032Speter aliaswait(map, ".pag", FALSE)) 89838032Speter return TRUE; 89938032Speter#if !LOCK_ON_OPEN && !NOFTRUNCATE 90038032Speter if (map->map_lockfd >= 0) 90138032Speter close(map->map_lockfd); 90238032Speter#endif 90338032Speter errno = save_errno; 90438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 90538032Speter syserr("Cannot open DBM database %s", map->map_file); 90638032Speter return FALSE; 90738032Speter } 90838032Speter dfd = dbm_dirfno(dbm); 90938032Speter pfd = dbm_pagfno(dbm); 91038032Speter if (dfd == pfd) 91138032Speter { 91238032Speter /* heuristic: if files are linked, this is actually gdbm */ 91338032Speter dbm_close(dbm); 91438032Speter#if !LOCK_ON_OPEN && !NOFTRUNCATE 91538032Speter if (map->map_lockfd >= 0) 91638032Speter close(map->map_lockfd); 91738032Speter#endif 91838032Speter errno = 0; 91938032Speter syserr("dbm map \"%s\": cannot support GDBM", 92038032Speter map->map_mname); 92138032Speter return FALSE; 92238032Speter } 92338032Speter 92438032Speter if (filechanged(dirfile, dfd, &std) || 92538032Speter filechanged(pagfile, pfd, &stp)) 92638032Speter { 92738032Speter int save_errno = errno; 92838032Speter 92938032Speter dbm_close(dbm); 93038032Speter#if !LOCK_ON_OPEN && !NOFTRUNCATE 93138032Speter if (map->map_lockfd >= 0) 93238032Speter close(map->map_lockfd); 93338032Speter#endif 93438032Speter errno = save_errno; 93538032Speter syserr("ndbm_map_open(%s): file changed after open", 93638032Speter map->map_file); 93738032Speter return FALSE; 93838032Speter } 93938032Speter 94038032Speter map->map_db1 = (ARBPTR_T) dbm; 94138032Speter if (mode == O_RDONLY) 94238032Speter { 94338032Speter#if LOCK_ON_OPEN 94438032Speter if (dfd >= 0) 94538032Speter (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 94638032Speter if (pfd >= 0) 94738032Speter (void) lockfile(pfd, map->map_file, ".pag", LOCK_UN); 94838032Speter#endif 94938032Speter if (bitset(MF_ALIAS, map->map_mflags) && 95038032Speter !aliaswait(map, ".pag", TRUE)) 95138032Speter return FALSE; 95238032Speter } 95338032Speter else 95438032Speter { 95538032Speter map->map_mflags |= MF_LOCKED; 95638032Speter if (geteuid() == 0 && TrustedFileUid != 0) 95738032Speter { 95838032Speter if (fchown(dfd, TrustedFileUid, -1) < 0 || 95938032Speter fchown(pfd, TrustedFileUid, -1) < 0) 96038032Speter { 96138032Speter int err = errno; 96238032Speter 96338032Speter sm_syslog(LOG_ALERT, NOQID, 96438032Speter "ownership change on %s failed: %s", 96538032Speter map->map_file, errstring(err)); 96638032Speter message("050 ownership change on %s failed: %s", 96738032Speter map->map_file, errstring(err)); 96838032Speter } 96938032Speter } 97038032Speter } 97138032Speter if (fstat(dfd, &st) >= 0) 97238032Speter map->map_mtime = st.st_mtime; 97338032Speter return TRUE; 97438032Speter} 97538032Speter 97638032Speter 97738032Speter/* 97838032Speter** NDBM_MAP_LOOKUP -- look up a datum in a DBM-type map 97938032Speter*/ 98038032Speter 98138032Speterchar * 98238032Speterndbm_map_lookup(map, name, av, statp) 98338032Speter MAP *map; 98438032Speter char *name; 98538032Speter char **av; 98638032Speter int *statp; 98738032Speter{ 98838032Speter datum key, val; 98938032Speter int fd; 99038032Speter char keybuf[MAXNAME + 1]; 99138032Speter struct stat stbuf; 99238032Speter 99338032Speter if (tTd(38, 20)) 99438032Speter printf("ndbm_map_lookup(%s, %s)\n", 99538032Speter map->map_mname, name); 99638032Speter 99738032Speter key.dptr = name; 99838032Speter key.dsize = strlen(name); 99938032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 100038032Speter { 100138032Speter if (key.dsize > sizeof keybuf - 1) 100238032Speter key.dsize = sizeof keybuf - 1; 100338032Speter bcopy(key.dptr, keybuf, key.dsize); 100438032Speter keybuf[key.dsize] = '\0'; 100538032Speter makelower(keybuf); 100638032Speter key.dptr = keybuf; 100738032Speter } 100838032Speterlockdbm: 100938032Speter fd = dbm_dirfno((DBM *) map->map_db1); 101038032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 101138032Speter (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 101238032Speter if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) 101338032Speter { 101438032Speter /* Reopen the database to sync the cache */ 101538032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 101638032Speter : O_RDONLY; 101738032Speter 101838032Speter map->map_class->map_close(map); 101938032Speter map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 102038032Speter if (map->map_class->map_open(map, omode)) 102138032Speter { 102238032Speter map->map_mflags |= MF_OPEN; 102338032Speter if ((omode && O_ACCMODE) == O_RDWR) 102438032Speter map->map_mflags |= MF_WRITABLE; 102538032Speter goto lockdbm; 102638032Speter } 102738032Speter else 102838032Speter { 102938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 103038032Speter { 103138032Speter extern MAPCLASS BogusMapClass; 103238032Speter 103338032Speter *statp = EX_TEMPFAIL; 103438032Speter map->map_class = &BogusMapClass; 103538032Speter map->map_mflags |= MF_OPEN; 103638032Speter syserr("Cannot reopen NDBM database %s", 103738032Speter map->map_file); 103838032Speter } 103938032Speter return NULL; 104038032Speter } 104138032Speter } 104238032Speter val.dptr = NULL; 104338032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 104438032Speter { 104538032Speter val = dbm_fetch((DBM *) map->map_db1, key); 104638032Speter if (val.dptr != NULL) 104738032Speter map->map_mflags &= ~MF_TRY1NULL; 104838032Speter } 104938032Speter if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 105038032Speter { 105138032Speter key.dsize++; 105238032Speter val = dbm_fetch((DBM *) map->map_db1, key); 105338032Speter if (val.dptr != NULL) 105438032Speter map->map_mflags &= ~MF_TRY0NULL; 105538032Speter } 105638032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 105738032Speter (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 105838032Speter if (val.dptr == NULL) 105938032Speter return NULL; 106038032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 106138032Speter return map_rewrite(map, name, strlen(name), NULL); 106238032Speter else 106338032Speter return map_rewrite(map, val.dptr, val.dsize, av); 106438032Speter} 106538032Speter 106638032Speter 106738032Speter/* 106838032Speter** NDBM_MAP_STORE -- store a datum in the database 106938032Speter*/ 107038032Speter 107138032Spetervoid 107238032Speterndbm_map_store(map, lhs, rhs) 107338032Speter register MAP *map; 107438032Speter char *lhs; 107538032Speter char *rhs; 107638032Speter{ 107738032Speter datum key; 107838032Speter datum data; 107938032Speter int stat; 108038032Speter char keybuf[MAXNAME + 1]; 108138032Speter 108238032Speter if (tTd(38, 12)) 108338032Speter printf("ndbm_map_store(%s, %s, %s)\n", 108438032Speter map->map_mname, lhs, rhs); 108538032Speter 108638032Speter key.dsize = strlen(lhs); 108738032Speter key.dptr = lhs; 108838032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 108938032Speter { 109038032Speter if (key.dsize > sizeof keybuf - 1) 109138032Speter key.dsize = sizeof keybuf - 1; 109238032Speter bcopy(key.dptr, keybuf, key.dsize); 109338032Speter keybuf[key.dsize] = '\0'; 109438032Speter makelower(keybuf); 109538032Speter key.dptr = keybuf; 109638032Speter } 109738032Speter 109838032Speter data.dsize = strlen(rhs); 109938032Speter data.dptr = rhs; 110038032Speter 110138032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 110238032Speter { 110338032Speter key.dsize++; 110438032Speter data.dsize++; 110538032Speter } 110638032Speter 110738032Speter stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 110838032Speter if (stat > 0) 110938032Speter { 111038032Speter if (!bitset(MF_APPEND, map->map_mflags)) 111138032Speter message("050 Warning: duplicate alias name %s", lhs); 111238032Speter else 111338032Speter { 111438032Speter static char *buf = NULL; 111538032Speter static int bufsiz = 0; 111638032Speter auto int xstat; 111738032Speter datum old; 111838032Speter 111938032Speter old.dptr = ndbm_map_lookup(map, key.dptr, 112038032Speter (char **)NULL, &xstat); 112138032Speter if (old.dptr != NULL && *(char *) old.dptr != '\0') 112238032Speter { 112338032Speter old.dsize = strlen(old.dptr); 112438032Speter if (data.dsize + old.dsize + 2 > bufsiz) 112538032Speter { 112638032Speter if (buf != NULL) 112738032Speter (void) free(buf); 112838032Speter bufsiz = data.dsize + old.dsize + 2; 112938032Speter buf = xalloc(bufsiz); 113038032Speter } 113138032Speter snprintf(buf, bufsiz, "%s,%s", 113238032Speter data.dptr, old.dptr); 113338032Speter data.dsize = data.dsize + old.dsize + 1; 113438032Speter data.dptr = buf; 113538032Speter if (tTd(38, 9)) 113638032Speter printf("ndbm_map_store append=%s\n", data.dptr); 113738032Speter } 113838032Speter } 113938032Speter stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 114038032Speter } 114138032Speter if (stat != 0) 114238032Speter syserr("readaliases: dbm put (%s)", lhs); 114338032Speter} 114438032Speter 114538032Speter 114638032Speter/* 114738032Speter** NDBM_MAP_CLOSE -- close the database 114838032Speter*/ 114938032Speter 115038032Spetervoid 115138032Speterndbm_map_close(map) 115238032Speter register MAP *map; 115338032Speter{ 115438032Speter if (tTd(38, 9)) 115538032Speter printf("ndbm_map_close(%s, %s, %lx)\n", 115638032Speter map->map_mname, map->map_file, map->map_mflags); 115738032Speter 115838032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 115938032Speter { 116038032Speter#ifdef NDBM_YP_COMPAT 116138032Speter bool inclnull; 116238032Speter char buf[200]; 116338032Speter 116438032Speter inclnull = bitset(MF_INCLNULL, map->map_mflags); 116538032Speter map->map_mflags &= ~MF_INCLNULL; 116638032Speter 116738032Speter if (strstr(map->map_file, "/yp/") != NULL) 116838032Speter { 116938032Speter long save_mflags = map->map_mflags; 117038032Speter 117138032Speter map->map_mflags |= MF_NOFOLDCASE; 117238032Speter 117338032Speter (void) snprintf(buf, sizeof buf, "%010ld", curtime()); 117438032Speter ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 117538032Speter 117638032Speter (void) gethostname(buf, sizeof buf); 117738032Speter ndbm_map_store(map, "YP_MASTER_NAME", buf); 117838032Speter 117938032Speter map->map_mflags = save_mflags; 118038032Speter } 118138032Speter 118238032Speter if (inclnull) 118338032Speter map->map_mflags |= MF_INCLNULL; 118438032Speter#endif 118538032Speter 118638032Speter /* write out the distinguished alias */ 118738032Speter ndbm_map_store(map, "@", "@"); 118838032Speter } 118938032Speter dbm_close((DBM *) map->map_db1); 119038032Speter 119138032Speter /* release lock (if needed) */ 119238032Speter#if !LOCK_ON_OPEN 119338032Speter if (map->map_lockfd >= 0) 119438032Speter (void) close(map->map_lockfd); 119538032Speter#endif 119638032Speter} 119738032Speter 119838032Speter#endif 119938032Speter/* 120038032Speter** NEWDB (Hash and BTree) Modules 120138032Speter*/ 120238032Speter 120338032Speter#ifdef NEWDB 120438032Speter 120538032Speter/* 120638032Speter** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 120738032Speter** 120838032Speter** These do rather bizarre locking. If you can lock on open, 120938032Speter** do that to avoid the condition of opening a database that 121038032Speter** is being rebuilt. If you don't, we'll try to fake it, but 121138032Speter** there will be a race condition. If opening for read-only, 121238032Speter** we immediately release the lock to avoid freezing things up. 121338032Speter** We really ought to hold the lock, but guarantee that we won't 121438032Speter** be pokey about it. That's hard to do. 121538032Speter*/ 121638032Speter 121738032Speter#if DB_VERSION_MAJOR < 2 121838032Speterextern bool db_map_open __P((MAP *, int, char *, DBTYPE, const void *)); 121938032Speter#else 122038032Speterextern bool db_map_open __P((MAP *, int, char *, DBTYPE, DB_INFO *)); 122138032Speter#endif 122238032Speter 122338032Speter/* these should be K line arguments */ 122438032Speter#if DB_VERSION_MAJOR < 2 122538032Speter# define db_cachesize cachesize 122638032Speter# define h_nelem nelem 122738032Speter# ifndef DB_CACHE_SIZE 122838032Speter# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */ 122938032Speter# endif 123038032Speter# ifndef DB_HASH_NELEM 123138032Speter# define DB_HASH_NELEM 4096 /* (starting) size of hash table */ 123238032Speter# endif 123338032Speter#endif 123438032Speter 123538032Speterbool 123638032Speterbt_map_open(map, mode) 123738032Speter MAP *map; 123838032Speter int mode; 123938032Speter{ 124038032Speter#if DB_VERSION_MAJOR < 2 124138032Speter BTREEINFO btinfo; 124238032Speter#else 124338032Speter DB_INFO btinfo; 124438032Speter#endif 124538032Speter 124638032Speter if (tTd(38, 2)) 124738032Speter printf("bt_map_open(%s, %s, %d)\n", 124838032Speter map->map_mname, map->map_file, mode); 124938032Speter 125038032Speter bzero(&btinfo, sizeof btinfo); 125138032Speter#ifdef DB_CACHE_SIZE 125238032Speter btinfo.db_cachesize = DB_CACHE_SIZE; 125338032Speter#endif 125438032Speter return db_map_open(map, mode, "btree", DB_BTREE, &btinfo); 125538032Speter} 125638032Speter 125738032Speterbool 125838032Speterhash_map_open(map, mode) 125938032Speter MAP *map; 126038032Speter int mode; 126138032Speter{ 126238032Speter#if DB_VERSION_MAJOR < 2 126338032Speter HASHINFO hinfo; 126438032Speter#else 126538032Speter DB_INFO hinfo; 126638032Speter#endif 126738032Speter 126838032Speter if (tTd(38, 2)) 126938032Speter printf("hash_map_open(%s, %s, %d)\n", 127038032Speter map->map_mname, map->map_file, mode); 127138032Speter 127238032Speter bzero(&hinfo, sizeof hinfo); 127338032Speter#ifdef DB_HASH_NELEM 127438032Speter hinfo.h_nelem = DB_HASH_NELEM; 127538032Speter#endif 127638032Speter#ifdef DB_CACHE_SIZE 127738032Speter hinfo.db_cachesize = DB_CACHE_SIZE; 127838032Speter#endif 127938032Speter return db_map_open(map, mode, "hash", DB_HASH, &hinfo); 128038032Speter} 128138032Speter 128238032Speterbool 128338032Speterdb_map_open(map, mode, mapclassname, dbtype, openinfo) 128438032Speter MAP *map; 128538032Speter int mode; 128638032Speter char *mapclassname; 128738032Speter DBTYPE dbtype; 128838032Speter#if DB_VERSION_MAJOR < 2 128938032Speter const void *openinfo; 129038032Speter#else 129138032Speter DB_INFO *openinfo; 129238032Speter#endif 129338032Speter{ 129438032Speter DB *db = NULL; 129538032Speter int i; 129638032Speter int omode; 129738032Speter int smode = S_IREAD; 129838032Speter int fd; 129938032Speter int sff; 130038032Speter int saveerrno; 130138032Speter struct stat st; 130238032Speter char buf[MAXNAME + 1]; 130338032Speter 130438032Speter /* do initial file and directory checks */ 130538032Speter snprintf(buf, sizeof buf - 3, "%s", map->map_file); 130638032Speter i = strlen(buf); 130738032Speter if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 130838032Speter (void) strcat(buf, ".db"); 130938032Speter 131038032Speter mode &= O_ACCMODE; 131138032Speter omode = mode; 131238032Speter 131338032Speter sff = SFF_ROOTOK|SFF_REGONLY; 131438032Speter if (mode == O_RDWR) 131538032Speter { 131638032Speter sff |= SFF_CREAT; 131738032Speter if (!bitset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 131838032Speter sff |= SFF_NOSLINK; 131938032Speter if (!bitset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 132038032Speter sff |= SFF_NOHLINK; 132138032Speter smode = S_IWRITE; 132238032Speter } 132338032Speter else 132438032Speter { 132538032Speter if (!bitset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 132638032Speter sff |= SFF_NOWLINK; 132738032Speter } 132838032Speter if (!bitset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 132938032Speter sff |= SFF_SAFEDIRPATH; 133038032Speter i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st); 133138032Speter if (i == ENOENT && AutoRebuild && 133238032Speter bitset(MCF_REBUILDABLE, map->map_class->map_cflags) && 133338032Speter (bitset(MF_IMPL_HASH, map->map_mflags) || 133438032Speter bitset(MF_ALIAS, map->map_mflags)) && 133538032Speter mode == O_RDONLY) 133638032Speter { 133738032Speter bool impl = bitset(MF_IMPL_HASH, map->map_mflags); 133838032Speter extern bool impl_map_open __P((MAP *, int)); 133938032Speter 134038032Speter /* may be able to rebuild */ 134138032Speter map->map_mflags &= ~MF_IMPL_HASH; 134238032Speter if (!rebuildaliases(map, TRUE)) 134338032Speter return FALSE; 134438032Speter if (impl) 134538032Speter return impl_map_open(map, O_RDONLY); 134638032Speter else 134738032Speter return db_map_open(map, O_RDONLY, mapclassname, 134838032Speter dbtype, openinfo); 134938032Speter } 135038032Speter 135138032Speter if (i != 0) 135238032Speter { 135338032Speter char *prob = "unsafe"; 135438032Speter 135538032Speter /* cannot open this map */ 135638032Speter if (i == ENOENT) 135738032Speter prob = "missing"; 135838032Speter if (tTd(38, 2)) 135938032Speter printf("\t%s map file: %s\n", prob, errstring(i)); 136038032Speter errno = i; 136138032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 136238032Speter syserr("%s map \"%s\": %s map file %s", 136338032Speter mapclassname, map->map_mname, prob, buf); 136438032Speter return FALSE; 136538032Speter } 136638032Speter if (st.st_mode == ST_MODE_NOFILE) 136738032Speter omode |= O_CREAT|O_EXCL; 136838032Speter 136938032Speter map->map_lockfd = -1; 137038032Speter 137138032Speter#if LOCK_ON_OPEN 137238032Speter if (mode == O_RDWR) 137338032Speter omode |= O_TRUNC|O_EXLOCK; 137438032Speter else 137538032Speter omode |= O_SHLOCK; 137638032Speter#else 137738032Speter /* 137838032Speter ** Pre-lock the file to avoid race conditions. In particular, 137938032Speter ** since dbopen returns NULL if the file is zero length, we 138038032Speter ** must have a locked instance around the dbopen. 138138032Speter */ 138238032Speter 138338032Speter fd = open(buf, omode, DBMMODE); 138438032Speter if (fd < 0) 138538032Speter { 138638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 138738032Speter syserr("db_map_open: cannot pre-open database %s", buf); 138838032Speter return FALSE; 138938032Speter } 139038032Speter 139138032Speter /* make sure no baddies slipped in just before the open... */ 139238032Speter if (filechanged(buf, fd, &st)) 139338032Speter { 139438032Speter int save_errno = errno; 139538032Speter 139638032Speter (void) close(fd); 139738032Speter errno = save_errno; 139838032Speter syserr("db_map_open(%s): file changed after pre-open", buf); 139938032Speter return FALSE; 140038032Speter } 140138032Speter 140238032Speter /* if new file, get the "before" bits for later filechanged check */ 140338032Speter if (st.st_mode == ST_MODE_NOFILE && fstat(fd, &st) < 0) 140438032Speter { 140538032Speter int save_errno = errno; 140638032Speter 140738032Speter (void) close(fd); 140838032Speter errno = save_errno; 140938032Speter syserr("db_map_open(%s): cannot fstat pre-opened file", 141038032Speter buf); 141138032Speter return FALSE; 141238032Speter } 141338032Speter 141438032Speter /* actually lock the pre-opened file */ 141538032Speter if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX)) 141638032Speter syserr("db_map_open: cannot lock %s", buf); 141738032Speter 141838032Speter /* set up mode bits for dbopen */ 141938032Speter if (mode == O_RDWR) 142038032Speter omode |= O_TRUNC; 142138032Speter omode &= ~(O_EXCL|O_CREAT); 142238032Speter#endif 142338032Speter 142438032Speter#if DB_VERSION_MAJOR < 2 142538032Speter db = dbopen(buf, omode, DBMMODE, dbtype, openinfo); 142638032Speter#else 142738032Speter { 142838032Speter int flags = 0; 142938032Speter 143038032Speter if (mode == O_RDONLY) 143138032Speter flags |= DB_RDONLY; 143238032Speter if (bitset(O_CREAT, omode)) 143338032Speter flags |= DB_CREATE; 143438032Speter if (bitset(O_TRUNC, omode)) 143538032Speter flags |= DB_TRUNCATE; 143638032Speter 143738032Speter errno = db_open(buf, dbtype, flags, DBMMODE, 143838032Speter NULL, openinfo, &db); 143938032Speter } 144038032Speter#endif 144138032Speter saveerrno = errno; 144238032Speter 144338032Speter#if !LOCK_ON_OPEN 144438032Speter if (mode == O_RDWR) 144538032Speter map->map_lockfd = fd; 144638032Speter else 144738032Speter (void) close(fd); 144838032Speter#endif 144938032Speter 145038032Speter if (db == NULL) 145138032Speter { 145238032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 145338032Speter aliaswait(map, ".db", FALSE)) 145438032Speter return TRUE; 145538032Speter#if !LOCK_ON_OPEN 145638032Speter if (map->map_lockfd >= 0) 145738032Speter (void) close(map->map_lockfd); 145838032Speter#endif 145938032Speter errno = saveerrno; 146038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 146138032Speter syserr("Cannot open %s database %s", 146238032Speter mapclassname, buf); 146338032Speter return FALSE; 146438032Speter } 146538032Speter 146638032Speter#if DB_VERSION_MAJOR < 2 146738032Speter fd = db->fd(db); 146838032Speter#else 146938032Speter fd = -1; 147038032Speter errno = db->fd(db, &fd); 147138032Speter#endif 147238032Speter if (filechanged(buf, fd, &st)) 147338032Speter { 147438032Speter int save_errno = errno; 147538032Speter 147638032Speter#if DB_VERSION_MAJOR < 2 147738032Speter db->close(db); 147838032Speter#else 147938032Speter errno = db->close(db, 0); 148038032Speter#endif 148138032Speter#if !LOCK_ON_OPEN 148238032Speter if (map->map_lockfd >= 0) 148338032Speter close(map->map_lockfd); 148438032Speter#endif 148538032Speter errno = save_errno; 148638032Speter syserr("db_map_open(%s): file changed after open", buf); 148738032Speter return FALSE; 148838032Speter } 148938032Speter 149038032Speter if (mode == O_RDWR) 149138032Speter map->map_mflags |= MF_LOCKED; 149238032Speter#if LOCK_ON_OPEN 149338032Speter if (fd >= 0 && mode == O_RDONLY) 149438032Speter { 149538032Speter (void) lockfile(fd, buf, NULL, LOCK_UN); 149638032Speter } 149738032Speter#endif 149838032Speter 149938032Speter /* try to make sure that at least the database header is on disk */ 150038032Speter if (mode == O_RDWR) 150138032Speter { 150238032Speter (void) db->sync(db, 0); 150338032Speter if (geteuid() == 0 && TrustedFileUid != 0) 150438032Speter { 150538032Speter if (fchown(fd, TrustedFileUid, -1) < 0) 150638032Speter { 150738032Speter int err = errno; 150838032Speter 150938032Speter sm_syslog(LOG_ALERT, NOQID, 151038032Speter "ownership change on %s failed: %s", 151138032Speter buf, errstring(err)); 151238032Speter message("050 ownership change on %s failed: %s", 151338032Speter buf, errstring(err)); 151438032Speter } 151538032Speter } 151638032Speter } 151738032Speter 151838032Speter if (fd >= 0 && fstat(fd, &st) >= 0) 151938032Speter map->map_mtime = st.st_mtime; 152038032Speter 152138032Speter map->map_db2 = (ARBPTR_T) db; 152238032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 152338032Speter !aliaswait(map, ".db", TRUE)) 152438032Speter return FALSE; 152538032Speter return TRUE; 152638032Speter} 152738032Speter 152838032Speter 152938032Speter/* 153038032Speter** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 153138032Speter*/ 153238032Speter 153338032Speterchar * 153438032Speterdb_map_lookup(map, name, av, statp) 153538032Speter MAP *map; 153638032Speter char *name; 153738032Speter char **av; 153838032Speter int *statp; 153938032Speter{ 154038032Speter DBT key, val; 154138032Speter register DB *db = (DB *) map->map_db2; 154238032Speter int i; 154338032Speter int st; 154438032Speter int saveerrno; 154538032Speter int fd; 154638032Speter struct stat stbuf; 154738032Speter char keybuf[MAXNAME + 1]; 154838032Speter char buf[MAXNAME + 1]; 154938032Speter 155038032Speter bzero(&key, sizeof key); 155138032Speter bzero(&val, sizeof val); 155238032Speter 155338032Speter if (tTd(38, 20)) 155438032Speter printf("db_map_lookup(%s, %s)\n", 155538032Speter map->map_mname, name); 155638032Speter 155738032Speter i = strlen(map->map_file); 155838032Speter if (i > MAXNAME) 155938032Speter i = MAXNAME; 156038032Speter strncpy(buf, map->map_file, i); 156138032Speter buf[i] = '\0'; 156238032Speter if (i > 3 && strcmp(&buf[i - 3], ".db") == 0) 156338032Speter buf[i - 3] = '\0'; 156438032Speter 156538032Speter key.size = strlen(name); 156638032Speter if (key.size > sizeof keybuf - 1) 156738032Speter key.size = sizeof keybuf - 1; 156838032Speter key.data = keybuf; 156938032Speter bcopy(name, keybuf, key.size); 157038032Speter keybuf[key.size] = '\0'; 157138032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 157238032Speter makelower(keybuf); 157338032Speter lockdb: 157438032Speter#if DB_VERSION_MAJOR < 2 157538032Speter fd = db->fd(db); 157638032Speter#else 157738032Speter fd = -1; 157838032Speter errno = db->fd(db, &fd); 157938032Speter#endif 158038032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 158138032Speter (void) lockfile(fd, buf, ".db", LOCK_SH); 158238032Speter if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) 158338032Speter { 158438032Speter /* Reopen the database to sync the cache */ 158538032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 158638032Speter : O_RDONLY; 158738032Speter 158838032Speter map->map_class->map_close(map); 158938032Speter map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 159038032Speter if (map->map_class->map_open(map, omode)) 159138032Speter { 159238032Speter map->map_mflags |= MF_OPEN; 159338032Speter if ((omode && O_ACCMODE) == O_RDWR) 159438032Speter map->map_mflags |= MF_WRITABLE; 159538032Speter db = (DB *) map->map_db2; 159638032Speter goto lockdb; 159738032Speter } 159838032Speter else 159938032Speter { 160038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 160138032Speter { 160238032Speter extern MAPCLASS BogusMapClass; 160338032Speter 160438032Speter *statp = EX_TEMPFAIL; 160538032Speter map->map_class = &BogusMapClass; 160638032Speter map->map_mflags |= MF_OPEN; 160738032Speter syserr("Cannot reopen DB database %s", 160838032Speter map->map_file); 160938032Speter } 161038032Speter return NULL; 161138032Speter } 161238032Speter } 161338032Speter 161438032Speter st = 1; 161538032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 161638032Speter { 161738032Speter#if DB_VERSION_MAJOR < 2 161838032Speter st = db->get(db, &key, &val, 0); 161938032Speter#else 162038032Speter errno = db->get(db, NULL, &key, &val, 0); 162138032Speter switch (errno) 162238032Speter { 162338032Speter case DB_NOTFOUND: 162438032Speter case DB_KEYEMPTY: 162538032Speter st = 1; 162638032Speter break; 162738032Speter 162838032Speter case 0: 162938032Speter st = 0; 163038032Speter break; 163138032Speter 163238032Speter default: 163338032Speter st = -1; 163438032Speter break; 163538032Speter } 163638032Speter#endif 163738032Speter if (st == 0) 163838032Speter map->map_mflags &= ~MF_TRY1NULL; 163938032Speter } 164038032Speter if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 164138032Speter { 164238032Speter key.size++; 164338032Speter#if DB_VERSION_MAJOR < 2 164438032Speter st = db->get(db, &key, &val, 0); 164538032Speter#else 164638032Speter errno = db->get(db, NULL, &key, &val, 0); 164738032Speter switch (errno) 164838032Speter { 164938032Speter case DB_NOTFOUND: 165038032Speter case DB_KEYEMPTY: 165138032Speter st = 1; 165238032Speter break; 165338032Speter 165438032Speter case 0: 165538032Speter st = 0; 165638032Speter break; 165738032Speter 165838032Speter default: 165938032Speter st = -1; 166038032Speter break; 166138032Speter } 166238032Speter#endif 166338032Speter if (st == 0) 166438032Speter map->map_mflags &= ~MF_TRY0NULL; 166538032Speter } 166638032Speter saveerrno = errno; 166738032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 166838032Speter (void) lockfile(fd, buf, ".db", LOCK_UN); 166938032Speter if (st != 0) 167038032Speter { 167138032Speter errno = saveerrno; 167238032Speter if (st < 0) 167338032Speter syserr("db_map_lookup: get (%s)", name); 167438032Speter return NULL; 167538032Speter } 167638032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 167738032Speter return map_rewrite(map, name, strlen(name), NULL); 167838032Speter else 167938032Speter return map_rewrite(map, val.data, val.size, av); 168038032Speter} 168138032Speter 168238032Speter 168338032Speter/* 168438032Speter** DB_MAP_STORE -- store a datum in the NEWDB database 168538032Speter*/ 168638032Speter 168738032Spetervoid 168838032Speterdb_map_store(map, lhs, rhs) 168938032Speter register MAP *map; 169038032Speter char *lhs; 169138032Speter char *rhs; 169238032Speter{ 169338032Speter int stat; 169438032Speter DBT key; 169538032Speter DBT data; 169638032Speter register DB *db = map->map_db2; 169738032Speter char keybuf[MAXNAME + 1]; 169838032Speter 169938032Speter bzero(&key, sizeof key); 170038032Speter bzero(&data, sizeof data); 170138032Speter 170238032Speter if (tTd(38, 12)) 170338032Speter printf("db_map_store(%s, %s, %s)\n", 170438032Speter map->map_mname, lhs, rhs); 170538032Speter 170638032Speter key.size = strlen(lhs); 170738032Speter key.data = lhs; 170838032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 170938032Speter { 171038032Speter if (key.size > sizeof keybuf - 1) 171138032Speter key.size = sizeof keybuf - 1; 171238032Speter bcopy(key.data, keybuf, key.size); 171338032Speter keybuf[key.size] = '\0'; 171438032Speter makelower(keybuf); 171538032Speter key.data = keybuf; 171638032Speter } 171738032Speter 171838032Speter data.size = strlen(rhs); 171938032Speter data.data = rhs; 172038032Speter 172138032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 172238032Speter { 172338032Speter key.size++; 172438032Speter data.size++; 172538032Speter } 172638032Speter 172738032Speter#if DB_VERSION_MAJOR < 2 172838032Speter stat = db->put(db, &key, &data, R_NOOVERWRITE); 172938032Speter#else 173038032Speter errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE); 173138032Speter switch (errno) 173238032Speter { 173338032Speter case DB_KEYEXIST: 173438032Speter stat = 1; 173538032Speter break; 173638032Speter 173738032Speter case 0: 173838032Speter stat = 0; 173938032Speter break; 174038032Speter 174138032Speter default: 174238032Speter stat = -1; 174338032Speter break; 174438032Speter } 174538032Speter#endif 174638032Speter if (stat > 0) 174738032Speter { 174838032Speter if (!bitset(MF_APPEND, map->map_mflags)) 174938032Speter message("050 Warning: duplicate alias name %s", lhs); 175038032Speter else 175138032Speter { 175238032Speter static char *buf = NULL; 175338032Speter static int bufsiz = 0; 175438032Speter DBT old; 175538032Speter 175638032Speter bzero(&old, sizeof old); 175738032Speter 175838032Speter old.data = db_map_lookup(map, key.data, 175938032Speter (char **)NULL, &stat); 176038032Speter if (old.data != NULL) 176138032Speter { 176238032Speter old.size = strlen(old.data); 176338032Speter if (data.size + old.size + 2 > bufsiz) 176438032Speter { 176538032Speter if (buf != NULL) 176638032Speter (void) free(buf); 176738032Speter bufsiz = data.size + old.size + 2; 176838032Speter buf = xalloc(bufsiz); 176938032Speter } 177038032Speter snprintf(buf, bufsiz, "%s,%s", 177138032Speter (char *) data.data, (char *) old.data); 177238032Speter data.size = data.size + old.size + 1; 177338032Speter data.data = buf; 177438032Speter if (tTd(38, 9)) 177538032Speter printf("db_map_store append=%s\n", 177638032Speter (char *) data.data); 177738032Speter } 177838032Speter } 177938032Speter#if DB_VERSION_MAJOR < 2 178038032Speter stat = db->put(db, &key, &data, 0); 178138032Speter#else 178238032Speter stat = errno = db->put(db, NULL, &key, &data, 0); 178338032Speter#endif 178438032Speter } 178538032Speter if (stat != 0) 178638032Speter syserr("readaliases: db put (%s)", lhs); 178738032Speter} 178838032Speter 178938032Speter 179038032Speter/* 179138032Speter** DB_MAP_CLOSE -- add distinguished entries and close the database 179238032Speter*/ 179338032Speter 179438032Spetervoid 179538032Speterdb_map_close(map) 179638032Speter MAP *map; 179738032Speter{ 179838032Speter register DB *db = map->map_db2; 179938032Speter 180038032Speter if (tTd(38, 9)) 180138032Speter printf("db_map_close(%s, %s, %lx)\n", 180238032Speter map->map_mname, map->map_file, map->map_mflags); 180338032Speter 180438032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 180538032Speter { 180638032Speter /* write out the distinguished alias */ 180738032Speter db_map_store(map, "@", "@"); 180838032Speter } 180938032Speter 181038032Speter (void) db->sync(db, 0); 181138032Speter 181238032Speter#if !LOCK_ON_OPEN 181338032Speter if (map->map_lockfd >= 0) 181438032Speter (void) close(map->map_lockfd); 181538032Speter#endif 181638032Speter 181738032Speter#if DB_VERSION_MAJOR < 2 181838032Speter if (db->close(db) != 0) 181938032Speter#else 182038032Speter if ((errno = db->close(db, 0)) != 0) 182138032Speter#endif 182238032Speter syserr("readaliases: db close failure"); 182338032Speter} 182438032Speter 182538032Speter#endif 182638032Speter/* 182738032Speter** NIS Modules 182838032Speter*/ 182938032Speter 183038032Speter# ifdef NIS 183138032Speter 183238032Speter# ifndef YPERR_BUSY 183338032Speter# define YPERR_BUSY 16 183438032Speter# endif 183538032Speter 183638032Speter/* 183738032Speter** NIS_MAP_OPEN -- open DBM map 183838032Speter*/ 183938032Speter 184038032Speterbool 184138032Speternis_map_open(map, mode) 184238032Speter MAP *map; 184338032Speter int mode; 184438032Speter{ 184538032Speter int yperr; 184638032Speter register char *p; 184738032Speter auto char *vp; 184838032Speter auto int vsize; 184938032Speter 185038032Speter if (tTd(38, 2)) 185138032Speter printf("nis_map_open(%s, %s, %d)\n", 185238032Speter map->map_mname, map->map_file, mode); 185338032Speter 185438032Speter mode &= O_ACCMODE; 185538032Speter if (mode != O_RDONLY) 185638032Speter { 185738032Speter /* issue a pseudo-error message */ 185838032Speter#ifdef ENOSYS 185938032Speter errno = ENOSYS; 186038032Speter#else 186138032Speter# ifdef EFTYPE 186238032Speter errno = EFTYPE; 186338032Speter# else 186438032Speter errno = ENXIO; 186538032Speter# endif 186638032Speter#endif 186738032Speter return FALSE; 186838032Speter } 186938032Speter 187038032Speter p = strchr(map->map_file, '@'); 187138032Speter if (p != NULL) 187238032Speter { 187338032Speter *p++ = '\0'; 187438032Speter if (*p != '\0') 187538032Speter map->map_domain = p; 187638032Speter } 187738032Speter 187838032Speter if (*map->map_file == '\0') 187938032Speter map->map_file = "mail.aliases"; 188038032Speter 188138032Speter if (map->map_domain == NULL) 188238032Speter { 188338032Speter yperr = yp_get_default_domain(&map->map_domain); 188438032Speter if (yperr != 0) 188538032Speter { 188638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 188738032Speter syserr("421 NIS map %s specified, but NIS not running", 188838032Speter map->map_file); 188938032Speter return FALSE; 189038032Speter } 189138032Speter } 189238032Speter 189338032Speter /* check to see if this map actually exists */ 189438032Speter yperr = yp_match(map->map_domain, map->map_file, "@", 1, 189538032Speter &vp, &vsize); 189638032Speter if (tTd(38, 10)) 189738032Speter printf("nis_map_open: yp_match(@, %s, %s) => %s\n", 189838032Speter map->map_domain, map->map_file, yperr_string(yperr)); 189938032Speter if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 190038032Speter { 190138032Speter /* 190238032Speter ** We ought to be calling aliaswait() here if this is an 190338032Speter ** alias file, but powerful HP-UX NIS servers apparently 190438032Speter ** don't insert the @:@ token into the alias map when it 190538032Speter ** is rebuilt, so aliaswait() just hangs. I hate HP-UX. 190638032Speter */ 190738032Speter 190838032Speter#if 0 190938032Speter if (!bitset(MF_ALIAS, map->map_mflags) || 191038032Speter aliaswait(map, NULL, TRUE)) 191138032Speter#endif 191238032Speter return TRUE; 191338032Speter } 191438032Speter 191538032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 191638032Speter { 191738032Speter syserr("421 Cannot bind to map %s in domain %s: %s", 191838032Speter map->map_file, map->map_domain, yperr_string(yperr)); 191938032Speter } 192038032Speter 192138032Speter return FALSE; 192238032Speter} 192338032Speter 192438032Speter 192538032Speter/* 192638032Speter** NIS_MAP_LOOKUP -- look up a datum in a NIS map 192738032Speter*/ 192838032Speter 192938032Speter/* ARGSUSED3 */ 193038032Speterchar * 193138032Speternis_map_lookup(map, name, av, statp) 193238032Speter MAP *map; 193338032Speter char *name; 193438032Speter char **av; 193538032Speter int *statp; 193638032Speter{ 193738032Speter char *vp; 193838032Speter auto int vsize; 193938032Speter int buflen; 194038032Speter int yperr; 194138032Speter char keybuf[MAXNAME + 1]; 194238032Speter 194338032Speter if (tTd(38, 20)) 194438032Speter printf("nis_map_lookup(%s, %s)\n", 194538032Speter map->map_mname, name); 194638032Speter 194738032Speter buflen = strlen(name); 194838032Speter if (buflen > sizeof keybuf - 1) 194938032Speter buflen = sizeof keybuf - 1; 195038032Speter bcopy(name, keybuf, buflen); 195138032Speter keybuf[buflen] = '\0'; 195238032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 195338032Speter makelower(keybuf); 195438032Speter yperr = YPERR_KEY; 195538032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 195638032Speter { 195738032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 195838032Speter &vp, &vsize); 195938032Speter if (yperr == 0) 196038032Speter map->map_mflags &= ~MF_TRY1NULL; 196138032Speter } 196238032Speter if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 196338032Speter { 196438032Speter buflen++; 196538032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 196638032Speter &vp, &vsize); 196738032Speter if (yperr == 0) 196838032Speter map->map_mflags &= ~MF_TRY0NULL; 196938032Speter } 197038032Speter if (yperr != 0) 197138032Speter { 197238032Speter if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 197338032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 197438032Speter return NULL; 197538032Speter } 197638032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 197738032Speter return map_rewrite(map, name, strlen(name), NULL); 197838032Speter else 197938032Speter return map_rewrite(map, vp, vsize, av); 198038032Speter} 198138032Speter 198238032Speter 198338032Speter/* 198438032Speter** NIS_GETCANONNAME -- look up canonical name in NIS 198538032Speter*/ 198638032Speter 198738032Speterbool 198838032Speternis_getcanonname(name, hbsize, statp) 198938032Speter char *name; 199038032Speter int hbsize; 199138032Speter int *statp; 199238032Speter{ 199338032Speter char *vp; 199438032Speter auto int vsize; 199538032Speter int keylen; 199638032Speter int yperr; 199738032Speter static bool try0null = TRUE; 199838032Speter static bool try1null = TRUE; 199938032Speter static char *yp_domain = NULL; 200038032Speter char host_record[MAXLINE]; 200138032Speter char cbuf[MAXNAME]; 200238032Speter char nbuf[MAXNAME + 1]; 200338032Speter 200438032Speter if (tTd(38, 20)) 200538032Speter printf("nis_getcanonname(%s)\n", name); 200638032Speter 200738032Speter if (strlen(name) >= sizeof nbuf) 200838032Speter { 200938032Speter *statp = EX_UNAVAILABLE; 201038032Speter return FALSE; 201138032Speter } 201238032Speter (void) strcpy(nbuf, name); 201338032Speter shorten_hostname(nbuf); 201438032Speter keylen = strlen(nbuf); 201538032Speter 201638032Speter if (yp_domain == NULL) 201738032Speter yp_get_default_domain(&yp_domain); 201838032Speter makelower(nbuf); 201938032Speter yperr = YPERR_KEY; 202038032Speter if (try0null) 202138032Speter { 202238032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 202338032Speter &vp, &vsize); 202438032Speter if (yperr == 0) 202538032Speter try1null = FALSE; 202638032Speter } 202738032Speter if (yperr == YPERR_KEY && try1null) 202838032Speter { 202938032Speter keylen++; 203038032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 203138032Speter &vp, &vsize); 203238032Speter if (yperr == 0) 203338032Speter try0null = FALSE; 203438032Speter } 203538032Speter if (yperr != 0) 203638032Speter { 203738032Speter if (yperr == YPERR_KEY) 203838032Speter *statp = EX_NOHOST; 203938032Speter else if (yperr == YPERR_BUSY) 204038032Speter *statp = EX_TEMPFAIL; 204138032Speter else 204238032Speter *statp = EX_UNAVAILABLE; 204338032Speter return FALSE; 204438032Speter } 204538032Speter if (vsize >= sizeof host_record) 204638032Speter vsize = sizeof host_record - 1; 204738032Speter strncpy(host_record, vp, vsize); 204838032Speter host_record[vsize] = '\0'; 204938032Speter if (tTd(38, 44)) 205038032Speter printf("got record `%s'\n", host_record); 205138032Speter if (!extract_canonname(nbuf, host_record, cbuf, sizeof cbuf)) 205238032Speter { 205338032Speter /* this should not happen, but.... */ 205438032Speter *statp = EX_NOHOST; 205538032Speter return FALSE; 205638032Speter } 205738032Speter if (hbsize < strlen(cbuf)) 205838032Speter { 205938032Speter *statp = EX_UNAVAILABLE; 206038032Speter return FALSE; 206138032Speter } 206238032Speter strcpy(name, cbuf); 206338032Speter *statp = EX_OK; 206438032Speter return TRUE; 206538032Speter} 206638032Speter 206738032Speter#endif 206838032Speter/* 206938032Speter** NISPLUS Modules 207038032Speter** 207138032Speter** This code donated by Sun Microsystems. 207238032Speter*/ 207338032Speter 207438032Speter#ifdef NISPLUS 207538032Speter 207638032Speter#undef NIS /* symbol conflict in nis.h */ 207738032Speter#undef T_UNSPEC /* symbol conflict in nis.h -> ... -> sys/tiuser.h */ 207838032Speter#include <rpcsvc/nis.h> 207938032Speter#include <rpcsvc/nislib.h> 208038032Speter 208138032Speter#define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 208238032Speter#define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 208338032Speter#define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 208438032Speter#define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 208538032Speter 208638032Speter/* 208738032Speter** NISPLUS_MAP_OPEN -- open nisplus table 208838032Speter*/ 208938032Speter 209038032Speterbool 209138032Speternisplus_map_open(map, mode) 209238032Speter MAP *map; 209338032Speter int mode; 209438032Speter{ 209538032Speter nis_result *res = NULL; 209638032Speter int retry_cnt, max_col, i; 209738032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 209838032Speter 209938032Speter if (tTd(38, 2)) 210038032Speter printf("nisplus_map_open(%s, %s, %d)\n", 210138032Speter map->map_mname, map->map_file, mode); 210238032Speter 210338032Speter mode &= O_ACCMODE; 210438032Speter if (mode != O_RDONLY) 210538032Speter { 210638032Speter errno = EPERM; 210738032Speter return FALSE; 210838032Speter } 210938032Speter 211038032Speter if (*map->map_file == '\0') 211138032Speter map->map_file = "mail_aliases.org_dir"; 211238032Speter 211338032Speter if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 211438032Speter { 211538032Speter /* set default NISPLUS Domain to $m */ 211638032Speter extern char *nisplus_default_domain __P((void)); 211738032Speter 211838032Speter map->map_domain = newstr(nisplus_default_domain()); 211938032Speter if (tTd(38, 2)) 212038032Speter printf("nisplus_map_open(%s): using domain %s\n", 212138032Speter map->map_file, map->map_domain); 212238032Speter } 212338032Speter if (!PARTIAL_NAME(map->map_file)) 212438032Speter { 212538032Speter map->map_domain = newstr(""); 212638032Speter snprintf(qbuf, sizeof qbuf, "%s", map->map_file); 212738032Speter } 212838032Speter else 212938032Speter { 213038032Speter /* check to see if this map actually exists */ 213138032Speter snprintf(qbuf, sizeof qbuf, "%s.%s", 213238032Speter map->map_file, map->map_domain); 213338032Speter } 213438032Speter 213538032Speter retry_cnt = 0; 213638032Speter while (res == NULL || res->status != NIS_SUCCESS) 213738032Speter { 213838032Speter res = nis_lookup(qbuf, FOLLOW_LINKS); 213938032Speter switch (res->status) 214038032Speter { 214138032Speter case NIS_SUCCESS: 214238032Speter break; 214338032Speter 214438032Speter case NIS_TRYAGAIN: 214538032Speter case NIS_RPCERROR: 214638032Speter case NIS_NAMEUNREACHABLE: 214738032Speter if (retry_cnt++ > 4) 214838032Speter { 214938032Speter errno = EAGAIN; 215038032Speter return FALSE; 215138032Speter } 215238032Speter /* try not to overwhelm hosed server */ 215338032Speter sleep(2); 215438032Speter break; 215538032Speter 215638032Speter default: /* all other nisplus errors */ 215738032Speter#if 0 215838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 215938032Speter syserr("421 Cannot find table %s.%s: %s", 216038032Speter map->map_file, map->map_domain, 216138032Speter nis_sperrno(res->status)); 216238032Speter#endif 216338032Speter errno = EAGAIN; 216438032Speter return FALSE; 216538032Speter } 216638032Speter } 216738032Speter 216838032Speter if (NIS_RES_NUMOBJ(res) != 1 || 216938032Speter (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 217038032Speter { 217138032Speter if (tTd(38, 10)) 217238032Speter printf("nisplus_map_open: %s is not a table\n", qbuf); 217338032Speter#if 0 217438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 217538032Speter syserr("421 %s.%s: %s is not a table", 217638032Speter map->map_file, map->map_domain, 217738032Speter nis_sperrno(res->status)); 217838032Speter#endif 217938032Speter errno = EBADF; 218038032Speter return FALSE; 218138032Speter } 218238032Speter /* default key column is column 0 */ 218338032Speter if (map->map_keycolnm == NULL) 218438032Speter map->map_keycolnm = newstr(COL_NAME(res,0)); 218538032Speter 218638032Speter max_col = COL_MAX(res); 218738032Speter 218838032Speter /* verify the key column exist */ 218938032Speter for (i=0; i< max_col; i++) 219038032Speter { 219138032Speter if (!strcmp(map->map_keycolnm, COL_NAME(res,i))) 219238032Speter break; 219338032Speter } 219438032Speter if (i == max_col) 219538032Speter { 219638032Speter if (tTd(38, 2)) 219738032Speter printf("nisplus_map_open(%s): can not find key column %s\n", 219838032Speter map->map_file, map->map_keycolnm); 219938032Speter errno = ENOENT; 220038032Speter return FALSE; 220138032Speter } 220238032Speter 220338032Speter /* default value column is the last column */ 220438032Speter if (map->map_valcolnm == NULL) 220538032Speter { 220638032Speter map->map_valcolno = max_col - 1; 220738032Speter return TRUE; 220838032Speter } 220938032Speter 221038032Speter for (i=0; i< max_col; i++) 221138032Speter { 221238032Speter if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 221338032Speter { 221438032Speter map->map_valcolno = i; 221538032Speter return TRUE; 221638032Speter } 221738032Speter } 221838032Speter 221938032Speter if (tTd(38, 2)) 222038032Speter printf("nisplus_map_open(%s): can not find column %s\n", 222138032Speter map->map_file, map->map_keycolnm); 222238032Speter errno = ENOENT; 222338032Speter return FALSE; 222438032Speter} 222538032Speter 222638032Speter 222738032Speter/* 222838032Speter** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 222938032Speter*/ 223038032Speter 223138032Speterchar * 223238032Speternisplus_map_lookup(map, name, av, statp) 223338032Speter MAP *map; 223438032Speter char *name; 223538032Speter char **av; 223638032Speter int *statp; 223738032Speter{ 223838032Speter char *p; 223938032Speter auto int vsize; 224038032Speter char *skp; 224138032Speter int skleft; 224238032Speter char search_key[MAXNAME + 4]; 224338032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 224438032Speter nis_result *result; 224538032Speter 224638032Speter if (tTd(38, 20)) 224738032Speter printf("nisplus_map_lookup(%s, %s)\n", 224838032Speter map->map_mname, name); 224938032Speter 225038032Speter if (!bitset(MF_OPEN, map->map_mflags)) 225138032Speter { 225238032Speter if (nisplus_map_open(map, O_RDONLY)) 225338032Speter map->map_mflags |= MF_OPEN; 225438032Speter else 225538032Speter { 225638032Speter *statp = EX_UNAVAILABLE; 225738032Speter return NULL; 225838032Speter } 225938032Speter } 226038032Speter 226138032Speter /* 226238032Speter ** Copy the name to the key buffer, escaping double quote characters 226338032Speter ** by doubling them and quoting "]" and "," to avoid having the 226438032Speter ** NIS+ parser choke on them. 226538032Speter */ 226638032Speter 226738032Speter skleft = sizeof search_key - 4; 226838032Speter skp = search_key; 226938032Speter for (p = name; *p != '\0' && skleft > 0; p++) 227038032Speter { 227138032Speter switch (*p) 227238032Speter { 227338032Speter case ']': 227438032Speter case ',': 227538032Speter /* quote the character */ 227638032Speter *skp++ = '"'; 227738032Speter *skp++ = *p; 227838032Speter *skp++ = '"'; 227938032Speter skleft -= 3; 228038032Speter break; 228138032Speter 228238032Speter case '"': 228338032Speter /* double the quote */ 228438032Speter *skp++ = '"'; 228538032Speter skleft--; 228638032Speter /* fall through... */ 228738032Speter 228838032Speter default: 228938032Speter *skp++ = *p; 229038032Speter skleft--; 229138032Speter break; 229238032Speter } 229338032Speter } 229438032Speter *skp = '\0'; 229538032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 229638032Speter makelower(search_key); 229738032Speter 229838032Speter /* construct the query */ 229938032Speter if (PARTIAL_NAME(map->map_file)) 230038032Speter snprintf(qbuf, sizeof qbuf, "[%s=%s],%s.%s", 230138032Speter map->map_keycolnm, search_key, map->map_file, 230238032Speter map->map_domain); 230338032Speter else 230438032Speter snprintf(qbuf, sizeof qbuf, "[%s=%s],%s", 230538032Speter map->map_keycolnm, search_key, map->map_file); 230638032Speter 230738032Speter if (tTd(38, 20)) 230838032Speter printf("qbuf=%s\n", qbuf); 230938032Speter result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 231038032Speter if (result->status == NIS_SUCCESS) 231138032Speter { 231238032Speter int count; 231338032Speter char *str; 231438032Speter 231538032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 231638032Speter { 231738032Speter if (LogLevel > 10) 231838032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 231938032Speter "%s: lookup error, expected 1 entry, got %d", 232038032Speter map->map_file, count); 232138032Speter 232238032Speter /* ignore second entry */ 232338032Speter if (tTd(38, 20)) 232438032Speter printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 232538032Speter name, count); 232638032Speter } 232738032Speter 232838032Speter p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 232938032Speter /* set the length of the result */ 233038032Speter if (p == NULL) 233138032Speter p = ""; 233238032Speter vsize = strlen(p); 233338032Speter if (tTd(38, 20)) 233438032Speter printf("nisplus_map_lookup(%s), found %s\n", 233538032Speter name, p); 233638032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 233738032Speter str = map_rewrite(map, name, strlen(name), NULL); 233838032Speter else 233938032Speter str = map_rewrite(map, p, vsize, av); 234038032Speter nis_freeresult(result); 234138032Speter *statp = EX_OK; 234238032Speter return str; 234338032Speter } 234438032Speter else 234538032Speter { 234638032Speter if (result->status == NIS_NOTFOUND) 234738032Speter *statp = EX_NOTFOUND; 234838032Speter else if (result->status == NIS_TRYAGAIN) 234938032Speter *statp = EX_TEMPFAIL; 235038032Speter else 235138032Speter { 235238032Speter *statp = EX_UNAVAILABLE; 235338032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 235438032Speter } 235538032Speter } 235638032Speter if (tTd(38, 20)) 235738032Speter printf("nisplus_map_lookup(%s), failed\n", name); 235838032Speter nis_freeresult(result); 235938032Speter return NULL; 236038032Speter} 236138032Speter 236238032Speter 236338032Speter 236438032Speter/* 236538032Speter** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 236638032Speter*/ 236738032Speter 236838032Speterbool 236938032Speternisplus_getcanonname(name, hbsize, statp) 237038032Speter char *name; 237138032Speter int hbsize; 237238032Speter int *statp; 237338032Speter{ 237438032Speter char *vp; 237538032Speter auto int vsize; 237638032Speter nis_result *result; 237738032Speter char *p; 237838032Speter char nbuf[MAXNAME + 1]; 237938032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 238038032Speter 238138032Speter if (strlen(name) >= sizeof nbuf) 238238032Speter { 238338032Speter *statp = EX_UNAVAILABLE; 238438032Speter return FALSE; 238538032Speter } 238638032Speter (void) strcpy(nbuf, name); 238738032Speter shorten_hostname(nbuf); 238838032Speter 238938032Speter p = strchr(nbuf, '.'); 239038032Speter if (p == NULL) 239138032Speter { 239238032Speter /* single token */ 239338032Speter snprintf(qbuf, sizeof qbuf, "[name=%s],hosts.org_dir", nbuf); 239438032Speter } 239538032Speter else if (p[1] != '\0') 239638032Speter { 239738032Speter /* multi token -- take only first token in nbuf */ 239838032Speter *p = '\0'; 239938032Speter snprintf(qbuf, sizeof qbuf, "[name=%s],hosts.org_dir.%s", 240038032Speter nbuf, &p[1]); 240138032Speter } 240238032Speter else 240338032Speter { 240438032Speter *statp = EX_NOHOST; 240538032Speter return FALSE; 240638032Speter } 240738032Speter 240838032Speter if (tTd(38, 20)) 240938032Speter printf("\nnisplus_getcanoname(%s), qbuf=%s\n", 241038032Speter name, qbuf); 241138032Speter 241238032Speter result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 241338032Speter NULL, NULL); 241438032Speter 241538032Speter if (result->status == NIS_SUCCESS) 241638032Speter { 241738032Speter int count; 241838032Speter char *domain; 241938032Speter 242038032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 242138032Speter { 242238032Speter if (LogLevel > 10) 242338032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 242438032Speter "nisplus_getcanonname: lookup error, expected 1 entry, got %d", 242538032Speter count); 242638032Speter 242738032Speter /* ignore second entry */ 242838032Speter if (tTd(38, 20)) 242938032Speter printf("nisplus_getcanoname(%s), got %d entries, all but first ignored\n", 243038032Speter name, count); 243138032Speter } 243238032Speter 243338032Speter if (tTd(38, 20)) 243438032Speter printf("nisplus_getcanoname(%s), found in directory \"%s\"\n", 243538032Speter name, (NIS_RES_OBJECT(result))->zo_domain); 243638032Speter 243738032Speter 243838032Speter vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 243938032Speter vsize = strlen(vp); 244038032Speter if (tTd(38, 20)) 244138032Speter printf("nisplus_getcanonname(%s), found %s\n", 244238032Speter name, vp); 244338032Speter if (strchr(vp, '.') != NULL) 244438032Speter { 244538032Speter domain = ""; 244638032Speter } 244738032Speter else 244838032Speter { 244938032Speter domain = macvalue('m', CurEnv); 245038032Speter if (domain == NULL) 245138032Speter domain = ""; 245238032Speter } 245338032Speter if (hbsize > vsize + (int) strlen(domain) + 1) 245438032Speter { 245538032Speter if (domain[0] == '\0') 245638032Speter strcpy(name, vp); 245738032Speter else 245838032Speter snprintf(name, hbsize, "%s.%s", vp, domain); 245938032Speter *statp = EX_OK; 246038032Speter } 246138032Speter else 246238032Speter *statp = EX_NOHOST; 246338032Speter nis_freeresult(result); 246438032Speter return TRUE; 246538032Speter } 246638032Speter else 246738032Speter { 246838032Speter if (result->status == NIS_NOTFOUND) 246938032Speter *statp = EX_NOHOST; 247038032Speter else if (result->status == NIS_TRYAGAIN) 247138032Speter *statp = EX_TEMPFAIL; 247238032Speter else 247338032Speter *statp = EX_UNAVAILABLE; 247438032Speter } 247538032Speter if (tTd(38, 20)) 247638032Speter printf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 247738032Speter name, result->status, *statp); 247838032Speter nis_freeresult(result); 247938032Speter return FALSE; 248038032Speter} 248138032Speter 248238032Speter 248338032Speterchar * 248438032Speternisplus_default_domain() 248538032Speter{ 248638032Speter static char default_domain[MAXNAME + 1] = ""; 248738032Speter char *p; 248838032Speter 248938032Speter if (default_domain[0] != '\0') 249038032Speter return(default_domain); 249138032Speter 249238032Speter p = nis_local_directory(); 249338032Speter snprintf(default_domain, sizeof default_domain, "%s", p); 249438032Speter return default_domain; 249538032Speter} 249638032Speter 249738032Speter#endif /* NISPLUS */ 249838032Speter/* 249938032Speter** LDAP Modules 250038032Speter** 250138032Speter** Contributed by Booker C. Bense <bbense@networking.stanford.edu>. 250238032Speter** Get your support from him. 250338032Speter*/ 250438032Speter 250538032Speter#ifdef LDAPMAP 250638032Speter 250738032Speter# undef NEEDGETOPT /* used for something else in LDAP */ 250838032Speter 250938032Speter# include <lber.h> 251038032Speter# include <ldap.h> 251138032Speter# include "ldap_map.h" 251238032Speter 251338032Speter/* 251438032Speter** LDAP_MAP_OPEN -- open LDAP map 251538032Speter** 251638032Speter** Since LDAP is TCP-based there is not much we can or should do 251738032Speter** here. It might be a good idea to attempt an open/close here. 251838032Speter*/ 251938032Speter 252038032Speterbool 252138032Speterldap_map_open(map, mode) 252238032Speter MAP *map; 252338032Speter int mode; 252438032Speter{ 252538032Speter if (tTd(38, 2)) 252638032Speter printf("ldap_map_open(%s, %d)\n", map->map_mname, mode); 252738032Speter 252838032Speter mode &= O_ACCMODE; 252938032Speter if (mode != O_RDONLY) 253038032Speter { 253138032Speter /* issue a pseudo-error message */ 253238032Speter#ifdef ENOSYS 253338032Speter errno = ENOSYS; 253438032Speter#else 253538032Speter# ifdef EFTYPE 253638032Speter errno = EFTYPE; 253738032Speter# else 253838032Speter errno = ENXIO; 253938032Speter# endif 254038032Speter#endif 254138032Speter return FALSE; 254238032Speter } 254338032Speter return TRUE; 254438032Speter} 254538032Speter 254638032Speter 254738032Speter/* 254838032Speter** LDAP_MAP_START -- actually open LDAP map 254938032Speter** 255038032Speter** Caching should be investigated. 255138032Speter*/ 255238032Speter 255338032Speterstatic jmp_buf LDAPTimeout; 255438032Speter 255538032Speterstatic void 255638032Speterldaptimeout(sig_no) 255738032Speter int sig_no; 255838032Speter{ 255938032Speter longjmp(LDAPTimeout, 1); 256038032Speter} 256138032Speter 256238032Speterbool 256338032Speterldap_map_start(map) 256438032Speter MAP *map; 256538032Speter{ 256638032Speter LDAP_MAP_STRUCT *lmap; 256738032Speter LDAP *ld; 256838032Speter register EVENT *ev = NULL; 256938032Speter 257038032Speter if (tTd(38, 2)) 257138032Speter printf("ldap_map_start(%s)\n", map->map_mname); 257238032Speter 257338032Speter lmap = (LDAP_MAP_STRUCT *) map->map_db1; 257438032Speter 257538032Speter if (tTd(38,9)) 257638032Speter printf("ldap_open(%s, %d)\n", lmap->ldaphost, lmap->ldapport); 257738032Speter 257838032Speter /* Need to set an alarm here, ldap_open is hopelessly broken. */ 257938032Speter 258038032Speter /* set the timeout */ 258138032Speter if (lmap->timeout.tv_sec != 0) 258238032Speter { 258338032Speter if (setjmp(LDAPTimeout) != 0) 258438032Speter { 258538032Speter if (LogLevel > 1) 258638032Speter sm_syslog(LOG_NOTICE, CurEnv->e_id, 258738032Speter "timeout waiting for ldap_open to %.100s", 258838032Speter lmap->ldaphost); 258938032Speter return (FALSE); 259038032Speter } 259138032Speter ev = setevent(lmap->timeout.tv_sec, ldaptimeout, 0); 259238032Speter } 259338032Speter 259438032Speter if ((ld = ldap_open(lmap->ldaphost,lmap->ldapport)) == NULL) 259538032Speter { 259638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 259738032Speter { 259838032Speter syserr("ldapopen failed to %s in map %s", 259938032Speter lmap->ldaphost, map->map_mname); 260038032Speter } 260138032Speter return FALSE; 260238032Speter } 260338032Speter 260438032Speter /* clear the event if it has not sprung */ 260538032Speter clrevent(ev); 260638032Speter /* From here on in we can use ldap internal timelimits */ 260738032Speter ld->ld_deref = lmap->deref; 260838032Speter ld->ld_timelimit = lmap->timelimit; 260938032Speter ld->ld_sizelimit = lmap->sizelimit; 261038032Speter ld->ld_options = lmap->ldap_options; 261138032Speter 261238032Speter if (ldap_bind_s(ld, lmap->binddn,lmap->passwd,lmap->method) != LDAP_SUCCESS) 261338032Speter { 261438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 261538032Speter { 261638032Speter syserr("421 Cannot bind to map %s in ldap server %s", 261738032Speter map->map_mname, lmap->ldaphost); 261838032Speter } 261938032Speter } 262038032Speter else 262138032Speter { 262238032Speter /* We need to cast ld into the map structure */ 262338032Speter lmap->ld = ld; 262438032Speter return TRUE; 262538032Speter } 262638032Speter 262738032Speter return FALSE; 262838032Speter} 262938032Speter 263038032Speter 263138032Speter/* 263238032Speter** LDAP_MAP_CLOSE -- close ldap map 263338032Speter*/ 263438032Speter 263538032Spetervoid 263638032Speterldap_map_close(map) 263738032Speter MAP *map; 263838032Speter{ 263938032Speter LDAP_MAP_STRUCT *lmap ; 264038032Speter lmap = (LDAP_MAP_STRUCT *) map->map_db1; 264138032Speter if (lmap->ld != NULL) 264238032Speter ldap_unbind(lmap->ld); 264338032Speter} 264438032Speter 264538032Speter 264638032Speter#ifdef SUNET_ID 264738032Speter/* 264838032Speter** SUNET_ID_HASH -- Convert a string to it's Sunet_id canonical form 264938032Speter** This only makes sense at Stanford University. 265038032Speter*/ 265138032Speter 265238032Speterchar * 265338032Spetersunet_id_hash(str) 265438032Speter char *str; 265538032Speter{ 265638032Speter char *p, *p_last; 265738032Speter 265838032Speter p = str; 265938032Speter p_last = p; 266038032Speter while (*p != '\0') 266138032Speter { 266238032Speter if (islower(*p) || isdigit(*p)) 266338032Speter { 266438032Speter *p_last = *p; 266538032Speter p_last++; 266638032Speter } 266738032Speter else if (isupper(*p)) 266838032Speter { 266938032Speter *p_last = tolower(*p); 267038032Speter p_last++; 267138032Speter } 267238032Speter ++p; 267338032Speter } 267438032Speter if (*p_last != '\0') 267538032Speter *p_last = '\0'; 267638032Speter return (str); 267738032Speter} 267838032Speter 267938032Speter 268038032Speter 268138032Speter#endif /* SUNET_ID */ 268238032Speter/* 268338032Speter** LDAP_MAP_LOOKUP -- look up a datum in a LDAP map 268438032Speter*/ 268538032Speter 268638032Speterchar * 268738032Speterldap_map_lookup(map, name, av, statp) 268838032Speter MAP *map; 268938032Speter char *name; 269038032Speter char **av; 269138032Speter int *statp; 269238032Speter{ 269338032Speter LDAP_MAP_STRUCT *lmap = NULL; 269438032Speter LDAPMessage *entry; 269538032Speter char *vp; 269638032Speter auto int vsize; 269738032Speter char keybuf[MAXNAME + 1]; 269838032Speter char filter[LDAP_MAP_MAX_FILTER + 1]; 269938032Speter char **attr_values = NULL; 270038032Speter char *result; 270138032Speter int name_len; 270238032Speter 270338032Speter if (tTd(38, 20)) 270438032Speter printf("ldap_map_lookup(%s, %s)\n", map->map_mname, name); 270538032Speter 270638032Speter /* actually open the map */ 270738032Speter if (!ldap_map_start(map)) 270838032Speter { 270938032Speter result = NULL; 271038032Speter *statp = EX_TEMPFAIL; 271138032Speter goto quick_exit; 271238032Speter } 271338032Speter 271438032Speter /* Get ldap struct pointer from map */ 271538032Speter lmap = (LDAP_MAP_STRUCT *) map->map_db1; 271638032Speter 271738032Speter name_len = strlen(name); 271838032Speter if (name_len > MAXNAME) 271938032Speter name_len = MAXNAME; 272038032Speter strncpy(keybuf, name, name_len); 272138032Speter keybuf[name_len] = '\0'; 272238032Speter 272338032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 272438032Speter#ifdef SUNET_ID 272538032Speter sunet_id_hash(keybuf); 272638032Speter#else 272738032Speter makelower(keybuf); 272838032Speter#endif /*SUNET_ID */ 272938032Speter 273038032Speter /* sprintf keybuf into filter */ 273138032Speter snprintf(filter, sizeof filter, lmap->filter, keybuf); 273238032Speter 273338032Speter if (ldap_search_st(lmap->ld, lmap->base,lmap->scope,filter, 273438032Speter lmap->attr, lmap->attrsonly, &(lmap->timeout), 273538032Speter &(lmap->res)) != LDAP_SUCCESS) 273638032Speter { 273738032Speter /* try close/opening map */ 273838032Speter ldap_map_close(map); 273938032Speter if (!ldap_map_start(map)) 274038032Speter { 274138032Speter result = NULL; 274238032Speter *statp = EX_TEMPFAIL; 274338032Speter goto quick_exit; 274438032Speter } 274538032Speter if (ldap_search_st(lmap->ld, lmap->base, lmap->scope, filter, 274638032Speter lmap->attr, lmap->attrsonly, 274738032Speter &(lmap->timeout), &(lmap->res)) 274838032Speter != LDAP_SUCCESS) 274938032Speter { 275038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 275138032Speter { 275238032Speter syserr("Error in ldap_search_st using %s in map %s", 275338032Speter filter, map->map_mname); 275438032Speter } 275538032Speter result = NULL; 275638032Speter *statp = EX_TEMPFAIL; 275738032Speter goto quick_exit; 275838032Speter } 275938032Speter } 276038032Speter 276138032Speter entry = ldap_first_entry(lmap->ld,lmap->res); 276238032Speter if (entry == NULL) 276338032Speter { 276438032Speter result = NULL; 276538032Speter *statp = EX_NOTFOUND; 276638032Speter goto quick_exit; 276738032Speter } 276838032Speter 276938032Speter /* Need to build the args for map_rewrite here */ 277038032Speter attr_values = ldap_get_values(lmap->ld,entry,lmap->attr[0]); 277138032Speter if (attr_values == NULL) 277238032Speter { 277338032Speter /* bad things happened */ 277438032Speter result = NULL; 277538032Speter *statp = EX_NOTFOUND; 277638032Speter goto quick_exit; 277738032Speter } 277838032Speter 277938032Speter *statp = EX_OK; 278038032Speter 278138032Speter /* If there is more that one use the first */ 278238032Speter vp = attr_values[0]; 278338032Speter vsize = strlen(vp); 278438032Speter 278538032Speter if (LogLevel > 9) 278638032Speter sm_syslog(LOG_INFO, CurEnv->e_id, 278738032Speter "ldap %.100s => %s", 278838032Speter name, vp); 278938032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 279038032Speter result = map_rewrite(map, name, strlen(name), NULL); 279138032Speter else 279238032Speter result = map_rewrite(map, vp, vsize, av); 279338032Speter 279438032Speter quick_exit: 279538032Speter if (attr_values != NULL) 279638032Speter ldap_value_free(attr_values); 279738032Speter if (lmap != NULL) 279838032Speter ldap_msgfree(lmap->res); 279938032Speter ldap_map_close(map); 280038032Speter return result ; 280138032Speter} 280238032Speter 280338032Speter 280438032Speter/* 280538032Speter** LDAP_MAP_DEQUOTE - helper routine for ldap_map_parseargs 280638032Speter*/ 280738032Speter 280838032Speterchar * 280938032Speterldap_map_dequote(str) 281038032Speter char *str; 281138032Speter{ 281238032Speter char *p; 281338032Speter char *start; 281438032Speter p = str; 281538032Speter 281638032Speter if (*p == '"') 281738032Speter { 281838032Speter start = ++p; 281938032Speter /* Should probably swallow initial whitespace here */ 282038032Speter } 282138032Speter else 282238032Speter { 282338032Speter return(str); 282438032Speter } 282538032Speter while (*p != '"' && *p != '\0') 282638032Speter { 282738032Speter p++; 282838032Speter } 282938032Speter if (*p != '\0') 283038032Speter *p = '\0'; 283138032Speter return start; 283238032Speter} 283338032Speter 283438032Speter/* 283538032Speter** LDAP_MAP_PARSEARGS -- parse ldap map definition args. 283638032Speter*/ 283738032Speter 283838032Speterbool 283938032Speterldap_map_parseargs(map,args) 284038032Speter MAP *map; 284138032Speter char *args; 284238032Speter{ 284338032Speter register char *p = args; 284438032Speter register int done; 284538032Speter LDAP_MAP_STRUCT *lmap; 284638032Speter 284738032Speter /* We need to alloc an LDAP_MAP_STRUCT struct */ 284838032Speter lmap = (LDAP_MAP_STRUCT *) xalloc(sizeof(LDAP_MAP_STRUCT)); 284938032Speter 285038032Speter /* Set default int's here , default strings below */ 285138032Speter lmap->ldapport = DEFAULT_LDAP_MAP_PORT; 285238032Speter lmap->deref = DEFAULT_LDAP_MAP_DEREF; 285338032Speter lmap->timelimit = DEFAULT_LDAP_MAP_TIMELIMIT; 285438032Speter lmap->sizelimit = DEFAULT_LDAP_MAP_SIZELIMIT; 285538032Speter lmap->ldap_options = DEFAULT_LDAP_MAP_LDAP_OPTIONS; 285638032Speter lmap->method = DEFAULT_LDAP_MAP_METHOD; 285738032Speter lmap->scope = DEFAULT_LDAP_MAP_SCOPE; 285838032Speter lmap->attrsonly = DEFAULT_LDAP_MAP_ATTRSONLY; 285938032Speter lmap->timeout.tv_sec = DEFAULT_LDAP_MAP_TIMELIMIT; 286038032Speter lmap->timeout.tv_usec = 0; 286138032Speter 286238032Speter /* Default char ptrs to NULL */ 286338032Speter lmap->binddn = NULL; 286438032Speter lmap->passwd = NULL; 286538032Speter lmap->base = NULL; 286638032Speter lmap->ldaphost = NULL; 286738032Speter 286838032Speter /* Default general ptrs to NULL */ 286938032Speter lmap->ld = NULL; 287038032Speter lmap->res = NULL; 287138032Speter 287238032Speter map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; 287338032Speter for (;;) 287438032Speter { 287538032Speter while (isascii(*p) && isspace(*p)) 287638032Speter p++; 287738032Speter if (*p != '-') 287838032Speter break; 287938032Speter switch (*++p) 288038032Speter { 288138032Speter case 'N': 288238032Speter map->map_mflags |= MF_INCLNULL; 288338032Speter map->map_mflags &= ~MF_TRY0NULL; 288438032Speter break; 288538032Speter 288638032Speter case 'O': 288738032Speter map->map_mflags &= ~MF_TRY1NULL; 288838032Speter break; 288938032Speter 289038032Speter case 'o': 289138032Speter map->map_mflags |= MF_OPTIONAL; 289238032Speter break; 289338032Speter 289438032Speter case 'f': 289538032Speter map->map_mflags |= MF_NOFOLDCASE; 289638032Speter break; 289738032Speter 289838032Speter case 'm': 289938032Speter map->map_mflags |= MF_MATCHONLY; 290038032Speter break; 290138032Speter 290238032Speter case 'A': 290338032Speter map->map_mflags |= MF_APPEND; 290438032Speter break; 290538032Speter 290638032Speter case 'q': 290738032Speter map->map_mflags |= MF_KEEPQUOTES; 290838032Speter break; 290938032Speter 291038032Speter case 't': 291138032Speter map->map_mflags |= MF_NODEFER; 291238032Speter break; 291338032Speter 291438032Speter case 'a': 291538032Speter map->map_app = ++p; 291638032Speter break; 291738032Speter 291838032Speter case 'T': 291938032Speter map->map_tapp = ++p; 292038032Speter break; 292138032Speter 292238032Speter /* Start of ldap_map specific args */ 292338032Speter case 'k': /* search field */ 292438032Speter while (isascii(*++p) && isspace(*p)) 292538032Speter continue; 292638032Speter lmap->filter = p; 292738032Speter break; 292838032Speter 292938032Speter case 'v': /* attr to return */ 293038032Speter while (isascii(*++p) && isspace(*p)) 293138032Speter continue; 293238032Speter lmap->attr[0] = p; 293338032Speter lmap->attr[1] = NULL; 293438032Speter break; 293538032Speter 293638032Speter /* args stolen from ldapsearch.c */ 293738032Speter case 'R': /* don't auto chase referrals */ 293838032Speter#ifdef LDAP_REFERRALS 293938032Speter lmap->ldap_options &= ~LDAP_OPT_REFERRALS; 294038032Speter#else /* LDAP_REFERRALS */ 294138032Speter syserr("compile with -DLDAP_REFERRALS for referral support\n"); 294238032Speter#endif /* LDAP_REFERRALS */ 294338032Speter break; 294438032Speter 294538032Speter case 'n': /* retrieve attribute names only -- no values */ 294638032Speter lmap->attrsonly += 1; 294738032Speter break; 294838032Speter 294938032Speter case 's': /* search scope */ 295038032Speter if (strncasecmp(++p, "base", 4) == 0) 295138032Speter { 295238032Speter lmap->scope = LDAP_SCOPE_BASE; 295338032Speter } 295438032Speter else if (strncasecmp(p, "one", 3) == 0) 295538032Speter { 295638032Speter lmap->scope = LDAP_SCOPE_ONELEVEL; 295738032Speter } 295838032Speter else if (strncasecmp(p, "sub", 3) == 0) 295938032Speter { 296038032Speter lmap->scope = LDAP_SCOPE_SUBTREE; 296138032Speter } 296238032Speter else 296338032Speter { /* bad config line */ 296438032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 296538032Speter { 296638032Speter char *ptr; 296738032Speter 296838032Speter if ((ptr = strchr(p, ' ')) != NULL) 296938032Speter *ptr = '\0'; 297038032Speter syserr("Scope must be [base|one|sub] not %s in map %s", 297138032Speter p, map->map_mname); 297238032Speter if (ptr != NULL) 297338032Speter *ptr = ' '; 297438032Speter return FALSE; 297538032Speter } 297638032Speter } 297738032Speter break; 297838032Speter 297938032Speter case 'h': /* ldap host */ 298038032Speter while (isascii(*++p) && isspace(*p)) 298138032Speter continue; 298238032Speter map->map_domain = p; 298338032Speter lmap->ldaphost = p; 298438032Speter break; 298538032Speter 298638032Speter case 'b': /* search base */ 298738032Speter while (isascii(*++p) && isspace(*p)) 298838032Speter continue; 298938032Speter lmap->base = p; 299038032Speter break; 299138032Speter 299238032Speter case 'p': /* ldap port */ 299338032Speter while (isascii(*++p) && isspace(*p)) 299438032Speter continue; 299538032Speter lmap->ldapport = atoi(p); 299638032Speter break; 299738032Speter 299838032Speter case 'l': /* time limit */ 299938032Speter while (isascii(*++p) && isspace(*p)) 300038032Speter continue; 300138032Speter lmap->timelimit = atoi(p); 300238032Speter lmap->timeout.tv_sec = lmap->timelimit; 300338032Speter break; 300438032Speter 300538032Speter } 300638032Speter 300738032Speter /* need to account for quoted strings here arggg... */ 300838032Speter done = isascii(*p) && isspace(*p); 300938032Speter while (*p != '\0' && !done) 301038032Speter { 301138032Speter if (*p == '"') 301238032Speter { 301338032Speter while (*++p != '"' && *p != '\0') 301438032Speter { 301538032Speter continue; 301638032Speter } 301738032Speter if (*p != '\0') 301838032Speter p++; 301938032Speter } 302038032Speter else 302138032Speter { 302238032Speter p++; 302338032Speter } 302438032Speter done = isascii(*p) && isspace(*p); 302538032Speter } 302638032Speter 302738032Speter if (*p != '\0') 302838032Speter *p++ = '\0'; 302938032Speter } 303038032Speter 303138032Speter if (map->map_app != NULL) 303238032Speter map->map_app = newstr(ldap_map_dequote(map->map_app)); 303338032Speter if (map->map_tapp != NULL) 303438032Speter map->map_tapp = newstr(ldap_map_dequote(map->map_tapp)); 303538032Speter if (map->map_domain != NULL) 303638032Speter map->map_domain = newstr(ldap_map_dequote(map->map_domain)); 303738032Speter 303838032Speter /* 303938032Speter ** We need to swallow up all the stuff into a struct 304038032Speter ** and dump it into map->map_dbptr1 304138032Speter */ 304238032Speter 304338032Speter if (lmap->ldaphost != NULL) 304438032Speter lmap->ldaphost = newstr(ldap_map_dequote(lmap->ldaphost)); 304538032Speter else 304638032Speter { 304738032Speter syserr("LDAP map: -h flag is required"); 304838032Speter return FALSE; 304938032Speter } 305038032Speter 305138032Speter if (lmap->binddn != NULL) 305238032Speter lmap->binddn = newstr(ldap_map_dequote(lmap->binddn)); 305338032Speter else 305438032Speter lmap->binddn = DEFAULT_LDAP_MAP_BINDDN; 305538032Speter 305638032Speter 305738032Speter if (lmap->passwd != NULL) 305838032Speter lmap->passwd = newstr(ldap_map_dequote(lmap->passwd)); 305938032Speter else 306038032Speter lmap->passwd = DEFAULT_LDAP_MAP_PASSWD; 306138032Speter 306238032Speter if (lmap->base != NULL) 306338032Speter lmap->base = newstr(ldap_map_dequote(lmap->base)); 306438032Speter else 306538032Speter { 306638032Speter syserr("LDAP map: -b flag is required"); 306738032Speter return FALSE; 306838032Speter } 306938032Speter 307038032Speter 307138032Speter if (lmap->filter != NULL) 307238032Speter lmap->filter = newstr(ldap_map_dequote(lmap->filter)); 307338032Speter else 307438032Speter { 307538032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 307638032Speter { 307738032Speter syserr("No filter given in map %s", map->map_mname); 307838032Speter return FALSE; 307938032Speter } 308038032Speter } 308138032Speter if (lmap->attr[0] != NULL) 308238032Speter lmap->attr[0] = newstr(ldap_map_dequote(lmap->attr[0])); 308338032Speter else 308438032Speter { 308538032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 308638032Speter { 308738032Speter syserr("No return attribute in %s", map->map_mname); 308838032Speter return FALSE; 308938032Speter } 309038032Speter } 309138032Speter 309238032Speter map->map_db1 = (ARBPTR_T) lmap; 309338032Speter return TRUE; 309438032Speter} 309538032Speter 309638032Speter#endif /* LDAP Modules */ 309738032Speter/* 309838032Speter** syslog map 309938032Speter*/ 310038032Speter 310138032Speter#if _FFR_MAP_SYSLOG 310238032Speter 310338032Speter#define map_prio map_lockfd /* overload field */ 310438032Speter 310538032Speter/* 310638032Speter** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 310738032Speter*/ 310838032Speter 310938032Speterbool 311038032Spetersyslog_map_parseargs(map, args) 311138032Speter MAP *map; 311238032Speter char *args; 311338032Speter{ 311438032Speter char *p = args; 311538032Speter char *priority = NULL; 311638032Speter 311738032Speter for (;;) 311838032Speter { 311938032Speter while (isascii(*p) && isspace(*p)) 312038032Speter p++; 312138032Speter if (*p != '-') 312238032Speter break; 312338032Speter if (*++p == 'L') 312438032Speter priority = ++p; 312538032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 312638032Speter p++; 312738032Speter if (*p != '\0') 312838032Speter *p++ = '\0'; 312938032Speter } 313038032Speter 313138032Speter if (priority == NULL) 313238032Speter map->map_prio = LOG_INFO; 313338032Speter else 313438032Speter { 313538032Speter if (strncasecmp("LOG_", priority, 4) == 0) 313638032Speter priority += 4; 313738032Speter 313838032Speter#ifdef LOG_EMERG 313938032Speter if (strcasecmp("EMERG", priority) == 0) 314038032Speter map->map_prio = LOG_EMERG; 314138032Speter else 314238032Speter#endif 314338032Speter#ifdef LOG_ALERT 314438032Speter if (strcasecmp("ALERT", priority) == 0) 314538032Speter map->map_prio = LOG_ALERT; 314638032Speter else 314738032Speter#endif 314838032Speter#ifdef LOG_CRIT 314938032Speter if (strcasecmp("CRIT", priority) == 0) 315038032Speter map->map_prio = LOG_CRIT; 315138032Speter else 315238032Speter#endif 315338032Speter#ifdef LOG_ERR 315438032Speter if (strcasecmp("ERR", priority) == 0) 315538032Speter map->map_prio = LOG_ERR; 315638032Speter else 315738032Speter#endif 315838032Speter#ifdef LOG_WARNING 315938032Speter if (strcasecmp("WARNING", priority) == 0) 316038032Speter map->map_prio = LOG_WARNING; 316138032Speter else 316238032Speter#endif 316338032Speter#ifdef LOG_NOTICE 316438032Speter if (strcasecmp("NOTICE", priority) == 0) 316538032Speter map->map_prio = LOG_NOTICE; 316638032Speter else 316738032Speter#endif 316838032Speter#ifdef LOG_INFO 316938032Speter if (strcasecmp("INFO", priority) == 0) 317038032Speter map->map_prio = LOG_INFO; 317138032Speter else 317238032Speter#endif 317338032Speter#ifdef LOG_DEBUG 317438032Speter if (strcasecmp("DEBUG", priority) == 0) 317538032Speter map->map_prio = LOG_DEBUG; 317638032Speter else 317738032Speter#endif 317838032Speter { 317938032Speter syserr("syslog_map_parseargs: Unknown priority %s\n", 318038032Speter priority); 318138032Speter return FALSE; 318238032Speter } 318338032Speter } 318438032Speter return TRUE; 318538032Speter} 318638032Speter 318738032Speter/* 318838032Speter** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 318938032Speter*/ 319038032Speter 319138032Speterchar * 319238032Spetersyslog_map_lookup(map, string, args, statp) 319338032Speter MAP *map; 319438032Speter char *string; 319538032Speter char **args; 319638032Speter int *statp; 319738032Speter{ 319838032Speter char *ptr = map_rewrite(map, string, strlen(string), args); 319938032Speter 320038032Speter if (ptr != NULL) 320138032Speter { 320238032Speter if (tTd(38, 20)) 320338032Speter printf("syslog_map_lookup(%s (priority %d): %s\n", 320438032Speter map->map_mname, map->map_prio, ptr); 320538032Speter 320638032Speter sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); 320738032Speter } 320838032Speter 320938032Speter *statp = EX_OK; 321038032Speter return ""; 321138032Speter} 321238032Speter 321338032Speter#endif /* _FFR_MAP_SYSLOG */ 321438032Speter/* 321538032Speter** HESIOD Modules 321638032Speter*/ 321738032Speter 321838032Speter#ifdef HESIOD 321938032Speter 322038032Speterbool 322138032Speterhes_map_open(map, mode) 322238032Speter MAP *map; 322338032Speter int mode; 322438032Speter{ 322538032Speter if (tTd(38, 2)) 322638032Speter printf("hes_map_open(%s, %s, %d)\n", 322738032Speter map->map_mname, map->map_file, mode); 322838032Speter 322938032Speter if (mode != O_RDONLY) 323038032Speter { 323138032Speter /* issue a pseudo-error message */ 323238032Speter#ifdef ENOSYS 323338032Speter errno = ENOSYS; 323438032Speter#else 323538032Speter# ifdef EFTYPE 323638032Speter errno = EFTYPE; 323738032Speter# else 323838032Speter errno = ENXIO; 323938032Speter# endif 324038032Speter#endif 324138032Speter return FALSE; 324238032Speter } 324338032Speter 324438032Speter#ifdef HESIOD_INIT 324538032Speter if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) 324638032Speter return TRUE; 324738032Speter 324838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 324938032Speter syserr("421 cannot initialize Hesiod map (%s)", 325038032Speter errstring(errno)); 325138032Speter return FALSE; 325238032Speter#else 325338032Speter if (hes_error() == HES_ER_UNINIT) 325438032Speter hes_init(); 325538032Speter switch (hes_error()) 325638032Speter { 325738032Speter case HES_ER_OK: 325838032Speter case HES_ER_NOTFOUND: 325938032Speter return TRUE; 326038032Speter } 326138032Speter 326238032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 326338032Speter syserr("421 cannot initialize Hesiod map (%d)", hes_error()); 326438032Speter 326538032Speter return FALSE; 326638032Speter#endif /* HESIOD_INIT */ 326738032Speter} 326838032Speter 326938032Speterchar * 327038032Speterhes_map_lookup(map, name, av, statp) 327138032Speter MAP *map; 327238032Speter char *name; 327338032Speter char **av; 327438032Speter int *statp; 327538032Speter{ 327638032Speter char **hp; 327738032Speter 327838032Speter if (tTd(38, 20)) 327938032Speter printf("hes_map_lookup(%s, %s)\n", map->map_file, name); 328038032Speter 328138032Speter if (name[0] == '\\') 328238032Speter { 328338032Speter char *np; 328438032Speter int nl; 328538032Speter char nbuf[MAXNAME]; 328638032Speter 328738032Speter nl = strlen(name); 328838032Speter if (nl < sizeof nbuf - 1) 328938032Speter np = nbuf; 329038032Speter else 329138032Speter np = xalloc(strlen(name) + 2); 329238032Speter np[0] = '\\'; 329338032Speter strcpy(&np[1], name); 329438032Speter#ifdef HESIOD_INIT 329538032Speter hp = hesiod_resolve(HesiodContext, np, map->map_file); 329638032Speter#else 329738032Speter hp = hes_resolve(np, map->map_file); 329838032Speter#endif /* HESIOD_INIT */ 329938032Speter if (np != nbuf) 330038032Speter free(np); 330138032Speter } 330238032Speter else 330338032Speter { 330438032Speter#ifdef HESIOD_INIT 330538032Speter hp = hesiod_resolve(HesiodContext, name, map->map_file); 330638032Speter#else 330738032Speter hp = hes_resolve(name, map->map_file); 330838032Speter#endif /* HESIOD_INIT */ 330938032Speter } 331038032Speter#ifdef HESIOD_INIT 331138032Speter if (hp == NULL) 331238032Speter return NULL; 331338032Speter if (*hp == NULL) 331438032Speter { 331538032Speter hesiod_free_list(HesiodContext, hp); 331638032Speter switch (errno) 331738032Speter { 331838032Speter case ENOENT: 331938032Speter *statp = EX_NOTFOUND; 332038032Speter break; 332138032Speter case ECONNREFUSED: 332238032Speter case EMSGSIZE: 332338032Speter *statp = EX_TEMPFAIL; 332438032Speter break; 332538032Speter case ENOMEM: 332638032Speter default: 332738032Speter *statp = EX_UNAVAILABLE; 332838032Speter break; 332938032Speter } 333038032Speter return NULL; 333138032Speter } 333238032Speter#else 333338032Speter if (hp == NULL || hp[0] == NULL) 333438032Speter { 333538032Speter switch (hes_error()) 333638032Speter { 333738032Speter case HES_ER_OK: 333838032Speter *statp = EX_OK; 333938032Speter break; 334038032Speter 334138032Speter case HES_ER_NOTFOUND: 334238032Speter *statp = EX_NOTFOUND; 334338032Speter break; 334438032Speter 334538032Speter case HES_ER_CONFIG: 334638032Speter *statp = EX_UNAVAILABLE; 334738032Speter break; 334838032Speter 334938032Speter case HES_ER_NET: 335038032Speter *statp = EX_TEMPFAIL; 335138032Speter break; 335238032Speter } 335338032Speter return NULL; 335438032Speter } 335538032Speter#endif /* HESIOD_INIT */ 335638032Speter 335738032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 335838032Speter return map_rewrite(map, name, strlen(name), NULL); 335938032Speter else 336038032Speter return map_rewrite(map, hp[0], strlen(hp[0]), av); 336138032Speter} 336238032Speter 336338032Speter#endif 336438032Speter/* 336538032Speter** NeXT NETINFO Modules 336638032Speter*/ 336738032Speter 336838032Speter#if NETINFO 336938032Speter 337038032Speter# define NETINFO_DEFAULT_DIR "/aliases" 337138032Speter# define NETINFO_DEFAULT_PROPERTY "members" 337238032Speter 337338032Speterextern char *ni_propval __P((char *, char *, char *, char *, int)); 337438032Speter 337538032Speter 337638032Speter/* 337738032Speter** NI_MAP_OPEN -- open NetInfo Aliases 337838032Speter*/ 337938032Speter 338038032Speterbool 338138032Speterni_map_open(map, mode) 338238032Speter MAP *map; 338338032Speter int mode; 338438032Speter{ 338538032Speter char *p; 338638032Speter 338738032Speter if (tTd(38, 2)) 338838032Speter printf("ni_map_open(%s, %s, %d)\n", 338938032Speter map->map_mname, map->map_file, mode); 339038032Speter mode &= O_ACCMODE; 339138032Speter 339238032Speter if (*map->map_file == '\0') 339338032Speter map->map_file = NETINFO_DEFAULT_DIR; 339438032Speter 339538032Speter if (map->map_valcolnm == NULL) 339638032Speter map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 339738032Speter 339838032Speter if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 339938032Speter map->map_coldelim = ','; 340038032Speter 340138032Speter return TRUE; 340238032Speter} 340338032Speter 340438032Speter 340538032Speter/* 340638032Speter** NI_MAP_LOOKUP -- look up a datum in NetInfo 340738032Speter*/ 340838032Speter 340938032Speterchar * 341038032Speterni_map_lookup(map, name, av, statp) 341138032Speter MAP *map; 341238032Speter char *name; 341338032Speter char **av; 341438032Speter int *statp; 341538032Speter{ 341638032Speter char *res; 341738032Speter char *propval; 341838032Speter 341938032Speter if (tTd(38, 20)) 342038032Speter printf("ni_map_lookup(%s, %s)\n", map->map_mname, name); 342138032Speter 342238032Speter propval = ni_propval(map->map_file, map->map_keycolnm, name, 342338032Speter map->map_valcolnm, map->map_coldelim); 342438032Speter 342538032Speter if (propval == NULL) 342638032Speter return NULL; 342738032Speter 342838032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 342938032Speter res = map_rewrite(map, name, strlen(name), NULL); 343038032Speter else 343138032Speter res = map_rewrite(map, propval, strlen(propval), av); 343238032Speter free(propval); 343338032Speter return res; 343438032Speter} 343538032Speter 343638032Speter 343738032Speterbool 343838032Speterni_getcanonname(name, hbsize, statp) 343938032Speter char *name; 344038032Speter int hbsize; 344138032Speter int *statp; 344238032Speter{ 344338032Speter char *vptr; 344438032Speter char *ptr; 344538032Speter char nbuf[MAXNAME + 1]; 344638032Speter 344738032Speter if (tTd(38, 20)) 344838032Speter printf("ni_getcanonname(%s)\n", name); 344938032Speter 345038032Speter if (strlen(name) >= sizeof nbuf) 345138032Speter { 345238032Speter *statp = EX_UNAVAILABLE; 345338032Speter return FALSE; 345438032Speter } 345538032Speter (void) strcpy(nbuf, name); 345638032Speter shorten_hostname(nbuf); 345738032Speter 345838032Speter /* we only accept single token search key */ 345938032Speter if (strchr(nbuf, '.')) 346038032Speter { 346138032Speter *statp = EX_NOHOST; 346238032Speter return FALSE; 346338032Speter } 346438032Speter 346538032Speter /* Do the search */ 346638032Speter vptr = ni_propval("/machines", NULL, nbuf, "name", '\n'); 346738032Speter 346838032Speter if (vptr == NULL) 346938032Speter { 347038032Speter *statp = EX_NOHOST; 347138032Speter return FALSE; 347238032Speter } 347338032Speter 347438032Speter /* Only want the first machine name */ 347538032Speter if ((ptr = strchr(vptr, '\n')) != NULL) 347638032Speter *ptr = '\0'; 347738032Speter 347838032Speter if (hbsize >= strlen(vptr)) 347938032Speter { 348038032Speter strcpy(name, vptr); 348138032Speter *statp = EX_OK; 348238032Speter return TRUE; 348338032Speter } 348438032Speter *statp = EX_UNAVAILABLE; 348538032Speter free(vptr); 348638032Speter return FALSE; 348738032Speter} 348838032Speter 348938032Speter 349038032Speter/* 349138032Speter** NI_PROPVAL -- NetInfo property value lookup routine 349238032Speter** 349338032Speter** Parameters: 349438032Speter** keydir -- the NetInfo directory name in which to search 349538032Speter** for the key. 349638032Speter** keyprop -- the name of the property in which to find the 349738032Speter** property we are interested. Defaults to "name". 349838032Speter** keyval -- the value for which we are really searching. 349938032Speter** valprop -- the property name for the value in which we 350038032Speter** are interested. 350138032Speter** sepchar -- if non-nil, this can be multiple-valued, and 350238032Speter** we should return a string separated by this 350338032Speter** character. 350438032Speter** 350538032Speter** Returns: 350638032Speter** NULL -- if: 350738032Speter** 1. the directory is not found 350838032Speter** 2. the property name is not found 350938032Speter** 3. the property contains multiple values 351038032Speter** 4. some error occured 351138032Speter** else -- the value of the lookup. 351238032Speter** 351338032Speter** Example: 351438032Speter** To search for an alias value, use: 351538032Speter** ni_propval("/aliases", "name", aliasname, "members", ',') 351638032Speter** 351738032Speter** Notes: 351838032Speter** Caller should free the return value of ni_proval 351938032Speter*/ 352038032Speter 352138032Speter# include <netinfo/ni.h> 352238032Speter 352338032Speter# define LOCAL_NETINFO_DOMAIN "." 352438032Speter# define PARENT_NETINFO_DOMAIN ".." 352538032Speter# define MAX_NI_LEVELS 256 352638032Speter 352738032Speterchar * 352838032Speterni_propval(keydir, keyprop, keyval, valprop, sepchar) 352938032Speter char *keydir; 353038032Speter char *keyprop; 353138032Speter char *keyval; 353238032Speter char *valprop; 353338032Speter int sepchar; 353438032Speter{ 353538032Speter char *propval = NULL; 353638032Speter int i; 353738032Speter int j, alen; 353838032Speter void *ni = NULL; 353938032Speter void *lastni = NULL; 354038032Speter ni_status nis; 354138032Speter ni_id nid; 354238032Speter ni_namelist ninl; 354338032Speter register char *p; 354438032Speter char keybuf[1024]; 354538032Speter 354638032Speter /* 354738032Speter ** Create the full key from the two parts. 354838032Speter ** 354938032Speter ** Note that directory can end with, e.g., "name=" to specify 355038032Speter ** an alternate search property. 355138032Speter */ 355238032Speter 355338032Speter i = strlen(keydir) + strlen(keyval) + 2; 355438032Speter if (keyprop != NULL) 355538032Speter i += strlen(keyprop) + 1; 355638032Speter if (i > sizeof keybuf) 355738032Speter return NULL; 355838032Speter strcpy(keybuf, keydir); 355938032Speter strcat(keybuf, "/"); 356038032Speter if (keyprop != NULL) 356138032Speter { 356238032Speter strcat(keybuf, keyprop); 356338032Speter strcat(keybuf, "="); 356438032Speter } 356538032Speter strcat(keybuf, keyval); 356638032Speter 356738032Speter if (tTd(38, 21)) 356838032Speter printf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n", 356938032Speter keydir, keyprop, keyval, valprop, sepchar, keybuf); 357038032Speter /* 357138032Speter ** If the passed directory and property name are found 357238032Speter ** in one of netinfo domains we need to search (starting 357338032Speter ** from the local domain moving all the way back to the 357438032Speter ** root domain) set propval to the property's value 357538032Speter ** and return it. 357638032Speter */ 357738032Speter 357838032Speter for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++) 357938032Speter { 358038032Speter if (i == 0) 358138032Speter { 358238032Speter nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); 358338032Speter if (tTd(38, 20)) 358438032Speter printf("ni_open(LOCAL) = %d\n", nis); 358538032Speter } 358638032Speter else 358738032Speter { 358838032Speter if (lastni != NULL) 358938032Speter ni_free(lastni); 359038032Speter lastni = ni; 359138032Speter nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); 359238032Speter if (tTd(38, 20)) 359338032Speter printf("ni_open(PARENT) = %d\n", nis); 359438032Speter } 359538032Speter 359638032Speter /* 359738032Speter ** Don't bother if we didn't get a handle on a 359838032Speter ** proper domain. This is not necessarily an error. 359938032Speter ** We would get a positive ni_status if, for instance 360038032Speter ** we never found the directory or property and tried 360138032Speter ** to open the parent of the root domain! 360238032Speter */ 360338032Speter 360438032Speter if (nis != 0) 360538032Speter break; 360638032Speter 360738032Speter /* 360838032Speter ** Find the path to the server information. 360938032Speter */ 361038032Speter 361138032Speter if (ni_pathsearch(ni, &nid, keybuf) != 0) 361238032Speter continue; 361338032Speter 361438032Speter /* 361538032Speter ** Find associated value information. 361638032Speter */ 361738032Speter 361838032Speter if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0) 361938032Speter continue; 362038032Speter 362138032Speter if (tTd(38, 20)) 362238032Speter printf("ni_lookupprop: len=%d\n", ninl.ni_namelist_len); 362338032Speter /* 362438032Speter ** See if we have an acceptable number of values. 362538032Speter */ 362638032Speter 362738032Speter if (ninl.ni_namelist_len <= 0) 362838032Speter continue; 362938032Speter 363038032Speter if (sepchar == '\0' && ninl.ni_namelist_len > 1) 363138032Speter { 363238032Speter ni_namelist_free(&ninl); 363338032Speter continue; 363438032Speter } 363538032Speter 363638032Speter /* 363738032Speter ** Calculate number of bytes needed and build result 363838032Speter */ 363938032Speter 364038032Speter alen = 1; 364138032Speter for (j = 0; j < ninl.ni_namelist_len; j++) 364238032Speter alen += strlen(ninl.ni_namelist_val[j]) + 1; 364338032Speter propval = p = xalloc(alen); 364438032Speter for (j = 0; j < ninl.ni_namelist_len; j++) 364538032Speter { 364638032Speter strcpy(p, ninl.ni_namelist_val[j]); 364738032Speter p += strlen(p); 364838032Speter *p++ = sepchar; 364938032Speter } 365038032Speter *--p = '\0'; 365138032Speter 365238032Speter ni_namelist_free(&ninl); 365338032Speter } 365438032Speter 365538032Speter /* 365638032Speter ** Clean up. 365738032Speter */ 365838032Speter 365938032Speter if (ni != NULL) 366038032Speter ni_free(ni); 366138032Speter if (lastni != NULL && ni != lastni) 366238032Speter ni_free(lastni); 366338032Speter if (tTd(38, 20)) 366438032Speter printf("ni_propval returns: '%s'\n", propval); 366538032Speter 366638032Speter return propval; 366738032Speter} 366838032Speter 366938032Speter#endif 367038032Speter/* 367138032Speter** TEXT (unindexed text file) Modules 367238032Speter** 367338032Speter** This code donated by Sun Microsystems. 367438032Speter*/ 367538032Speter 367638032Speter#define map_sff map_lockfd /* overload field */ 367738032Speter 367838032Speter 367938032Speter/* 368038032Speter** TEXT_MAP_OPEN -- open text table 368138032Speter*/ 368238032Speter 368338032Speterbool 368438032Spetertext_map_open(map, mode) 368538032Speter MAP *map; 368638032Speter int mode; 368738032Speter{ 368838032Speter int sff; 368938032Speter int i; 369038032Speter 369138032Speter if (tTd(38, 2)) 369238032Speter printf("text_map_open(%s, %s, %d)\n", 369338032Speter map->map_mname, map->map_file, mode); 369438032Speter 369538032Speter mode &= O_ACCMODE; 369638032Speter if (mode != O_RDONLY) 369738032Speter { 369838032Speter errno = EPERM; 369938032Speter return FALSE; 370038032Speter } 370138032Speter 370238032Speter if (*map->map_file == '\0') 370338032Speter { 370438032Speter syserr("text map \"%s\": file name required", 370538032Speter map->map_mname); 370638032Speter return FALSE; 370738032Speter } 370838032Speter 370938032Speter if (map->map_file[0] != '/') 371038032Speter { 371138032Speter syserr("text map \"%s\": file name must be fully qualified", 371238032Speter map->map_mname); 371338032Speter return FALSE; 371438032Speter } 371538032Speter 371638032Speter sff = SFF_ROOTOK|SFF_REGONLY; 371738032Speter if (!bitset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 371838032Speter sff |= SFF_NOWLINK; 371938032Speter if (!bitset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 372038032Speter sff |= SFF_SAFEDIRPATH; 372138032Speter if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, 372238032Speter sff, S_IRUSR, NULL)) != 0) 372338032Speter { 372438032Speter /* cannot open this map */ 372538032Speter if (tTd(38, 2)) 372638032Speter printf("\tunsafe map file: %d\n", i); 372738032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 372838032Speter syserr("text map \"%s\": unsafe map file %s", 372938032Speter map->map_mname, map->map_file); 373038032Speter return FALSE; 373138032Speter } 373238032Speter 373338032Speter if (map->map_keycolnm == NULL) 373438032Speter map->map_keycolno = 0; 373538032Speter else 373638032Speter { 373738032Speter if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) 373838032Speter { 373938032Speter syserr("text map \"%s\", file %s: -k should specify a number, not %s", 374038032Speter map->map_mname, map->map_file, 374138032Speter map->map_keycolnm); 374238032Speter return FALSE; 374338032Speter } 374438032Speter map->map_keycolno = atoi(map->map_keycolnm); 374538032Speter } 374638032Speter 374738032Speter if (map->map_valcolnm == NULL) 374838032Speter map->map_valcolno = 0; 374938032Speter else 375038032Speter { 375138032Speter if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) 375238032Speter { 375338032Speter syserr("text map \"%s\", file %s: -v should specify a number, not %s", 375438032Speter map->map_mname, map->map_file, 375538032Speter map->map_valcolnm); 375638032Speter return FALSE; 375738032Speter } 375838032Speter map->map_valcolno = atoi(map->map_valcolnm); 375938032Speter } 376038032Speter 376138032Speter if (tTd(38, 2)) 376238032Speter { 376338032Speter printf("text_map_open(%s, %s): delimiter = ", 376438032Speter map->map_mname, map->map_file); 376538032Speter if (map->map_coldelim == '\0') 376638032Speter printf("(white space)\n"); 376738032Speter else 376838032Speter printf("%c\n", map->map_coldelim); 376938032Speter } 377038032Speter 377138032Speter map->map_sff = sff; 377238032Speter return TRUE; 377338032Speter} 377438032Speter 377538032Speter 377638032Speter/* 377738032Speter** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 377838032Speter*/ 377938032Speter 378038032Speterchar * 378138032Spetertext_map_lookup(map, name, av, statp) 378238032Speter MAP *map; 378338032Speter char *name; 378438032Speter char **av; 378538032Speter int *statp; 378638032Speter{ 378738032Speter char *vp; 378838032Speter auto int vsize; 378938032Speter int buflen; 379038032Speter FILE *f; 379138032Speter char delim; 379238032Speter int key_idx; 379338032Speter bool found_it; 379438032Speter int sff = map->map_sff; 379538032Speter char search_key[MAXNAME + 1]; 379638032Speter char linebuf[MAXLINE]; 379738032Speter char buf[MAXNAME + 1]; 379838032Speter extern char *get_column __P((char *, int, char, char *, int)); 379938032Speter 380038032Speter found_it = FALSE; 380138032Speter if (tTd(38, 20)) 380238032Speter printf("text_map_lookup(%s, %s)\n", map->map_mname, name); 380338032Speter 380438032Speter buflen = strlen(name); 380538032Speter if (buflen > sizeof search_key - 1) 380638032Speter buflen = sizeof search_key - 1; 380738032Speter bcopy(name, search_key, buflen); 380838032Speter search_key[buflen] = '\0'; 380938032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 381038032Speter makelower(search_key); 381138032Speter 381238032Speter f = safefopen(map->map_file, O_RDONLY, FileMode, sff); 381338032Speter if (f == NULL) 381438032Speter { 381538032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 381638032Speter *statp = EX_UNAVAILABLE; 381738032Speter return NULL; 381838032Speter } 381938032Speter key_idx = map->map_keycolno; 382038032Speter delim = map->map_coldelim; 382138032Speter while (fgets(linebuf, MAXLINE, f) != NULL) 382238032Speter { 382338032Speter char *p; 382438032Speter 382538032Speter /* skip comment line */ 382638032Speter if (linebuf[0] == '#') 382738032Speter continue; 382838032Speter p = strchr(linebuf, '\n'); 382938032Speter if (p != NULL) 383038032Speter *p = '\0'; 383138032Speter p = get_column(linebuf, key_idx, delim, buf, sizeof buf); 383238032Speter if (p != NULL && strcasecmp(search_key, p) == 0) 383338032Speter { 383438032Speter found_it = TRUE; 383538032Speter break; 383638032Speter } 383738032Speter } 383838032Speter fclose(f); 383938032Speter if (!found_it) 384038032Speter { 384138032Speter *statp = EX_NOTFOUND; 384238032Speter return NULL; 384338032Speter } 384438032Speter vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf); 384538032Speter vsize = strlen(vp); 384638032Speter *statp = EX_OK; 384738032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 384838032Speter return map_rewrite(map, name, strlen(name), NULL); 384938032Speter else 385038032Speter return map_rewrite(map, vp, vsize, av); 385138032Speter} 385238032Speter 385338032Speter 385438032Speter/* 385538032Speter** TEXT_GETCANONNAME -- look up canonical name in hosts file 385638032Speter*/ 385738032Speter 385838032Speterbool 385938032Spetertext_getcanonname(name, hbsize, statp) 386038032Speter char *name; 386138032Speter int hbsize; 386238032Speter int *statp; 386338032Speter{ 386438032Speter bool found; 386538032Speter FILE *f; 386638032Speter char linebuf[MAXLINE]; 386738032Speter char cbuf[MAXNAME + 1]; 386838032Speter char nbuf[MAXNAME + 1]; 386938032Speter 387038032Speter if (tTd(38, 20)) 387138032Speter printf("text_getcanonname(%s)\n", name); 387238032Speter 387338032Speter if (strlen(name) >= (SIZE_T) sizeof nbuf) 387438032Speter { 387538032Speter *statp = EX_UNAVAILABLE; 387638032Speter return FALSE; 387738032Speter } 387838032Speter (void) strcpy(nbuf, name); 387938032Speter shorten_hostname(nbuf); 388038032Speter 388138032Speter f = fopen(HostsFile, "r"); 388238032Speter if (f == NULL) 388338032Speter { 388438032Speter *statp = EX_UNAVAILABLE; 388538032Speter return FALSE; 388638032Speter } 388738032Speter found = FALSE; 388838032Speter while (!found && fgets(linebuf, MAXLINE, f) != NULL) 388938032Speter { 389038032Speter char *p = strpbrk(linebuf, "#\n"); 389138032Speter 389238032Speter if (p != NULL) 389338032Speter *p = '\0'; 389438032Speter if (linebuf[0] != '\0') 389538032Speter found = extract_canonname(nbuf, linebuf, cbuf, sizeof cbuf); 389638032Speter } 389738032Speter fclose(f); 389838032Speter if (!found) 389938032Speter { 390038032Speter *statp = EX_NOHOST; 390138032Speter return FALSE; 390238032Speter } 390338032Speter 390438032Speter if ((SIZE_T) hbsize >= strlen(cbuf)) 390538032Speter { 390638032Speter strcpy(name, cbuf); 390738032Speter *statp = EX_OK; 390838032Speter return TRUE; 390938032Speter } 391038032Speter *statp = EX_UNAVAILABLE; 391138032Speter return FALSE; 391238032Speter} 391338032Speter/* 391438032Speter** STAB (Symbol Table) Modules 391538032Speter*/ 391638032Speter 391738032Speter 391838032Speter/* 391938032Speter** STAB_MAP_LOOKUP -- look up alias in symbol table 392038032Speter*/ 392138032Speter 392238032Speter/* ARGSUSED2 */ 392338032Speterchar * 392438032Speterstab_map_lookup(map, name, av, pstat) 392538032Speter register MAP *map; 392638032Speter char *name; 392738032Speter char **av; 392838032Speter int *pstat; 392938032Speter{ 393038032Speter register STAB *s; 393138032Speter 393238032Speter if (tTd(38, 20)) 393338032Speter printf("stab_lookup(%s, %s)\n", 393438032Speter map->map_mname, name); 393538032Speter 393638032Speter s = stab(name, ST_ALIAS, ST_FIND); 393738032Speter if (s != NULL) 393838032Speter return (s->s_alias); 393938032Speter return (NULL); 394038032Speter} 394138032Speter 394238032Speter 394338032Speter/* 394438032Speter** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 394538032Speter*/ 394638032Speter 394738032Spetervoid 394838032Speterstab_map_store(map, lhs, rhs) 394938032Speter register MAP *map; 395038032Speter char *lhs; 395138032Speter char *rhs; 395238032Speter{ 395338032Speter register STAB *s; 395438032Speter 395538032Speter s = stab(lhs, ST_ALIAS, ST_ENTER); 395638032Speter s->s_alias = newstr(rhs); 395738032Speter} 395838032Speter 395938032Speter 396038032Speter/* 396138032Speter** STAB_MAP_OPEN -- initialize (reads data file) 396238032Speter** 396338032Speter** This is a wierd case -- it is only intended as a fallback for 396438032Speter** aliases. For this reason, opens for write (only during a 396538032Speter** "newaliases") always fails, and opens for read open the 396638032Speter** actual underlying text file instead of the database. 396738032Speter*/ 396838032Speter 396938032Speterbool 397038032Speterstab_map_open(map, mode) 397138032Speter register MAP *map; 397238032Speter int mode; 397338032Speter{ 397438032Speter FILE *af; 397538032Speter int sff; 397638032Speter struct stat st; 397738032Speter 397838032Speter if (tTd(38, 2)) 397938032Speter printf("stab_map_open(%s, %s, %d)\n", 398038032Speter map->map_mname, map->map_file, mode); 398138032Speter 398238032Speter mode &= O_ACCMODE; 398338032Speter if (mode != O_RDONLY) 398438032Speter { 398538032Speter errno = EPERM; 398638032Speter return FALSE; 398738032Speter } 398838032Speter 398938032Speter sff = SFF_ROOTOK|SFF_REGONLY; 399038032Speter if (!bitset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 399138032Speter sff |= SFF_NOWLINK; 399238032Speter if (!bitset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 399338032Speter sff |= SFF_SAFEDIRPATH; 399438032Speter af = safefopen(map->map_file, O_RDONLY, 0444, sff); 399538032Speter if (af == NULL) 399638032Speter return FALSE; 399738032Speter readaliases(map, af, FALSE, FALSE); 399838032Speter 399938032Speter if (fstat(fileno(af), &st) >= 0) 400038032Speter map->map_mtime = st.st_mtime; 400138032Speter fclose(af); 400238032Speter 400338032Speter return TRUE; 400438032Speter} 400538032Speter/* 400638032Speter** Implicit Modules 400738032Speter** 400838032Speter** Tries several types. For back compatibility of aliases. 400938032Speter*/ 401038032Speter 401138032Speter 401238032Speter/* 401338032Speter** IMPL_MAP_LOOKUP -- lookup in best open database 401438032Speter*/ 401538032Speter 401638032Speterchar * 401738032Speterimpl_map_lookup(map, name, av, pstat) 401838032Speter MAP *map; 401938032Speter char *name; 402038032Speter char **av; 402138032Speter int *pstat; 402238032Speter{ 402338032Speter if (tTd(38, 20)) 402438032Speter printf("impl_map_lookup(%s, %s)\n", 402538032Speter map->map_mname, name); 402638032Speter 402738032Speter#ifdef NEWDB 402838032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 402938032Speter return db_map_lookup(map, name, av, pstat); 403038032Speter#endif 403138032Speter#ifdef NDBM 403238032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 403338032Speter return ndbm_map_lookup(map, name, av, pstat); 403438032Speter#endif 403538032Speter return stab_map_lookup(map, name, av, pstat); 403638032Speter} 403738032Speter 403838032Speter/* 403938032Speter** IMPL_MAP_STORE -- store in open databases 404038032Speter*/ 404138032Speter 404238032Spetervoid 404338032Speterimpl_map_store(map, lhs, rhs) 404438032Speter MAP *map; 404538032Speter char *lhs; 404638032Speter char *rhs; 404738032Speter{ 404838032Speter if (tTd(38, 12)) 404938032Speter printf("impl_map_store(%s, %s, %s)\n", 405038032Speter map->map_mname, lhs, rhs); 405138032Speter#ifdef NEWDB 405238032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 405338032Speter db_map_store(map, lhs, rhs); 405438032Speter#endif 405538032Speter#ifdef NDBM 405638032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 405738032Speter ndbm_map_store(map, lhs, rhs); 405838032Speter#endif 405938032Speter stab_map_store(map, lhs, rhs); 406038032Speter} 406138032Speter 406238032Speter/* 406338032Speter** IMPL_MAP_OPEN -- implicit database open 406438032Speter*/ 406538032Speter 406638032Speterbool 406738032Speterimpl_map_open(map, mode) 406838032Speter MAP *map; 406938032Speter int mode; 407038032Speter{ 407138032Speter if (tTd(38, 2)) 407238032Speter printf("impl_map_open(%s, %s, %d)\n", 407338032Speter map->map_mname, map->map_file, mode); 407438032Speter 407538032Speter mode &= O_ACCMODE; 407638032Speter#ifdef NEWDB 407738032Speter map->map_mflags |= MF_IMPL_HASH; 407838032Speter if (hash_map_open(map, mode)) 407938032Speter { 408038032Speter# ifdef NDBM_YP_COMPAT 408138032Speter if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 408238032Speter# endif 408338032Speter return TRUE; 408438032Speter } 408538032Speter else 408638032Speter map->map_mflags &= ~MF_IMPL_HASH; 408738032Speter#endif 408838032Speter#ifdef NDBM 408938032Speter map->map_mflags |= MF_IMPL_NDBM; 409038032Speter if (ndbm_map_open(map, mode)) 409138032Speter { 409238032Speter return TRUE; 409338032Speter } 409438032Speter else 409538032Speter map->map_mflags &= ~MF_IMPL_NDBM; 409638032Speter#endif 409738032Speter 409838032Speter#if defined(NEWDB) || defined(NDBM) 409938032Speter if (Verbose) 410038032Speter message("WARNING: cannot open alias database %s%s", 410138032Speter map->map_file, 410238032Speter mode == O_RDONLY ? "; reading text version" : ""); 410338032Speter#else 410438032Speter if (mode != O_RDONLY) 410538032Speter usrerr("Cannot rebuild aliases: no database format defined"); 410638032Speter#endif 410738032Speter 410838032Speter if (mode == O_RDONLY) 410938032Speter return stab_map_open(map, mode); 411038032Speter else 411138032Speter return FALSE; 411238032Speter} 411338032Speter 411438032Speter 411538032Speter/* 411638032Speter** IMPL_MAP_CLOSE -- close any open database(s) 411738032Speter*/ 411838032Speter 411938032Spetervoid 412038032Speterimpl_map_close(map) 412138032Speter MAP *map; 412238032Speter{ 412338032Speter if (tTd(38, 9)) 412438032Speter printf("impl_map_close(%s, %s, %lx)\n", 412538032Speter map->map_mname, map->map_file, map->map_mflags); 412638032Speter#ifdef NEWDB 412738032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 412838032Speter { 412938032Speter db_map_close(map); 413038032Speter map->map_mflags &= ~MF_IMPL_HASH; 413138032Speter } 413238032Speter#endif 413338032Speter 413438032Speter#ifdef NDBM 413538032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 413638032Speter { 413738032Speter ndbm_map_close(map); 413838032Speter map->map_mflags &= ~MF_IMPL_NDBM; 413938032Speter } 414038032Speter#endif 414138032Speter} 414238032Speter/* 414338032Speter** User map class. 414438032Speter** 414538032Speter** Provides access to the system password file. 414638032Speter*/ 414738032Speter 414838032Speter/* 414938032Speter** USER_MAP_OPEN -- open user map 415038032Speter** 415138032Speter** Really just binds field names to field numbers. 415238032Speter*/ 415338032Speter 415438032Speterbool 415538032Speteruser_map_open(map, mode) 415638032Speter MAP *map; 415738032Speter int mode; 415838032Speter{ 415938032Speter if (tTd(38, 2)) 416038032Speter printf("user_map_open(%s, %d)\n", 416138032Speter map->map_mname, mode); 416238032Speter 416338032Speter mode &= O_ACCMODE; 416438032Speter if (mode != O_RDONLY) 416538032Speter { 416638032Speter /* issue a pseudo-error message */ 416738032Speter#ifdef ENOSYS 416838032Speter errno = ENOSYS; 416938032Speter#else 417038032Speter# ifdef EFTYPE 417138032Speter errno = EFTYPE; 417238032Speter# else 417338032Speter errno = ENXIO; 417438032Speter# endif 417538032Speter#endif 417638032Speter return FALSE; 417738032Speter } 417838032Speter if (map->map_valcolnm == NULL) 417938032Speter /* nothing */ ; 418038032Speter else if (strcasecmp(map->map_valcolnm, "name") == 0) 418138032Speter map->map_valcolno = 1; 418238032Speter else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 418338032Speter map->map_valcolno = 2; 418438032Speter else if (strcasecmp(map->map_valcolnm, "uid") == 0) 418538032Speter map->map_valcolno = 3; 418638032Speter else if (strcasecmp(map->map_valcolnm, "gid") == 0) 418738032Speter map->map_valcolno = 4; 418838032Speter else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 418938032Speter map->map_valcolno = 5; 419038032Speter else if (strcasecmp(map->map_valcolnm, "dir") == 0) 419138032Speter map->map_valcolno = 6; 419238032Speter else if (strcasecmp(map->map_valcolnm, "shell") == 0) 419338032Speter map->map_valcolno = 7; 419438032Speter else 419538032Speter { 419638032Speter syserr("User map %s: unknown column name %s", 419738032Speter map->map_mname, map->map_valcolnm); 419838032Speter return FALSE; 419938032Speter } 420038032Speter return TRUE; 420138032Speter} 420238032Speter 420338032Speter 420438032Speter/* 420538032Speter** USER_MAP_LOOKUP -- look up a user in the passwd file. 420638032Speter*/ 420738032Speter 420838032Speter/* ARGSUSED3 */ 420938032Speterchar * 421038032Speteruser_map_lookup(map, key, av, statp) 421138032Speter MAP *map; 421238032Speter char *key; 421338032Speter char **av; 421438032Speter int *statp; 421538032Speter{ 421638032Speter struct passwd *pw; 421738032Speter auto bool fuzzy; 421838032Speter 421938032Speter if (tTd(38, 20)) 422038032Speter printf("user_map_lookup(%s, %s)\n", 422138032Speter map->map_mname, key); 422238032Speter 422338032Speter pw = finduser(key, &fuzzy); 422438032Speter if (pw == NULL) 422538032Speter return NULL; 422638032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 422738032Speter return map_rewrite(map, key, strlen(key), NULL); 422838032Speter else 422938032Speter { 423038032Speter char *rwval = NULL; 423138032Speter char buf[30]; 423238032Speter 423338032Speter switch (map->map_valcolno) 423438032Speter { 423538032Speter case 0: 423638032Speter case 1: 423738032Speter rwval = pw->pw_name; 423838032Speter break; 423938032Speter 424038032Speter case 2: 424138032Speter rwval = pw->pw_passwd; 424238032Speter break; 424338032Speter 424438032Speter case 3: 424538032Speter snprintf(buf, sizeof buf, "%d", pw->pw_uid); 424638032Speter rwval = buf; 424738032Speter break; 424838032Speter 424938032Speter case 4: 425038032Speter snprintf(buf, sizeof buf, "%d", pw->pw_gid); 425138032Speter rwval = buf; 425238032Speter break; 425338032Speter 425438032Speter case 5: 425538032Speter rwval = pw->pw_gecos; 425638032Speter break; 425738032Speter 425838032Speter case 6: 425938032Speter rwval = pw->pw_dir; 426038032Speter break; 426138032Speter 426238032Speter case 7: 426338032Speter rwval = pw->pw_shell; 426438032Speter break; 426538032Speter } 426638032Speter return map_rewrite(map, rwval, strlen(rwval), av); 426738032Speter } 426838032Speter} 426938032Speter/* 427038032Speter** Program map type. 427138032Speter** 427238032Speter** This provides access to arbitrary programs. It should be used 427338032Speter** only very sparingly, since there is no way to bound the cost 427438032Speter** of invoking an arbitrary program. 427538032Speter*/ 427638032Speter 427738032Speterchar * 427838032Speterprog_map_lookup(map, name, av, statp) 427938032Speter MAP *map; 428038032Speter char *name; 428138032Speter char **av; 428238032Speter int *statp; 428338032Speter{ 428438032Speter int i; 428538032Speter register char *p; 428638032Speter int fd; 428738032Speter auto pid_t pid; 428838032Speter char *rval; 428938032Speter int stat; 429038032Speter char *argv[MAXPV + 1]; 429138032Speter char buf[MAXLINE]; 429238032Speter 429338032Speter if (tTd(38, 20)) 429438032Speter printf("prog_map_lookup(%s, %s) %s\n", 429538032Speter map->map_mname, name, map->map_file); 429638032Speter 429738032Speter i = 0; 429838032Speter argv[i++] = map->map_file; 429938032Speter if (map->map_rebuild != NULL) 430038032Speter { 430138032Speter snprintf(buf, sizeof buf, "%s", map->map_rebuild); 430238032Speter for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 430338032Speter { 430438032Speter if (i >= MAXPV - 1) 430538032Speter break; 430638032Speter argv[i++] = p; 430738032Speter } 430838032Speter } 430938032Speter argv[i++] = name; 431038032Speter argv[i] = NULL; 431138032Speter if (tTd(38, 21)) 431238032Speter { 431338032Speter printf("prog_open:"); 431438032Speter for (i = 0; argv[i] != NULL; i++) 431538032Speter printf(" %s", argv[i]); 431638032Speter printf("\n"); 431738032Speter } 431838032Speter (void) blocksignal(SIGCHLD); 431938032Speter pid = prog_open(argv, &fd, CurEnv); 432038032Speter if (pid < 0) 432138032Speter { 432238032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 432338032Speter syserr("prog_map_lookup(%s) failed (%s) -- closing", 432438032Speter map->map_mname, errstring(errno)); 432538032Speter else if (tTd(38, 9)) 432638032Speter printf("prog_map_lookup(%s) failed (%s) -- closing", 432738032Speter map->map_mname, errstring(errno)); 432838032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 432938032Speter *statp = EX_OSFILE; 433038032Speter return NULL; 433138032Speter } 433238032Speter i = read(fd, buf, sizeof buf - 1); 433338032Speter if (i < 0) 433438032Speter { 433538032Speter syserr("prog_map_lookup(%s): read error %s\n", 433638032Speter map->map_mname, errstring(errno)); 433738032Speter rval = NULL; 433838032Speter } 433938032Speter else if (i == 0) 434038032Speter { 434138032Speter if (tTd(38, 20)) 434238032Speter printf("prog_map_lookup(%s): empty answer\n", 434338032Speter map->map_mname); 434438032Speter rval = NULL; 434538032Speter } 434638032Speter else 434738032Speter { 434838032Speter buf[i] = '\0'; 434938032Speter p = strchr(buf, '\n'); 435038032Speter if (p != NULL) 435138032Speter *p = '\0'; 435238032Speter 435338032Speter /* collect the return value */ 435438032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 435538032Speter rval = map_rewrite(map, name, strlen(name), NULL); 435638032Speter else 435738032Speter rval = map_rewrite(map, buf, strlen(buf), NULL); 435838032Speter 435938032Speter /* now flush any additional output */ 436038032Speter while ((i = read(fd, buf, sizeof buf)) > 0) 436138032Speter continue; 436238032Speter } 436338032Speter 436438032Speter /* wait for the process to terminate */ 436538032Speter close(fd); 436638032Speter stat = waitfor(pid); 436738032Speter (void) releasesignal(SIGCHLD); 436838032Speter 436938032Speter if (stat == -1) 437038032Speter { 437138032Speter syserr("prog_map_lookup(%s): wait error %s\n", 437238032Speter map->map_mname, errstring(errno)); 437338032Speter *statp = EX_SOFTWARE; 437438032Speter rval = NULL; 437538032Speter } 437638032Speter else if (WIFEXITED(stat)) 437738032Speter { 437838032Speter if ((*statp = WEXITSTATUS(stat)) != EX_OK) 437938032Speter rval = NULL; 438038032Speter } 438138032Speter else 438238032Speter { 438338032Speter syserr("prog_map_lookup(%s): child died on signal %d", 438438032Speter map->map_mname, stat); 438538032Speter *statp = EX_UNAVAILABLE; 438638032Speter rval = NULL; 438738032Speter } 438838032Speter return rval; 438938032Speter} 439038032Speter/* 439138032Speter** Sequenced map type. 439238032Speter** 439338032Speter** Tries each map in order until something matches, much like 439438032Speter** implicit. Stores go to the first map in the list that can 439538032Speter** support storing. 439638032Speter** 439738032Speter** This is slightly unusual in that there are two interfaces. 439838032Speter** The "sequence" interface lets you stack maps arbitrarily. 439938032Speter** The "switch" interface builds a sequence map by looking 440038032Speter** at a system-dependent configuration file such as 440138032Speter** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 440238032Speter** 440338032Speter** We don't need an explicit open, since all maps are 440438032Speter** opened during startup, including underlying maps. 440538032Speter*/ 440638032Speter 440738032Speter/* 440838032Speter** SEQ_MAP_PARSE -- Sequenced map parsing 440938032Speter*/ 441038032Speter 441138032Speterbool 441238032Speterseq_map_parse(map, ap) 441338032Speter MAP *map; 441438032Speter char *ap; 441538032Speter{ 441638032Speter int maxmap; 441738032Speter 441838032Speter if (tTd(38, 2)) 441938032Speter printf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 442038032Speter maxmap = 0; 442138032Speter while (*ap != '\0') 442238032Speter { 442338032Speter register char *p; 442438032Speter STAB *s; 442538032Speter 442638032Speter /* find beginning of map name */ 442738032Speter while (isascii(*ap) && isspace(*ap)) 442838032Speter ap++; 442938032Speter for (p = ap; isascii(*p) && isalnum(*p); p++) 443038032Speter continue; 443138032Speter if (*p != '\0') 443238032Speter *p++ = '\0'; 443338032Speter while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 443438032Speter p++; 443538032Speter if (*ap == '\0') 443638032Speter { 443738032Speter ap = p; 443838032Speter continue; 443938032Speter } 444038032Speter s = stab(ap, ST_MAP, ST_FIND); 444138032Speter if (s == NULL) 444238032Speter { 444338032Speter syserr("Sequence map %s: unknown member map %s", 444438032Speter map->map_mname, ap); 444538032Speter } 444638032Speter else if (maxmap == MAXMAPSTACK) 444738032Speter { 444838032Speter syserr("Sequence map %s: too many member maps (%d max)", 444938032Speter map->map_mname, MAXMAPSTACK); 445038032Speter maxmap++; 445138032Speter } 445238032Speter else if (maxmap < MAXMAPSTACK) 445338032Speter { 445438032Speter map->map_stack[maxmap++] = &s->s_map; 445538032Speter } 445638032Speter ap = p; 445738032Speter } 445838032Speter return TRUE; 445938032Speter} 446038032Speter 446138032Speter 446238032Speter/* 446338032Speter** SWITCH_MAP_OPEN -- open a switched map 446438032Speter** 446538032Speter** This looks at the system-dependent configuration and builds 446638032Speter** a sequence map that does the same thing. 446738032Speter** 446838032Speter** Every system must define a switch_map_find routine in conf.c 446938032Speter** that will return the list of service types associated with a 447038032Speter** given service class. 447138032Speter*/ 447238032Speter 447338032Speterbool 447438032Speterswitch_map_open(map, mode) 447538032Speter MAP *map; 447638032Speter int mode; 447738032Speter{ 447838032Speter int mapno; 447938032Speter int nmaps; 448038032Speter char *maptype[MAXMAPSTACK]; 448138032Speter 448238032Speter if (tTd(38, 2)) 448338032Speter printf("switch_map_open(%s, %s, %d)\n", 448438032Speter map->map_mname, map->map_file, mode); 448538032Speter 448638032Speter mode &= O_ACCMODE; 448738032Speter nmaps = switch_map_find(map->map_file, maptype, map->map_return); 448838032Speter if (tTd(38, 19)) 448938032Speter { 449038032Speter printf("\tswitch_map_find => %d\n", nmaps); 449138032Speter for (mapno = 0; mapno < nmaps; mapno++) 449238032Speter printf("\t\t%s\n", maptype[mapno]); 449338032Speter } 449438032Speter if (nmaps <= 0 || nmaps > MAXMAPSTACK) 449538032Speter return FALSE; 449638032Speter 449738032Speter for (mapno = 0; mapno < nmaps; mapno++) 449838032Speter { 449938032Speter register STAB *s; 450038032Speter char nbuf[MAXNAME + 1]; 450138032Speter 450238032Speter if (maptype[mapno] == NULL) 450338032Speter continue; 450438032Speter (void) snprintf(nbuf, sizeof nbuf, "%s.%s", 450538032Speter map->map_mname, maptype[mapno]); 450638032Speter s = stab(nbuf, ST_MAP, ST_FIND); 450738032Speter if (s == NULL) 450838032Speter { 450938032Speter syserr("Switch map %s: unknown member map %s", 451038032Speter map->map_mname, nbuf); 451138032Speter } 451238032Speter else 451338032Speter { 451438032Speter map->map_stack[mapno] = &s->s_map; 451538032Speter if (tTd(38, 4)) 451638032Speter printf("\tmap_stack[%d] = %s:%s\n", 451738032Speter mapno, s->s_map.map_class->map_cname, 451838032Speter nbuf); 451938032Speter } 452038032Speter } 452138032Speter return TRUE; 452238032Speter} 452338032Speter 452438032Speter 452538032Speter/* 452638032Speter** SEQ_MAP_CLOSE -- close all underlying maps 452738032Speter*/ 452838032Speter 452938032Spetervoid 453038032Speterseq_map_close(map) 453138032Speter MAP *map; 453238032Speter{ 453338032Speter int mapno; 453438032Speter 453538032Speter if (tTd(38, 9)) 453638032Speter printf("seq_map_close(%s)\n", map->map_mname); 453738032Speter 453838032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 453938032Speter { 454038032Speter MAP *mm = map->map_stack[mapno]; 454138032Speter 454238032Speter if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 454338032Speter continue; 454438032Speter mm->map_class->map_close(mm); 454538032Speter mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 454638032Speter } 454738032Speter} 454838032Speter 454938032Speter 455038032Speter/* 455138032Speter** SEQ_MAP_LOOKUP -- sequenced map lookup 455238032Speter*/ 455338032Speter 455438032Speterchar * 455538032Speterseq_map_lookup(map, key, args, pstat) 455638032Speter MAP *map; 455738032Speter char *key; 455838032Speter char **args; 455938032Speter int *pstat; 456038032Speter{ 456138032Speter int mapno; 456238032Speter int mapbit = 0x01; 456338032Speter bool tempfail = FALSE; 456438032Speter 456538032Speter if (tTd(38, 20)) 456638032Speter printf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 456738032Speter 456838032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 456938032Speter { 457038032Speter MAP *mm = map->map_stack[mapno]; 457138032Speter char *rv; 457238032Speter 457338032Speter if (mm == NULL) 457438032Speter continue; 457538032Speter if (!bitset(MF_OPEN, mm->map_mflags)) 457638032Speter { 457738032Speter if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 457838032Speter { 457938032Speter *pstat = EX_UNAVAILABLE; 458038032Speter return NULL; 458138032Speter } 458238032Speter continue; 458338032Speter } 458438032Speter *pstat = EX_OK; 458538032Speter rv = mm->map_class->map_lookup(mm, key, args, pstat); 458638032Speter if (rv != NULL) 458738032Speter return rv; 458838032Speter if (*pstat == EX_TEMPFAIL) 458938032Speter { 459038032Speter if (bitset(mapbit, map->map_return[MA_TRYAGAIN])) 459138032Speter return NULL; 459238032Speter tempfail = TRUE; 459338032Speter } 459438032Speter else if (bitset(mapbit, map->map_return[MA_NOTFOUND])) 459538032Speter break; 459638032Speter } 459738032Speter if (tempfail) 459838032Speter *pstat = EX_TEMPFAIL; 459938032Speter else if (*pstat == EX_OK) 460038032Speter *pstat = EX_NOTFOUND; 460138032Speter return NULL; 460238032Speter} 460338032Speter 460438032Speter 460538032Speter/* 460638032Speter** SEQ_MAP_STORE -- sequenced map store 460738032Speter*/ 460838032Speter 460938032Spetervoid 461038032Speterseq_map_store(map, key, val) 461138032Speter MAP *map; 461238032Speter char *key; 461338032Speter char *val; 461438032Speter{ 461538032Speter int mapno; 461638032Speter 461738032Speter if (tTd(38, 12)) 461838032Speter printf("seq_map_store(%s, %s, %s)\n", 461938032Speter map->map_mname, key, val); 462038032Speter 462138032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 462238032Speter { 462338032Speter MAP *mm = map->map_stack[mapno]; 462438032Speter 462538032Speter if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 462638032Speter continue; 462738032Speter 462838032Speter mm->map_class->map_store(mm, key, val); 462938032Speter return; 463038032Speter } 463138032Speter syserr("seq_map_store(%s, %s, %s): no writable map", 463238032Speter map->map_mname, key, val); 463338032Speter} 463438032Speter/* 463538032Speter** NULL stubs 463638032Speter*/ 463738032Speter 463838032Speter/* ARGSUSED */ 463938032Speterbool 464038032Speternull_map_open(map, mode) 464138032Speter MAP *map; 464238032Speter int mode; 464338032Speter{ 464438032Speter return TRUE; 464538032Speter} 464638032Speter 464738032Speter/* ARGSUSED */ 464838032Spetervoid 464938032Speternull_map_close(map) 465038032Speter MAP *map; 465138032Speter{ 465238032Speter return; 465338032Speter} 465438032Speter 465538032Speterchar * 465638032Speternull_map_lookup(map, key, args, pstat) 465738032Speter MAP *map; 465838032Speter char *key; 465938032Speter char **args; 466038032Speter int *pstat; 466138032Speter{ 466238032Speter *pstat = EX_NOTFOUND; 466338032Speter return NULL; 466438032Speter} 466538032Speter 466638032Speter/* ARGSUSED */ 466738032Spetervoid 466838032Speternull_map_store(map, key, val) 466938032Speter MAP *map; 467038032Speter char *key; 467138032Speter char *val; 467238032Speter{ 467338032Speter return; 467438032Speter} 467538032Speter 467638032Speter 467738032Speter/* 467838032Speter** BOGUS stubs 467938032Speter*/ 468038032Speter 468138032Speterchar * 468238032Speterbogus_map_lookup(map, key, args, pstat) 468338032Speter MAP *map; 468438032Speter char *key; 468538032Speter char **args; 468638032Speter int *pstat; 468738032Speter{ 468838032Speter *pstat = EX_TEMPFAIL; 468938032Speter return NULL; 469038032Speter} 469138032Speter 469238032SpeterMAPCLASS BogusMapClass = 469338032Speter{ 469438032Speter "bogus-map", NULL, 0, 469538032Speter NULL, bogus_map_lookup, null_map_store, 469638032Speter null_map_open, null_map_close, 469738032Speter}; 469838032Speter/* 469938032Speter** REGEX modules 470038032Speter*/ 470138032Speter 470238032Speter#ifdef MAP_REGEX 470338032Speter 470438032Speter# include <regex.h> 470538032Speter 470638032Speter# define DEFAULT_DELIM CONDELSE 470738032Speter 470838032Speter# define END_OF_FIELDS -1 470938032Speter 471038032Speter# define ERRBUF_SIZE 80 471138032Speter# define MAX_MATCH 32 471238032Speter 471338032Speter# define xnalloc(s) memset(xalloc(s), 0, s); 471438032Speter 471538032Speterstruct regex_map 471638032Speter{ 471738032Speter regex_t pattern_buf; /* xalloc it */ 471838032Speter int *regex_subfields; /* move to type MAP */ 471938032Speter char *delim; /* move to type MAP */ 472038032Speter}; 472138032Speter 472238032Speterstatic int 472338032Speterparse_fields(s, ibuf, blen, nr_substrings) 472438032Speter char *s; 472538032Speter int *ibuf; /* array */ 472638032Speter int blen; /* number of elements in ibuf */ 472738032Speter int nr_substrings; /* number of substrings in the pattern */ 472838032Speter{ 472938032Speter register char *cp; 473038032Speter int i = 0; 473138032Speter bool lastone = FALSE; 473238032Speter 473338032Speter blen--; /* for terminating END_OF_FIELDS */ 473438032Speter cp = s; 473538032Speter do 473638032Speter { 473738032Speter for (;; cp++) 473838032Speter { 473938032Speter if (*cp == ',') 474038032Speter { 474138032Speter *cp = '\0'; 474238032Speter break; 474338032Speter } 474438032Speter if (*cp == '\0') 474538032Speter { 474638032Speter lastone = TRUE; 474738032Speter break; 474838032Speter } 474938032Speter } 475038032Speter if (i < blen) 475138032Speter { 475238032Speter int val = atoi(s); 475338032Speter 475438032Speter if (val < 0 || val >= nr_substrings) 475538032Speter { 475638032Speter syserr("field (%d) out of range, only %d substrings in pattern", 475738032Speter val, nr_substrings); 475838032Speter return -1; 475938032Speter } 476038032Speter ibuf[i++] = val; 476138032Speter } 476238032Speter else 476338032Speter { 476438032Speter syserr("too many fields, %d max\n", blen); 476538032Speter return -1; 476638032Speter } 476738032Speter s = ++cp; 476838032Speter } while (!lastone); 476938032Speter ibuf[i] = END_OF_FIELDS; 477038032Speter return i; 477138032Speter} 477238032Speter 477338032Speterbool 477438032Speterregex_map_init(map, ap) 477538032Speter MAP *map; 477638032Speter char *ap; 477738032Speter{ 477838032Speter int regerr; 477938032Speter struct regex_map *map_p; 478038032Speter register char *p; 478138032Speter char *sub_param = NULL; 478238032Speter int pflags; 478338032Speter static char defdstr[] = { (char)DEFAULT_DELIM, '\0' }; 478438032Speter 478538032Speter if (tTd(38, 2)) 478638032Speter printf("regex_map_init: mapname '%s', args '%s'\n", 478738032Speter map->map_mname, ap); 478838032Speter 478938032Speter pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; 479038032Speter 479138032Speter p = ap; 479238032Speter 479338032Speter map_p = (struct regex_map *) xnalloc(sizeof(struct regex_map)); 479438032Speter 479538032Speter for (;;) 479638032Speter { 479738032Speter while (isascii(*p) && isspace(*p)) 479838032Speter p++; 479938032Speter if (*p != '-') 480038032Speter break; 480138032Speter switch (*++p) 480238032Speter { 480338032Speter case 'n': /* not */ 480438032Speter map->map_mflags |= MF_REGEX_NOT; 480538032Speter break; 480638032Speter 480738032Speter case 'f': /* case sensitive */ 480838032Speter map->map_mflags |= MF_NOFOLDCASE; 480938032Speter pflags &= ~REG_ICASE; 481038032Speter break; 481138032Speter 481238032Speter case 'b': /* basic regular expressions */ 481338032Speter pflags &= ~REG_EXTENDED; 481438032Speter break; 481538032Speter 481638032Speter case 's': /* substring match () syntax */ 481738032Speter sub_param = ++p; 481838032Speter pflags &= ~REG_NOSUB; 481938032Speter break; 482038032Speter 482138032Speter case 'd': /* delimiter */ 482238032Speter map_p->delim = ++p; 482338032Speter break; 482438032Speter 482538032Speter case 'a': /* map append */ 482638032Speter map->map_app = ++p; 482738032Speter break; 482838032Speter 482938032Speter case 'm': /* matchonly */ 483038032Speter map->map_mflags |= MF_MATCHONLY; 483138032Speter break; 483238032Speter 483338032Speter } 483438032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 483538032Speter p++; 483638032Speter if (*p != '\0') 483738032Speter *p++ = '\0'; 483838032Speter } 483938032Speter if (tTd(38, 3)) 484038032Speter printf("regex_map_init: compile '%s' 0x%x\n", p, pflags); 484138032Speter 484238032Speter if ((regerr = regcomp(&(map_p->pattern_buf), p, pflags)) != 0) 484338032Speter { 484438032Speter /* Errorhandling */ 484538032Speter char errbuf[ERRBUF_SIZE]; 484638032Speter 484738032Speter regerror(regerr, &(map_p->pattern_buf), errbuf, ERRBUF_SIZE); 484838032Speter syserr("pattern-compile-error: %s\n", errbuf); 484938032Speter free(map_p); 485038032Speter return FALSE; 485138032Speter } 485238032Speter 485338032Speter if (map->map_app != NULL) 485438032Speter map->map_app = newstr(map->map_app); 485538032Speter if (map_p->delim != NULL) 485638032Speter map_p->delim = newstr(map_p->delim); 485738032Speter else 485838032Speter map_p->delim = defdstr; 485938032Speter 486038032Speter if (!bitset(REG_NOSUB, pflags)) 486138032Speter { 486238032Speter /* substring matching */ 486338032Speter int substrings; 486438032Speter int *fields = (int *)xalloc(sizeof(int) * (MAX_MATCH + 1)); 486538032Speter 486638032Speter substrings = map_p->pattern_buf.re_nsub + 1; 486738032Speter 486838032Speter if (tTd(38, 3)) 486938032Speter printf("regex_map_init: nr of substrings %d\n", substrings); 487038032Speter 487138032Speter if (substrings >= MAX_MATCH) 487238032Speter { 487338032Speter syserr("too many substrings, %d max\n", MAX_MATCH); 487438032Speter free(map_p); 487538032Speter return FALSE; 487638032Speter } 487738032Speter if (sub_param != NULL && sub_param[0] != '\0') 487838032Speter { 487938032Speter /* optional parameter -sfields */ 488038032Speter if (parse_fields(sub_param, fields, 488138032Speter MAX_MATCH + 1, substrings) == -1) 488238032Speter return FALSE; 488338032Speter } 488438032Speter else 488538032Speter { 488638032Speter /* set default fields */ 488738032Speter int i; 488838032Speter 488938032Speter for (i = 0; i < substrings; i++) 489038032Speter fields[i] = i; 489138032Speter fields[i] = END_OF_FIELDS; 489238032Speter } 489338032Speter map_p->regex_subfields = fields; 489438032Speter if (tTd(38, 3)) 489538032Speter { 489638032Speter int *ip; 489738032Speter 489838032Speter printf("regex_map_init: subfields"); 489938032Speter for (ip = fields; *ip != END_OF_FIELDS; ip++) 490038032Speter printf(" %d", *ip); 490138032Speter printf("\n"); 490238032Speter } 490338032Speter } 490438032Speter map->map_db1 = (ARBPTR_T)map_p; /* dirty hack */ 490538032Speter 490638032Speter return TRUE; 490738032Speter} 490838032Speter 490938032Speterstatic char * 491038032Speterregex_map_rewrite(map, s, slen, av) 491138032Speter MAP *map; 491238032Speter const char *s; 491338032Speter size_t slen; 491438032Speter char **av; 491538032Speter{ 491638032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 491738032Speter return map_rewrite(map, av[0], strlen(av[0]), NULL); 491838032Speter else 491938032Speter return map_rewrite(map, s, slen, NULL); 492038032Speter} 492138032Speter 492238032Speterchar * 492338032Speterregex_map_lookup(map, name, av, statp) 492438032Speter MAP *map; 492538032Speter char *name; 492638032Speter char **av; 492738032Speter int *statp; 492838032Speter{ 492938032Speter int reg_res; 493038032Speter struct regex_map *map_p; 493138032Speter regmatch_t pmatch[MAX_MATCH]; 493238032Speter 493338032Speter if (tTd(38, 20)) 493438032Speter { 493538032Speter char **cpp; 493638032Speter 493738032Speter printf("regex_map_lookup: key '%s'\n", name); 493838032Speter for (cpp = av; cpp && *cpp; cpp++) 493938032Speter printf("regex_map_lookup: arg '%s'\n", *cpp); 494038032Speter } 494138032Speter 494238032Speter map_p = (struct regex_map *)(map->map_db1); 494338032Speter reg_res = regexec(&(map_p->pattern_buf), name, MAX_MATCH, pmatch, 0); 494438032Speter 494538032Speter if (bitset(MF_REGEX_NOT, map->map_mflags)) 494638032Speter { 494738032Speter /* option -n */ 494838032Speter if (reg_res == REG_NOMATCH) 494938032Speter return regex_map_rewrite(map, "", (size_t)0, av); 495038032Speter else 495138032Speter return NULL; 495238032Speter } 495338032Speter if (reg_res == REG_NOMATCH) 495438032Speter return NULL; 495538032Speter 495638032Speter if (map_p->regex_subfields != NULL) 495738032Speter { 495838032Speter /* option -s */ 495938032Speter static char retbuf[MAXNAME]; 496038032Speter int fields[MAX_MATCH + 1]; 496138032Speter bool first = TRUE; 496238032Speter int anglecnt = 0, cmntcnt = 0, spacecnt = 0; 496338032Speter bool quotemode = FALSE, bslashmode = FALSE; 496438032Speter register char *dp, *sp; 496538032Speter char *endp, *ldp; 496638032Speter int *ip; 496738032Speter 496838032Speter dp = retbuf; 496938032Speter ldp = retbuf + sizeof(retbuf) - 1; 497038032Speter 497138032Speter if (av[1] != NULL) 497238032Speter { 497338032Speter if (parse_fields(av[1], fields, MAX_MATCH + 1, 497438032Speter (int) map_p->pattern_buf.re_nsub + 1) == -1) 497538032Speter { 497638032Speter *statp = EX_CONFIG; 497738032Speter return NULL; 497838032Speter } 497938032Speter ip = fields; 498038032Speter } 498138032Speter else 498238032Speter ip = map_p->regex_subfields; 498338032Speter 498438032Speter for ( ; *ip != END_OF_FIELDS; ip++) 498538032Speter { 498638032Speter if (!first) 498738032Speter { 498838032Speter for (sp = map_p->delim; *sp; sp++) 498938032Speter { 499038032Speter if (dp < ldp) 499138032Speter *dp++ = *sp; 499238032Speter } 499338032Speter } 499438032Speter else 499538032Speter first = FALSE; 499638032Speter 499738032Speter 499838032Speter if (pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) 499938032Speter continue; 500038032Speter 500138032Speter sp = name + pmatch[*ip].rm_so; 500238032Speter endp = name + pmatch[*ip].rm_eo; 500338032Speter for (; endp > sp; sp++) 500438032Speter { 500538032Speter if (dp < ldp) 500638032Speter { 500738032Speter if(bslashmode) 500838032Speter { 500938032Speter *dp++ = *sp; 501038032Speter bslashmode = FALSE; 501138032Speter } 501238032Speter else if(quotemode && *sp != '"' && 501338032Speter *sp != '\\') 501438032Speter { 501538032Speter *dp++ = *sp; 501638032Speter } 501738032Speter else switch(*dp++ = *sp) 501838032Speter { 501938032Speter case '\\': 502038032Speter bslashmode = TRUE; 502138032Speter break; 502238032Speter 502338032Speter case '(': 502438032Speter cmntcnt++; 502538032Speter break; 502638032Speter 502738032Speter case ')': 502838032Speter cmntcnt--; 502938032Speter break; 503038032Speter 503138032Speter case '<': 503238032Speter anglecnt++; 503338032Speter break; 503438032Speter 503538032Speter case '>': 503638032Speter anglecnt--; 503738032Speter break; 503838032Speter 503938032Speter case ' ': 504038032Speter spacecnt++; 504138032Speter break; 504238032Speter 504338032Speter case '"': 504438032Speter quotemode = !quotemode; 504538032Speter break; 504638032Speter } 504738032Speter } 504838032Speter } 504938032Speter } 505038032Speter if (anglecnt != 0 || cmntcnt != 0 || quotemode || 505138032Speter bslashmode || spacecnt != 0) 505238032Speter { 505338032Speter sm_syslog(LOG_WARNING, NOQID, 505438032Speter "Warning: regex may cause prescan() failure map=%s lookup=%s", 505538032Speter map->map_mname, name); 505638032Speter return NULL; 505738032Speter } 505838032Speter 505938032Speter *dp = '\0'; 506038032Speter 506138032Speter return regex_map_rewrite(map, retbuf, strlen(retbuf), av); 506238032Speter } 506338032Speter return regex_map_rewrite(map, "", (size_t)0, av); 506438032Speter} 506538032Speter#endif /* MAP_REGEX */ 5066